GenDurable.Executor (gen_durable v0.2.10)

Copy Markdown View Source

Runs one picked instance to a committed outcome.

Resolves the FSM module, loads the jsonb state into the FSM's struct, and calls step/2 under try. The signal-inbox and children snapshots ride in the job itself — batch-loaded by the pick, not fetched per step. A raised exception routes to handle/2, and so does an uncaught throw (as {:throw, value}); if handle/2 itself raises, the instance fails. A worker crash (a bare exit, a kill — no return at all) is not handled here — it is the reaper's job, the at-least-once safety floor.

Inline execution (run-ahead): an inline_execution: FSM's :next runs the next step in THIS task on the same claim instead of requeuing — a guarded continue_next commit (keeps the row executing; durability unchanged) then an out-of-band Limiter.admit for the next step's tokens; denied ⇒ the row requeues and the picker admits it. The chained step gets a fresh inbox/children snapshot (re-enriched per step), so its ctx matches what a re-pick would hand it. Disabled when run/3's sched is nil (the Testing.drain/1 path).

Signal consumption: a step sees the awaited subset as ctx.awaited (only the signals whose name is in the set it parked on) and the whole inbox as ctx.all. On a progressing outcome the engine deletes exactly the ctx.awaited ids the step received — latecomers and never-awaited signals survive; a terminal outcome clears the whole inbox (cleanup); :retry/:await delete nothing. Deletion happens in SQL, by id.

Outcomes commit only while this worker still owns the claim (locked_by + status = 'executing' guard in every complete_*): an orphaned task whose lease expired and whose row was reclaimed gets its late outcome dropped — observable as [:gen_durable, :outcome, :stale] — and the current claimant redoes the step (at-least-once).

Summary

Functions

Execute job (a map returned by Queries.pick/5). config is %{repo: ...}. Returns the last committed outcome tuple in its serialized (DB-ready) form.

Functions

run(config, job)

Execute job (a map returned by Queries.pick/5). config is %{repo: ...}. Returns the last committed outcome tuple in its serialized (DB-ready) form.

sched is the scheduler pid (for the inline-continuation slot handoff); nil — the Testing.drain/1 path — disables inline chaining, so each run/2 commits exactly one step, as before.

run(config, job, sched)