fsm_core

Finite state machine toolkit for PostgreSQL

Overview

PackageVersionCategoryLicenseLanguage
fsm_core1.1.0FEATApache-2.0SQL
IDExtensionBinLibLoadCreateTrustRelocSchema
2690fsm_coreNoNoNoYesNoNofsm_core
Relatedltree pgmq pg_jsonschema pgmq pg_jsonschema pg_task pg_later pg_cron

PG15+; requires ltree, pgmq, and pg_jsonschema

Version

TypeRepoVersionPG VerPackageDeps
EXTPIGSTY1.1.01817161514fsm_coreltree, pgmq, pg_jsonschema
RPMPIGSTY1.1.01817161514fsm_core_$vpgmq_$v
DEBPIGSTY1.1.01817161514postgresql-$v-fsm-corepostgresql-$v-pgmq, postgresql-$v-pg-jsonschema
OS / PGPG18PG17PG16PG15PG14
el8.x86_64PIGSTY MISS
el8.aarch64PIGSTY MISS
el9.x86_64PIGSTY MISS
el9.aarch64PIGSTY MISS
el10.x86_64PIGSTY MISS
el10.aarch64PIGSTY MISS
d12.x86_64PIGSTY MISS
d12.aarch64
PIGSTY 1.1.0
PIGSTY 1.1.0
PIGSTY 1.1.0
PIGSTY 1.1.0
PIGSTY MISS
d13.x86_64
PIGSTY 1.1.0
PIGSTY 1.1.0
PIGSTY 1.1.0
PIGSTY 1.1.0
PIGSTY MISS
d13.aarch64
PIGSTY 1.1.0
PIGSTY 1.1.0
PIGSTY 1.1.0
PIGSTY 1.1.0
PIGSTY MISS
u22.x86_64
PIGSTY 1.1.0
PIGSTY 1.1.0
PIGSTY 1.1.0
PIGSTY 1.1.0
PIGSTY MISS
u22.aarch64
PIGSTY 1.1.0
PIGSTY 1.1.0
PIGSTY 1.1.0
PIGSTY 1.1.0
PIGSTY MISS
u24.x86_64
PIGSTY 1.1.0
PIGSTY 1.1.0
PIGSTY 1.1.0
PIGSTY 1.1.0
PIGSTY MISS
u24.aarch64
PIGSTY 1.1.0
PIGSTY 1.1.0
PIGSTY 1.1.0
PIGSTY 1.1.0
PIGSTY MISS
u26.x86_64PIGSTY MISS
u26.aarch64
PIGSTY 1.1.0
PIGSTY 1.1.0
PIGSTY 1.1.0
PIGSTY 1.1.0
PIGSTY MISS

Build

You can build the RPM / DEB packages for fsm_core using pig build:

pig build pkg fsm_core         # build RPM / DEB packages

Install

You can install fsm_core directly. First, make sure the PGDG and PIGSTY repositories are added and enabled:

pig repo add pgsql -u          # Add repo and update cache

Install the extension using pig or apt/yum/dnf:

pig install fsm_core;          # Install for current active PG version
pig ext install -y fsm_core -v 18  # PG 18
pig ext install -y fsm_core -v 17  # PG 17
pig ext install -y fsm_core -v 16  # PG 16
pig ext install -y fsm_core -v 15  # PG 15
dnf install -y fsm_core_18       # PG 18
dnf install -y fsm_core_17       # PG 17
dnf install -y fsm_core_16       # PG 16
dnf install -y fsm_core_15       # PG 15
apt install -y postgresql-18-fsm-core   # PG 18
apt install -y postgresql-17-fsm-core   # PG 17
apt install -y postgresql-16-fsm-core   # PG 16
apt install -y postgresql-15-fsm-core   # PG 15

Create Extension:

CREATE EXTENSION fsm_core CASCADE;  -- requires: ltree, pgmq, pg_jsonschema

Source: fsm_core PGXN README, control file, 1.1.0 SQL definition, example definitions README.

Usage

fsm_core is a finite-state-machine toolkit that stores FSM definitions, instances, transitions, queue events, and event logs inside PostgreSQL. A machine definition is loaded from JSON, instances are created by name and version, and events are sent through SQL functions with optional pgmq queues.

The extension is PG15+ in the local catalog. The control file requires ltree and pgmq; the upstream README also lists pg_jsonschema as a requirement, and the Pigsty package dependency includes postgresql-$v-pg-jsonschema.

Core Tables and Types

fsm_core creates an enum fsm_state_type with atomic, compound, parallel, final, and history, plus tables including:

  • fsm_core.fsm_json for loaded FSM definitions.
  • fsm_core.fsm_states for expanded state nodes and ltree paths.
  • fsm_core.fsm_transitions for transition rules.
  • fsm_core.fsm_instance for running instances.
  • fsm_core.fsm_instance_lock for advisory/concurrency state.
  • fsm_core.fsm_instance_queue_event_logs and fsm_core.fsm_promise_queue_event_logs for queued event history.

Load a Machine Definition

SELECT fsm_core.load_fsm_from_json_v2(
  json_input        := :'fsm_json'::jsonb,
  root_node_text    := 'root',
  input_fsm_type    := 'workflow',
  input_fsm_name    := 'creditCheck',
  input_fsm_version := 'v01'
);

load_fsm_from_json_v2() validates the JSON against fsm_core.fsm_json_schema(), caches the raw definition in fsm_json, then expands states and transitions. Upstream examples keep immutable version folders such as fsm/creditCheck/v01/xstate-fsm.json and fsm/creditCheck/v02/xstate-fsm.json; keep deployed versions immutable so existing instances continue against their original definition.

Create an Instance

SELECT fsm_core.create_fsm_instance_from_name_v2(
  input_fsm_name     := 'creditCheck',
  input_fsm_version  := 'v01',
  input_fsm_context  := '{"applicant_id":"a-42"}'::jsonb,
  create_pgmq_queue  := true
);

The function checks that the named FSM exists, inserts an fsm_instance, copies transition authorization rows for that instance, and, when create_pgmq_queue is true, creates a pgmq queue named by the instance UUID and sends initialTransition_event.

The returned JSON includes queue_created, fsm_name, fsm_version, fsm_instance_id, fsm_instance_context, send_event_result, message, and extra_message.

Send Events

SELECT fsm_core.send_event_to_fsm_queue_with_event_logs_v2(
  input_fsm_instance_id                 := '00000000-0000-0000-0000-000000000000'::uuid,
  input_fsm_instance_id_fsm_type         := 'workflow',
  input_fsm_instance_id_fsm_version      := 'v01',
  input_send_to_parent_queue_id          := fsm_core.pg_system_queue_uuid(),
  input_send_to_parent_queue_type        := fsm_core.pg_system_queue_type(),
  input_send_to_parent_queue_id_event_name := fsm_core.pg_system_event_name(),
  input_event_name                       := 'APPROVE',
  input_event_action_type                := 'user',
  input_event_data                       := '{"approved_by":"manager"}'::jsonb,
  input_event_delay                      := 0
);

This helper writes to the instance queue with pgmq.send() and records the event in fsm_instance_queue_event_logs. For nested FSM and promise flows, send_event_to_queue_from_fsm_instance_id_v2() dispatches to the child-FSM or promise queue helper based on fsmtype.

Resolve and Step State

SELECT fsm_core.resolve_state_value_v2(
  input_json        := '{"value":"pending"}'::jsonb,
  input_fsm_name    := 'creditCheck',
  input_fsm_version := 'v01'
);

SELECT fsm_core.macrostep_v2(
  event_name        := 'APPROVE',
  input_state_value := ARRAY['pending']::text[],
  fsm_name_param    := 'creditCheck',
  fsm_version_param := 'v01'
);

The SQL surface also includes lower-level microstep_v2(), fsm_worker_v2(), lock helpers, archive helpers, and v1 compatibility functions. Prefer v2 entry points for new usage when both versions are present.

Dependency and Source Caveats

  • Enable ltree and pgmq before fsm_core; account for pg_jsonschema because upstream requirements and Pigsty package dependencies list it.
  • pgmq queues are part of the async execution model, so queue names and retention should be operated like application data.
  • The upstream repo has no release tag for 1.1.0; the authoritative packaged source for this stub is the packages/database-src/pgxn-dist SQL/control set plus the PGXN README.
  • Public docs are sparse compared with the SQL surface. Treat unlisted helper functions as internal unless the SQL definition or example app demonstrates their role.