node_flow/
lib.rs

1#![warn(
2    missing_docs,
3    clippy::tabs_in_doc_comments,
4    clippy::suspicious_doc_comments,
5    clippy::test_attr_in_doctest,
6    clippy::empty_line_after_doc_comments,
7    unused_doc_comments,
8    clippy::empty_docs,
9    clippy::pedantic,
10    clippy::all,
11    clippy::nursery
12)]
13#![forbid(
14    rustdoc::broken_intra_doc_links,
15    missing_debug_implementations,
16    invalid_doc_attributes
17)]
18#![cfg_attr(all(doc, not(doctest)), feature(doc_cfg))]
19
20//! # Node Flow
21//!
22//! **Node Flow** is runtime-agnostic, composable, asynchronous node-based framework for building
23//! structured and reusable data processing pipelines, workflows, or control flows.
24//!
25//! The core idea is that each **node** represents a self-contained asynchronous operation,
26//! and **flows** define how multiple nodes are composed and executed.
27//!
28//! ## Key concepts
29//!
30//! - **[`Node`](crate::node::Node)** - the core building block, representing an async unit of work.
31//! - **[`NodeOutput`](crate::node::NodeOutput)** - output type used by nodes to signal success or soft failure.
32//! - **[`Flows`](crate::flows)** - structures that determine execution order and behavior.
33//! - **[`Context system`](crate::context)** - flows and nodes can restrict the context to ensure that it can perform functions such as:
34//!     - sharing a mutable state
35//!     - context branching/joining
36//!     - task spawning
37//! - **[`Description`](crate::describe::Description)** - describes the structure of a flow, which can then be used for visualization.
38//!
39//! ## Examples
40//! ```
41//! use node_flow::node::{Node, NodeOutput};
42//! use node_flow::flows::SequentialFlow;
43//!
44//! // Example node
45//! #[derive(Clone)]
46//! struct AddOne;
47//!
48//! struct ExampleCtx;
49//!
50//! impl<Ctx: Send> Node<u8, NodeOutput<u8>, (), Ctx> for AddOne {
51//!     async fn run(&mut self, input: u8, _: &mut Ctx) -> Result<NodeOutput<u8>, ()> {
52//!         Ok(NodeOutput::Ok(input + 1))
53//!     }
54//! }
55//!
56//! # tokio::runtime::Builder::new_current_thread()
57//! #     .enable_all()
58//! #     .build()
59//! #     .unwrap()
60//! #     .block_on(async {
61//! async fn main() {
62//!     let mut flow = SequentialFlow::<u8, u8, (), _>::builder()
63//!         .add_node(AddOne)
64//!         .add_node(AddOne)
65//!         .add_node(AddOne)
66//!         .build();
67//!
68//!     let mut ctx = ExampleCtx;
69//!     let result = flow.run(5u8, &mut ctx).await;
70//!     assert_eq!(result, Ok(NodeOutput::Ok(8)));
71//! }
72//! # main().await;
73//! # });
74//! ```
75//!
76//! ## When to use Node Flow
77//!
78//! Use this crate when you need:
79//! - Composable async control flows (e.g., fallback chains, parallel processing).
80//! - Declarative and type-safe node composition.
81//! - Inspectable or visualizable flow structures.
82
83pub mod context;
84pub mod describe;
85pub mod flows;
86mod future_utils;
87pub mod node;