dagGraphType is the built-in dependency-graph form. A pipeline is one use of
that form: each stage is a node, and each edge says which stage must finish
before another can start.
The graph form only works with frozen data. It folds recorded events into state
and decides what runs next. createGraphExecutor stores each dispatch before it
runs the matching stage.
Run the example
From an Obversa checkout, run:examples/packages/pipeline.ts.
Define a pipeline
graph.definition with its resolved plan. It gives the
executor one data function for each node. The review function reads the draft
result, and the publish function reads the review result.
Restart and resume
If the executor process stops after it records a stage dispatch and before that stage completes, a new executor over the same store returnswaiting with that
stage’s position. Call resume with that position after the old process has
stopped.
Resume does not write a second dispatch event. Completed earlier stages stay
complete. The pipeline then continues from that stage.
The executor does not lock the run. Do not call resume while the previous
executor still runs.
This example pipeline sets globalConcurrency to 1, so at most one stage is in
flight and waiting.positions has one entry.
Node behaviour
- Required nodes block their dependants after failure and fail the pipeline after finalizers run.
- Optional nodes can fail without blocking their dependants.
- Expected skips use a completed result with
skipped: trueand do not block dependants. - Finalizer nodes have no edges and run after the other nodes settle.
- Paused nodes stop new dispatches and keep the recorded pause reason.
lane object uses the engine route stored in the plan. A node
without one uses its data function and is data-only.
Nodes can share a lane id when every copy of its declaration is identical; a
conflicting declaration is rejected. A failed finalizer fails the graph even
when every worker completed successfully.
stopOnError: true stops new work after a required failure. Set it to false
when independent branches and declared retries must continue.
Limits and output
globalConcurrency caps all running nodes. A node with a non-null key also
uses the matching cap in keyedConcurrency.
Each dispatch receives a stable position such as dag/review/1. Its input has
the completed results of its direct predecessors, keyed by node name. The final
output maps every completed node name to its returned payload. A failed optional
node is omitted because it has no completed payload. The example’s plan declares
exactly three dispatches and a maximum concurrency of one.