Skip to content

Commit 42cd144

Browse files
committed
Update readme
1 parent c4193ce commit 42cd144

File tree

1 file changed

+97
-2
lines changed

1 file changed

+97
-2
lines changed

README.md

Lines changed: 97 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ Foundatio.Mediator is a high-performance, convention-based mediator library that
1515
- **⚡ Source Generated** - Compile-time code generation for optimal performance
1616
- **🔧 Full DI Integration** - Works seamlessly with Microsoft.Extensions.DependencyInjection
1717
- **🎪 Middleware Pipeline** - Elegant middleware support
18-
- **📦 Auto Registration** - Handlers discovered and registered automatically
18+
- **� Cascading Messages** - Tuple returns automatically trigger follow-up events
19+
- **�📦 Auto Registration** - Handlers discovered and registered automatically
1920
- **🔒 Compile-Time Safety** - Rich diagnostics catch errors before runtime
2021
- **🔧 C# Interceptors** - Direct method calls using cutting-edge C# interceptor technology
2122
- **🎯 Built-in Result Type** - Comprehensive discriminated union for handling all operation outcomes
@@ -178,6 +179,100 @@ public class UserHandler
178179
}
179180
```
180181

182+
## 🔄 Cascading Messages - Elegant Event Choreography
183+
184+
Foundatio.Mediator supports **cascading messages** through tuple return types, enabling elegant event choreography where handlers can trigger additional messages automatically. This is perfect for implementing event-driven workflows and the saga pattern.
185+
186+
### How Cascading Messages Work
187+
188+
When a handler returns a tuple, the mediator automatically:
189+
190+
1. **Returns the expected type** to the caller (if specified)
191+
2. **Publishes remaining tuple items** as cascading events using `PublishAsync`
192+
3. **Waits for completion** - all cascading messages are processed before the original call completes
193+
194+
### Example: Order Processing with Cascading Events
195+
196+
```csharp
197+
// Messages
198+
public record CreateOrder(string ProductName, decimal Amount, string CustomerEmail);
199+
public record Order(int Id, string ProductName, decimal Amount, string CustomerEmail, DateTime CreatedAt);
200+
public record OrderCreatedEvent(int OrderId, string CustomerEmail, decimal Amount);
201+
public record SendWelcomeEmail(string Email, string CustomerName);
202+
public record UpdateInventory(string ProductName, int Quantity);
203+
204+
// Handler that returns a tuple - triggers cascading messages
205+
public class CreateOrderHandler
206+
{
207+
public async Task<(Order, OrderCreatedEvent)> HandleAsync(CreateOrder command, CancellationToken cancellationToken)
208+
{
209+
// Create the order
210+
var order = new Order(
211+
Id: Random.Shared.Next(1000, 9999),
212+
ProductName: command.ProductName,
213+
Amount: command.Amount,
214+
CustomerEmail: command.CustomerEmail,
215+
CreatedAt: DateTime.UtcNow
216+
);
217+
218+
// Create the event that will be published automatically
219+
var orderCreatedEvent = new OrderCreatedEvent(order.Id, order.CustomerEmail, order.Amount);
220+
221+
// Return tuple - Order goes to caller, OrderCreatedEvent gets published
222+
return (order, orderCreatedEvent);
223+
}
224+
}
225+
226+
// Handler for the cascading event
227+
public class OrderCreatedEventHandler
228+
{
229+
public async Task HandleAsync(OrderCreatedEvent orderCreated, CancellationToken cancellationToken)
230+
{
231+
Console.WriteLine($"Order {orderCreated.OrderId} created for ${orderCreated.Amount}");
232+
233+
// Could trigger more cascading messages by returning a tuple
234+
// For example: return (new SendWelcomeEmail(orderCreated.CustomerEmail, "Valued Customer"),);
235+
}
236+
}
237+
```
238+
239+
### Usage with Cascading Messages
240+
241+
```csharp
242+
// Only the Order is returned to the caller
243+
// OrderCreatedEvent is automatically published to all its handlers
244+
var order = await mediator.InvokeAsync<Order>(new CreateOrder(
245+
ProductName: "Amazing Widget",
246+
Amount: 29.99m,
247+
CustomerEmail: "customer@example.com"
248+
));
249+
250+
Console.WriteLine($"Created order {order.Id} - cascading events processed automatically!");
251+
```
252+
253+
### Multiple Cascading Messages
254+
255+
Handlers can return tuples with multiple cascading messages:
256+
257+
```csharp
258+
public class ComplexOrderHandler
259+
{
260+
public async Task<(Order, OrderCreatedEvent, SendWelcomeEmail, UpdateInventory)> HandleAsync(
261+
CreateOrder command,
262+
CancellationToken cancellationToken)
263+
{
264+
var order = new Order(/*...*/);
265+
266+
return (
267+
order, // Returned to caller
268+
new OrderCreatedEvent(order.Id, order.CustomerEmail, order.Amount), // Published
269+
new SendWelcomeEmail(order.CustomerEmail, "Valued Customer"), // Published
270+
new UpdateInventory(order.ProductName, -1) // Published
271+
);
272+
}
273+
}
274+
```
275+
181276
## 🎪 Beautiful Middleware Pipeline
182277

183278
Create elegant middleware that runs before, after, and finally around your handlers. Middleware works seamlessly with the Result type for comprehensive error handling:
@@ -219,7 +314,7 @@ public static class ValidationMiddleware
219314
{
220315
if (MiniValidator.TryValidate(message, out var errors))
221316
return HandlerResult.Continue();
222-
317+
223318
var validationErrors = errors.SelectMany(kvp =>
224319
kvp.Value.Select(errorMessage => new ValidationError(kvp.Key, errorMessage))).ToList();
225320

0 commit comments

Comments
 (0)