async_nodes/lib.rs
1//! `async-nodes` is a generic, type-safe execution engine implementing the Bulk
2//! Synchronous Parallel (BSP) standard for **control-flow graphs with loops**, with the
3//! classic dataflow-once pipelines expressed as a profile on the same core.
4//!
5//! # One core, two faces
6//!
7//! The engine core is control-flow with BSP superstep parallelism: nodes are
8//! re-executable units over a consumer-owned state `S`, edges are *data* carrying
9//! declarative [`Condition`]s, and activation is token-based (Kahn-style firing), which
10//! makes loops first-class topology — a back-edge simply delivers another token.
11//!
12//! A **dataflow DAG is a control-flow graph in which each node fires exactly once, when
13//! all its inputs are ready.** That profile (pins, links, `#[node]` macros, `BspSkip`
14//! propagation, static inputs) keeps its guarantees — static analyzability, trivial
15//! scheduling, no infinite loops by construction — without being a second engine.
16//!
17//! # The moving parts
18//!
19//! - [`BspGraph`] — the blueprint: nodes, [`graph::Edge`]s, static inputs, and the
20//! consumer's named-condition / merger registries. Author graphs with the fluent
21//! builder; exchange them as [`def::GraphDef`] JSON.
22//! - [`BspEngine`] — the scheduler: frontier supersteps under `buffer_unordered`, bounded
23//! by `max_concurrency`; circuit breakers (`max_steps`, per-edge `max_iterations`,
24//! per-node `max_executions`, per-edge token caps); recovery policies; suspension.
25//! - [`BspNode`] — the consumer's computation unit, generic over the consumer state `S`.
26//! - [`NodeRegistry`] — node factories + named conditions + mergers, making graphs
27//! instantiable from JSON.
28//! - [`BspInterceptor`] — the live event stream (supersteps, edges taken, loop
29//! iterations, retries, suspensions) a GUI subscribes to.
30//!
31//! # A loop, briefly
32//!
33//! ```text
34//! entry ──▶ Generate ──[has_more]──▶ Tools ──[always]──▶ Generate (back-edge, max_iterations = 30)
35//! │
36//! └──────[done]──────▶ next-node…
37//! ```
38//!
39//! Joins inside loops are almost always [`Activation::Any`] or merger-joins: an
40//! `All`-join on a cycle starves (one incoming edge fires once ever, the other once per
41//! iteration) — see [`engine`] for the diagram, and expect a validation warning.
42
43pub mod condition;
44pub mod context;
45pub mod def;
46pub mod engine;
47pub mod error;
48pub mod events;
49pub mod graph;
50pub mod merge;
51pub mod node;
52pub mod recovery;
53pub mod registry;
54pub mod run;
55pub mod value;
56
57#[doc(inline)]
58pub use condition::{Condition, ConditionEval, NamedConditionId};
59#[doc(inline)]
60pub use context::BspContext;
61#[doc(inline)]
62pub use def::{
63 ActivationDef, ConditionDef, EdgeDef, GRAPH_DEF_VERSION, GraphDef, NodeDef, RecoveryDef,
64 StaticInputDef,
65};
66#[doc(inline)]
67pub use engine::{
68 BranchTransform, BspEngine, DEFAULT_MAX_PENDING_TOKENS, DEFAULT_MAX_STEPS, ValidationReport,
69};
70#[doc(inline)]
71pub use error::BspError;
72#[cfg(feature = "tokio")]
73#[doc(inline)]
74pub use events::ChannelInterceptor;
75#[doc(inline)]
76pub use events::{BspEvent, BspInterceptor};
77#[doc(inline)]
78pub use graph::{
79 BspGraph, ERROR_PORT, Edge, EdgeId, InputPin, NodeHandle, NodeId, OutputPin, PortIndex,
80 TypedNodeHandle,
81};
82#[doc(inline)]
83pub use merge::Merger;
84#[doc(inline)]
85pub use node::{Activation, BspNode, DataflowNode, NodeOutcome};
86#[doc(inline)]
87pub use recovery::{Recovery, RecoveryPolicy, RetryPolicy};
88#[doc(inline)]
89pub use registry::NodeRegistry;
90#[doc(inline)]
91pub use run::{
92 EngineResult, PendingSuspension, RunContext, RunState, SuspendedExecution, ValueStore,
93};
94#[doc(inline)]
95pub use value::{BspOutputMapExt, BspSkip, BspValue};
96
97// Re-export proc-macros
98pub use async_nodes_macros::{BspType, node, node_blocking};
99
100// Hidden re-exports to provide macro hygiene in downstream projects
101#[doc(hidden)]
102pub use async_trait;
103#[doc(hidden)]
104pub use indexmap;
105
106// Re-export typemap_rev to simplify implementation of TypeMapKey for users
107pub use typemap_rev;
108
109#[cfg(feature = "tokio-blocking")]
110#[doc(hidden)]
111pub use ::tokio;