Route

Struct Route 

Source
pub struct Route { /* private fields */ }
Expand description

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:

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().

Implementations§

Source§

impl Route

Source

pub fn new() -> Route

Create an empty route.

Source

pub fn add<P>(self, p: P) -> Route
where P: Processor + 'static,

Add a processor to the route. Processors execute in insertion order.

Source

pub fn build(self) -> Route

Finalize the route (currently a no-op, kept for API symmetry / future extension).

Source

pub fn with_correlation(mirror_header: Option<&str>) -> Route

Convenience: create a route whose first processor ensures a correlation id. Optionally mirror the correlation id into an additional header name. Example:

use allora_core::{route::Route, processor::ClosureProcessor, Message, Exchange};
let route = Route::with_correlation(None)
    .add(ClosureProcessor::new(|exchange| { exchange.out_msg = Some(Message::from_text("pong")); Ok(()) }))
    .build();
let mut exchange = Exchange::new(Message::from_text("ping"));
tokio::runtime::Runtime::new().unwrap().block_on(async { route.run(&mut exchange).await.unwrap(); });
assert!(exchange.in_msg.header("correlation_id").is_some());
Source

pub async fn run(&self, exchange: &mut Exchange) -> Result<(), Error>

Run the route asynchronously over a mutable Exchange.

Trait Implementations§

Source§

impl Debug for Route

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Default for Route

Source§

fn default() -> Route

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl Freeze for Route

§

impl !RefUnwindSafe for Route

§

impl Send for Route

§

impl Sync for Route

§

impl Unpin for Route

§

impl !UnwindSafe for Route

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more