Modules
Durable FSM engine on top of Postgres + GenServer.
The context handed to GenDurable.FSM.step/2 and GenDurable.FSM.handle/2.
Runs one picked instance to a committed outcome (spec §3/§4).
Behaviour for a durable FSM definition.
Library-owned schema migration (Oban-style).
The five step/handle outcomes from the spec §3, with shape validation.
Every database statement from spec §10, one function each, as raw SQL.
Periodically returns executing rows with an expired lease to runnable,
bumping attempt (spec §4.3 / §10). This is the at-least-once safety floor for
worker crashes; handle/2 is intentionally not involved.
Resolves {fsm_name, fsm_version} to an FSM module.
Per-queue picker loop (spec §6). Demand-driven: each poll picks at most the number of free concurrency slots and runs each instance in a supervised Task. Also heartbeats the leases of in-flight instances (one batched UPDATE per tick, regardless of concurrency).
Typed FSM state: an Ecto embedded schema per FSM, encoded to/from jsonb.
Top-level engine supervisor. Started by the host (Oban-style) as
{GenDurable, opts} in their own supervision tree.