Skip to content

Computation Graph

A Computation Graph is an in-process, deterministic, event-driven DAG. Unlike a Workflow (where the task is the unit and state is persisted), a computation graph runs as a single traversal in memory, in response to an event. It is built from Nodes and is fired either by a Reactor or invoked directly from a workflow task.

  • A graph is a set of nodes wired by a topology (a -> b).
  • Entry nodes read named sources from an InputCache; processing nodes take their upstream node’s output; the terminal node (no downstream) produces the result.
  • It compiles to a callable function (<name>_compiled in Rust) that the reactor invokes; the Boundary events an Accumulator emits are what populate the cache.

A two-node pricing graph triggered by a reactor:

The #[computation_graph] macro declares the topology and generates the compiled function; each pub async fn in the module is a node:

#[cloacina_macros::computation_graph(
trigger = reactor("pricing_reactor"),
graph = {
ingest(orderbook) -> format_output,
}
)]
pub mod pricing {
use super::*;
pub async fn ingest(orderbook: Option<&OrderBookSnapshot>) -> SpreadSignal { /* ... */ }
pub async fn format_output(input: &SpreadSignal) -> FormattedOutput { /* ... */ }
}
// generates pricing_compiled(&InputCache) -> GraphResult
  • Reactor-triggered or trigger-less. A graph either subscribes to a reactor (trigger = reactor("…")) or is trigger-less and invoked inline from a workflow task.
  • Data is serialized. Values that cross node boundaries implement Serialize/Deserialize; the cache stores bytes.
  • Deterministic. Given the same cache, the traversal is deterministic.