Module content_router

Module content_router 

Source
Expand description

Content-Based Router pattern: route an Exchange to one of several processors based on a header value.

This implements the classic Enterprise Integration Pattern (EIP) “Content-Based Router”. It examines a specific message header and selects a processor whose configured value matches.

§Why It Exists

In message-driven integrations you often need to send different message types (or business events) through distinct processing flows. Instead of embedding conditional logic inside processors or scattering if/else routes, a dedicated router centralizes this decision, improving readability and testability.

§Why In patterns Folder

The patterns module groups canonical EIP building blocks (filter, splitter, aggregator, etc.). ContentBasedRouter is one of those core patterns, so it lives alongside them for discoverability and conceptual cohesion rather than in a generic utilities namespace.

§Behavior

  • Looks up a header (configured via new(header_name)).
  • If the header matches a registered route value (added via when(value, processor)), the associated processor is invoked.
  • If no route matches, returns a Routing error (Error::Routing).
  • Exactly one processor is invoked (first matching key lookup).

§Async vs Sync

The router itself is lightweight; it defers to the selected processor. Under the async feature its process method is async and awaits the downstream processor; without it, synchronous dispatch occurs.

§Example (basic usage)

use allora_core::{patterns::content_router::ContentBasedRouter, processor::ClosureProcessor, route::Route, Exchange, Message};
let hi = ClosureProcessor::new(|exchange| { exchange.out_msg = Some(Message::from_text("hi route")); Ok(()) });
let bye = ClosureProcessor::new(|exchange| { exchange.out_msg = Some(Message::from_text("bye route")); Ok(()) });
let router = ContentBasedRouter::new("kind").when("hi", Box::new(hi)).when("bye", Box::new(bye));
let route = Route::new().add(router).build();
let mut exchange = Exchange::new(Message::from_text("payload"));
exchange.in_msg.set_header("kind", "hi");
let rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on(async { route.run(&mut exchange).await.unwrap(); });
assert_eq!(exchange.out_msg.unwrap().body_text(), Some("hi route"));

§Error Handling

No match: Error::Routing("no matching route"). Downstream processor errors propagate unchanged.

§Testing Strategies

  • Provide several when routes, assert correct one chosen.
  • Assert error when header missing.
  • Use processors that mutate headers to verify only one is executed.

§Future Extensions

  • Predicate-based routing (closures) instead of plain equality.
  • Default / fallback processor.
  • Support for wildcards / pattern matching.
  • Metrics counters (per route hit counts).

Structs§

ContentBasedRouter