Skip to content

πŸ—ΊοΈ Library Overview

dagpipe is a small execution framework that propagates immutable State objects through Node units connected in a directed acyclic graph (DAG). It is designed for deterministic, observable, and resumable data-processing pipelines.


πŸ—οΈ Architecture

At runtime a pipeline is made of four cooperating layers:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                       YAML (optional)                       β”‚
β”‚     schema Β· initial Β· nodes Β· graph  β†’  load_pipeline()    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚               Graph (execution topology)                    β”‚
β”‚   roots Β· add_edge(child) Β· children() Β· parents()          β”‚
β”‚   acyclic β€” validated on every mutation                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚               Engine (orchestration)                        β”‚
β”‚   run / run_async / run_steps / run_steps_async             β”‚
β”‚   mode: linear sequence  OR  graph BFS                      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚       State Β· Payload Β· Schema (data plane)                 β”‚
β”‚   immutable State Β· fork() Β· dot-path payload Β· validation  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  • Node β€” a pure unit of work. Each node consumes one State and yields zero, one, or many derived State objects.
  • Graph β€” the execution topology. It only stores connectivity; it never executes anything.
  • Engine β€” the orchestrator. It accepts either a linear Sequence[Node] or a Graph and produces terminal states.
  • State / Payload / Schema β€” the immutable data plane. Nodes read a State, fork new ones, and let the Schema guarantee shape.

πŸ”„ Lifecycle of a run

Step Who What happens
1 You Define Node subclasses and a State subclass bound to a Schema.
2 You Build a Graph (order + add_edge) or a linear Sequence[Node].
3 You Construct Engine(nodes_or_graph).
4 You Create a root State (MyState(payload=Payload(...))) β€” validated here.
5 Engine Executes roots first, then fans State out along edges (graph mode) or feeds each sequence element (linear mode).
6 Engine Collects terminal states β€” states from nodes with no children (or the last step in linear mode).

Nodes that yield no states prune the branch β€” see use case 02.


βš–οΈ Which execution model should you use?

Model Construct Use when Runs
Linear Engine([a, b, c]) A fixed pipeline of steps, no branches run
Graph Engine(Graph) Branching, merging, multiple roots run
Async Engine + AsyncNode subclasses I/O-bound steps (HTTP, DB, files) run_async
Steps Engine.run_steps(...) Progress bars, resume-after-interrupt run_steps

A linear sequence is equivalent to a chain graph: each step receives every state its predecessor produced. Graph mode gives you explicit fan-out and fan-in.