1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use crate::;
/// A `Route` represents an ordered pipeline of `Processor` implementations applied to
/// an `Exchange`. Each processor can mutate the `Exchange` (e.g. enrich headers,
/// transform the payload, set `out_msg`, assign correlation identifiers, etc.).
///
/// # Design Goals
/// * Simple, minimal abstraction over a Vec of boxed processors.
/// * Works in both synchronous and asynchronous modes (feature `async`).
/// * Deterministic ordering: processors are executed in the order they were added.
/// * Uniform error propagation: the first processor returning an error short-circuits the route.
/// * Extensible: callers can wrap `Route::run` to add cross-cutting concerns (metrics, tracing, retry).
///
/// # When to Use
/// Use a `Route` anytime you need to compose a series of message transformations / routing logic.
/// It mirrors concepts from EIP frameworks where a route is an assembly of steps.
///
/// # Correlation & Message IDs
/// If your processors rely on correlation IDs (e.g. aggregation), have an early processor call
/// `exchange.in_msg.ensure_correlation_id()` to guarantee one is present. `Message` already
/// auto-generates a `message_id` header on creation.
///
/// # Examples
/// Unified example:
/// ```rust
/// use allora_core::{processor::ClosureProcessor, route::Route, Exchange, Message};
/// let route = Route::new().add(ClosureProcessor::new(|exchange| { exchange.out_msg = Some(Message::from_text("done")); Ok(()) })).build();
/// let mut exchange = Exchange::new(Message::from_text("hi"));
/// tokio::runtime::Runtime::new().unwrap().block_on(async { route.run(&mut exchange).await.unwrap(); });
/// assert_eq!(exchange.out_msg.unwrap().body_text(), Some("done"));
/// ```
///
/// # Error Handling
/// If any processor returns an `Err`, processing stops immediately and the error is returned to
/// the caller. Downstream processors are not executed.
///
/// # Future Extensions (Ideas)
/// * Conditional routing (e.g. only execute processor if a header matches).
/// * Branch / fork processors returning multiple Exchanges.
/// * Built-in metrics / tracing instrumentation wrapper.
/// * Middleware style before / after hooks.
///
/// Create routes via the builder pattern: `Route::new().add(...).add(...).build()`.