Skip to content

Commit e59f520

Browse files
committed
Remove some sections
1 parent 46a3e39 commit e59f520

File tree

1 file changed

+1
-137
lines changed

1 file changed

+1
-137
lines changed

README.md

Lines changed: 1 addition & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ public async Task<(User user, UserCreated evt)> HandleAsync(CreateUser cmd)
141141

142142
// Usage
143143
var user = await mediator.InvokeAsync<User>(new CreateUser(...));
144-
// UserCreated is auto-published
144+
// UserCreated is auto-published and handlers invoked inline before this method returns
145145
```
146146

147147
## 📦 Publish API & Behavior
@@ -152,142 +152,6 @@ await mediator.PublishAsync(new OrderShipped(orderId));
152152

153153
All handlers run in parallel; if any fail, PublishAsync throws.
154154

155-
### Example: Complete CRUD with Result Types
156-
157-
```csharp
158-
public record GetUserQuery(int Id);
159-
public record UpdateUserCommand(int Id, string Name, string Email);
160-
public record DeleteUserCommand(int Id);
161-
162-
public class UserHandler
163-
{
164-
public async Task<Result<User>> HandleAsync(GetUserQuery query)
165-
{
166-
var user = await _repository.GetByIdAsync(query.Id);
167-
return user != null
168-
? Result.Ok(user)
169-
: Result.NotFound($"User with ID {query.Id} not found");
170-
}
171-
172-
public async Task<Result<User>> HandleAsync(UpdateUserCommand command)
173-
{
174-
var existingUser = await _repository.GetByIdAsync(command.Id);
175-
if (existingUser == null)
176-
return Result.NotFound($"User with ID {command.Id} not found");
177-
178-
if (await _repository.EmailExistsAsync(command.Email, command.Id))
179-
return Result.Conflict("Another user already has this email address");
180-
181-
var updatedUser = existingUser with { Name = command.Name, Email = command.Email };
182-
await _repository.UpdateAsync(updatedUser);
183-
184-
return Result.Ok(updatedUser);
185-
}
186-
187-
public async Task<Result> HandleAsync(DeleteUserCommand command)
188-
{
189-
var deleted = await _repository.DeleteAsync(command.Id);
190-
return deleted
191-
? Result.NoContent()
192-
: Result.NotFound($"User with ID {command.Id} not found");
193-
}
194-
}
195-
```
196-
197-
## 🔄 Cascading Messages - Elegant Event Choreography
198-
199-
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.
200-
201-
### How Cascading Messages Work
202-
203-
When a handler returns a tuple, the mediator automatically:
204-
205-
1. **Returns the expected type** to the caller (if specified)
206-
2. **Publishes remaining tuple items** as cascading events using `PublishAsync`
207-
3. **Waits for completion** - all cascading messages are processed before the original call completes
208-
209-
### Example: Order Processing with Cascading Events
210-
211-
```csharp
212-
// Messages
213-
public record CreateOrder(string ProductName, decimal Amount, string CustomerEmail);
214-
public record Order(int Id, string ProductName, decimal Amount, string CustomerEmail, DateTime CreatedAt);
215-
public record OrderCreatedEvent(int OrderId, string CustomerEmail, decimal Amount);
216-
public record SendWelcomeEmail(string Email, string CustomerName);
217-
public record UpdateInventory(string ProductName, int Quantity);
218-
219-
// Handler that returns a tuple - triggers cascading messages
220-
public class CreateOrderHandler
221-
{
222-
public async Task<(Order, OrderCreatedEvent)> HandleAsync(CreateOrder command, CancellationToken cancellationToken)
223-
{
224-
// Create the order
225-
var order = new Order(
226-
Id: Random.Shared.Next(1000, 9999),
227-
ProductName: command.ProductName,
228-
Amount: command.Amount,
229-
CustomerEmail: command.CustomerEmail,
230-
CreatedAt: DateTime.UtcNow
231-
);
232-
233-
// Create the event that will be published automatically
234-
var orderCreatedEvent = new OrderCreatedEvent(order.Id, order.CustomerEmail, order.Amount);
235-
236-
// Return tuple - Order goes to caller, OrderCreatedEvent gets published
237-
return (order, orderCreatedEvent);
238-
}
239-
}
240-
241-
// Handler for the cascading event
242-
public class OrderCreatedEventHandler
243-
{
244-
public async Task HandleAsync(OrderCreatedEvent orderCreated, CancellationToken cancellationToken)
245-
{
246-
Console.WriteLine($"Order {orderCreated.OrderId} created for ${orderCreated.Amount}");
247-
248-
// Could trigger more cascading messages by returning a tuple
249-
// For example: return (new SendWelcomeEmail(orderCreated.CustomerEmail, "Valued Customer"),);
250-
}
251-
}
252-
```
253-
254-
### Usage with Cascading Messages
255-
256-
```csharp
257-
// Only the Order is returned to the caller
258-
// OrderCreatedEvent is automatically published to all its handlers
259-
var order = await mediator.InvokeAsync<Order>(new CreateOrder(
260-
ProductName: "Amazing Widget",
261-
Amount: 29.99m,
262-
CustomerEmail: "customer@example.com"
263-
));
264-
265-
Console.WriteLine($"Created order {order.Id} - cascading events processed automatically!");
266-
```
267-
268-
### Multiple Cascading Messages
269-
270-
Handlers can return tuples with multiple cascading messages:
271-
272-
```csharp
273-
public class ComplexOrderHandler
274-
{
275-
public async Task<(Order, OrderCreatedEvent, SendWelcomeEmail, UpdateInventory)> HandleAsync(
276-
CreateOrder command,
277-
CancellationToken cancellationToken)
278-
{
279-
var order = new Order(/*...*/);
280-
281-
return (
282-
order, // Returned to caller
283-
new OrderCreatedEvent(order.Id, order.CustomerEmail, order.Amount), // Published
284-
new SendWelcomeEmail(order.CustomerEmail, "Valued Customer"), // Published
285-
new UpdateInventory(order.ProductName, -1) // Published
286-
);
287-
}
288-
}
289-
```
290-
291155
## 📊 Performance Benchmarks
292156

293157
Foundatio.Mediator delivers exceptional performance, getting remarkably close to direct method calls while providing full mediator pattern benefits:

0 commit comments

Comments
 (0)