Message Routing
Message routing is a core concept in the Matrix Framework that determines how messages flow through your application. The framework uses a tree-based routing system that allows for flexible and powerful message handling.
Message Flow Patterns
Bubbling
Messages start at the source service and bubble up through parent services until handled:
<Matrix xmlns="http://schemas.matrix.com/network/2024">
<ServiceNode Name="OrderSystem">
<!-- Messages from children bubble up to here -->
<MessageHandler Route="Bubble">
<Handle Path="/orders/created" />
<Handle Path="/orders/updated" />
</MessageHandler>
<ServiceNode Name="OrderProcessor">
<!-- Messages originate here and bubble up -->
<MessageSource>
<Message Path="/orders/created" />
</MessageSource>
</ServiceNode>
</ServiceNode>
</Matrix>Tunneling
Messages start at a parent service and tunnel down through child services:
<Matrix xmlns="http://schemas.matrix.com/network/2024">
<ServiceNode Name="InventorySystem">
<!-- Messages originate here and tunnel down -->
<MessageSource>
<Message Path="/inventory/updated"
Route="Tunnel" />
</MessageSource>
<ServiceNode Name="StockManager">
<!-- Receives tunneled messages from parent -->
<MessageHandler>
<Handle Path="/inventory/updated" />
</MessageHandler>
</ServiceNode>
</ServiceNode>
</Matrix>Route Configuration
Message Paths
Define which messages a service handles:
<MessageHandler>
<!-- Exact path match -->
<Handle Path="/orders/created" />
<!-- Wildcard matching -->
<Handle Path="/orders/*" />
<!-- Multi-segment wildcard -->
<Handle Path="/inventory/**" />
</MessageHandler>Route Strategies
Configure how messages flow through services:
<ServiceNode Name="OrderSystem">
<MessageRouter>
<!-- Bubble up order events -->
<Route Path="/orders/*"
Strategy="Bubble" />
<!-- Tunnel down inventory updates -->
<Route Path="/inventory/*"
Strategy="Tunnel" />
<!-- Direct routing to specific service -->
<Route Path="/notifications/*"
Strategy="Direct"
Target="NotificationService" />
</MessageRouter>
</ServiceNode>Message Handling
Handler Registration
Services register handlers for specific message paths:
public class OrderProcessor : ServiceNode
{
protected override void RegisterHandlers()
{
// Handle specific message
HandleMessage("/orders/created",
async msg => await ProcessOrder(msg));
// Handle multiple messages
HandleMessages("/orders/*",
async msg => await TrackOrder(msg));
}
}Message Context
Access message context during handling:
public class OrderProcessor : ServiceNode
{
private async Task ProcessOrder(MessageContext context)
{
// Access message properties
var orderId = context.Message.GetValue<string>("orderId");
// Access source information
var source = context.SourceService;
// Check if message was handled
if (context.IsHandled)
return;
// Mark as handled
context.MarkHandled();
// Continue routing
await context.ContinueRoutingAsync();
}
}Best Practices
-
Message Design
- Use clear, hierarchical message paths
- Keep messages focused and cohesive
- Include necessary context
- Version message contracts
-
Route Configuration
- Choose appropriate routing strategies
- Use wildcards judiciously
- Document routing decisions
- Monitor message flow
-
Handler Implementation
- Keep handlers focused
- Process messages asynchronously
- Handle errors appropriately
- Log handling decisions