Adds the run lifecycle and the stepper loop - #12
Merged
Conversation
Plans sp-4an.2.1 in five phases: ADR-0004 recording the lifecycle contract, run records on the adapter behaviour and guarded facade, the executor seam with the happy-path loop, failure semantics (error.communication re-entry per st-ADR-0051, budget exhaustion, fail/4), and the pluggable per-run serialization strategy with the adapter lock default. Docs only; the quality gate does not apply to this diff. Refs: sp-4an.2.1
Phase 1 of the sp-4an.2.1 plan. Six decisions: the run record owns its current position; opaque caller-supplied run keys and total statuses; the loop order as contract with at-least-once semantics; the executor seam over the core effect vocabulary with uniform error.communication re-entry (st-ADR-0051); pluggable per-run serialization with the adapter lock default; chart-driven completion. Indexes the record and checks off the phase. Docs only; the quality gate does not apply to this diff. Refs: sp-4an.2.1
Phase 2 of the sp-4an.2.1 plan, encoding ADR-0004 decisions 1-2. The adapter behaviour gains insert_run/2, fetch_run/2, and update_run/2 over an opaque run_record (nullable position_blob), with :run_exists and :run_not_found arms; InMemory implements them with the exists-check atomic with the write. The facade adds insert_run/5, update_run/5, fetch_run/2, and the identity-guarded load_run_position/3 with the :run_position_missing arm; position: :skip carries the stored blob forward on update. The conformance suite covers the new callbacks so downstream adapters inherit the checks. Refs: sp-4an.2.1
Phase 3 of the sp-4an.2.1 plan, encoding ADR-0004 decisions 3, 4,
and 6. Runs.create/4 initializes a chart into a durable run;
Runs.step/5 drives the loop in the contract order: liveness check
on the run record before any decode, guarded load, unconditional
routes/invoke_types re-stamp behind the st-ADR-0064 nil tripwire,
handle_event, effects to the Executor seam in list order (:done
and :budget_exhausted consumed by the lifecycle), quiescence
assertion, persist. Terminal delivery discards with a typed
{:discarded, run}; the Executor behaviour accepts a module or an
arity-2 fun. Executor failures are collected without re-entry and
budget exhaustion is handled minimally; Phase 4 owns both.
Refs: sp-4an.2.1
Phase 4 of the sp-4an.2.1 plan, completing ADR-0004 decisions 3, 4, and 6. Executor failures on actionable effects re-enter the chart as error.communication through Interpreter.deliver_internal (st-ADR-0051's failed-communication row; this package never mints error.execution), single-wave per step, with origins reusing upstream's own Cause.origin arms. Budget exhaustion persists a :failed run with the prior blob intact and returns a typed error. Runs.fail/3,4 records host abandonment via the new blob-preserving Storage.update_run_status/4. The at-least-once contract gains its proof: a failed persist re-drives the same event and re-emits effects with identical deterministic keys. Refs: sp-4an.2.1
Phase 5 of the sp-4an.2.1 plan, encoding ADR-0004 decision 5. The Serialization behaviour carries the ordering guarantee (with_run/3 bodies for one run id never overlap); the lifecycle runs every fetch-to-persist tail inside it. The default AdapterLock strategy delegates to the new optional lock_run/3 adapter callback - recorded as a dated ADR-0003 amendment - which InMemory implements with a token-checked per-run lock released on any exit. The conformance suite checks no-overlap and release-after-raise when an adapter exports the callback; a job-queue strategy can swap in later with no loop change. Refs: sp-4an.2.1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Hosts running charts that span days or survive deploys currently hand-roll
the load -> step -> execute -> persist loop, the storage guard, and the
crash semantics. This branch ships that loop as the library: the run
lifecycle (sp-4an.2's charter scope bullets 2 and 3), on top of the
sp-4an.1 storage substrate.
What
Five phases, one commit each, recorded up front as ADR-0004:
insert_run/2,fetch_run/2,update_run/2adapter callbacks over an opaquerun_record(nullableposition_blob), the identity-guarded facade functions, and conformancecoverage downstream adapters inherit.
Runs.create/4andRuns.step/5in the contract order -liveness check before any decode, guarded load, unconditional
routes/invoke_types re-stamp behind the st-ADR-0064 nil tripwire, step,
effects to the
Executorseam in list order (:done/:budget_exhaustedconsumed by the lifecycle), quiescence assertion,persist. Terminal delivery is a typed
{:discarded, run}.error.communicationviaInterpreter.deliver_internal/5(single-wave;this package never mints
error.execution- st-ADR-0051's table),budget exhaustion persists a
:failedrun with the prior blob intact,Runs.fail/3,4records host abandonment, and the at-least-once contracthas an executable proof (injected persist failure re-drives the same
event with identical deterministic effect keys).
Serializationbehaviour(
with_run/3), theAdapterLockdefault over the new optionallock_run/3adapter callback (ADR-0003 amended), InMemory'stoken-checked per-run lock, and concurrency tests that distinguish
serial orders from lost-update interleavings.
Notes
mix qualitygreen on every commit and after the rebase: 61 tests,94.1% coverage (floor 90), dialyzer clean. Doctor/Gettext/Sobelow are
not installed in this project (standing configuration, not this branch).
merges this branch has no
gate.attestline, somix gate.verifywasrun directly alongside the manifest gate - green.
line was corrected on the bead: st-ADR-0051 classifies a registered
handler failing to reach its service as
error.communication, andplanning-time
error.executionnever reaches the executor seam. Thecode follows upstream's record.
:cancel/:cancel_invoke/:autoforwardhaveno upstream failed-communication precedent; they reuse existing
Cause.origin()arms matching each effect's own identity fields(documented in the code) - worth a second opinion.
at the bottom of
docs/plans/260822-sp-4an.2.1-run-lifecycle-executor-seam-stepper.md.Closes sp-4an.2.1