Loop Node
Example of using LoopNode for control flow loops.
This example demonstrates how to use LoopNode to create a loop that runs for a specific number of iterations.
use std::sync::{Arc, Mutex};
use async_trait::async_trait;
use dagrs::{
Action, DefaultNode, EnvVar, Graph, InChannels, LoopCondition, LoopNode, Node, NodeTable,
OutChannels, Output,
};
struct CountLoopCondition {
max_iterations: usize,
current_iteration: usize,
}
impl CountLoopCondition {
pub fn new(max: usize) -> Self {
Self {
max_iterations: max,
current_iteration: 0,
}
}
}
impl LoopCondition for CountLoopCondition {
fn should_continue(
&mut self,
_input: &InChannels,
_out: &OutChannels,
_env: Arc<EnvVar>,
) -> bool {
if self.current_iteration < self.max_iterations {
self.current_iteration += 1;
true
} else {
false
}
}
fn reset(&mut self) {
self.current_iteration = 0;
}
}
struct PrintAction(String);
#[async_trait]
impl Action for PrintAction {
async fn run(&self, _: &mut InChannels, _: &mut OutChannels, _: Arc<EnvVar>) -> Output {
println!("{}", self.0);
Output::empty()
}
}
#[tokio::main]
async fn main() {
let mut table = NodeTable::new();
let mut graph = Graph::new();
// Create a node that will be executed in the loop
let node_a = DefaultNode::with_action(
"Node A".to_string(),
PrintAction("Executing Node A".to_string()),
&mut table
);
let id_a = node_a.id();
// Create the LoopNode
// It targets 'node_a', meaning when the condition is true, it jumps back to 'node_a'
let loop_node = LoopNode::new(
"Loop Controller".to_string(),
id_a,
CountLoopCondition::new(3), // Loop 3 times
&mut table,
);
let id_loop = loop_node.id();
graph.add_node(node_a);
graph.add_node(loop_node);
// Set dependency: Node A -> Loop Node
graph.add_edge(id_a, vec![id_loop]);
graph.start().unwrap();
}