Skip to content

Commit ac594ae

Browse files
committed
Add async streaming example
1 parent 838e88c commit ac594ae

File tree

4 files changed

+57
-6
lines changed

4 files changed

+57
-6
lines changed

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -375,9 +375,8 @@ The source generator provides compile-time errors for:
375375
- Ability to call `AddMediator` to entry assembly and have it register handlers in all assemblies
376376
- [ ] Clean architecture sample app
377377
- [ ] Modular monolith architecture sample app
378-
- [ ] Switch source generator package name back to Foundatio.Mediator (maybe Foundatio.Mediator.Abstractions)
379378
- [ ] Figure out issue with props / targets files not being included
380-
- [ ] See if we can support streaming with IAsyncEnumerable
379+
- [ ] Talk about streaming support
381380
- [ ] Talk about lifetime. Handlers aren't registered in DI by default and are singleton instances. Just add your handler or services to DI if you want a different behavior.
382381
- [ ] Add GeneratedCodeAttribute
383382
- [ ] Talk about for tuple returns / cascading messages, if a middleware short circuits the response, the value will be returned as the first tuple item and all others will be null or default.

samples/ConsoleSample/Handlers/Handlers.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Runtime.CompilerServices;
12
using ConsoleSample.Messages;
23
using Foundatio.Mediator;
34
using Microsoft.Extensions.Logging;
@@ -95,3 +96,28 @@ public Result<Order> Handle(GetOrder query)
9596
return (Result.NoContent(), new OrderDeleted(command.OrderId, DateTime.UtcNow));
9697
}
9798
}
99+
100+
// Streaming handler example
101+
public class StreamingHandler
102+
{
103+
private readonly ILogger<StreamingHandler> _logger;
104+
105+
public StreamingHandler(ILogger<StreamingHandler> logger)
106+
{
107+
_logger = logger;
108+
}
109+
110+
public async IAsyncEnumerable<int> HandleAsync(CounterStreamRequest request, [EnumeratorCancellation] CancellationToken cancellationToken)
111+
{
112+
for (int i = 0; i < 10; i++)
113+
{
114+
_logger.LogInformation("Streaming value: {Value}", i);
115+
116+
if (cancellationToken.IsCancellationRequested)
117+
yield break;
118+
119+
await Task.Delay(1000, cancellationToken);
120+
yield return i;
121+
}
122+
}
123+
}

samples/ConsoleSample/Messages/Messages.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ public record GetGreeting(string Name);
1010
public record CreateOrder(
1111
[Required(ErrorMessage = "Customer ID is required")]
1212
[StringLength(50, MinimumLength = 3, ErrorMessage = "Customer ID must be between 3 and 50 characters")]
13-
string CustomerId,
14-
13+
string CustomerId,
14+
1515
[Required(ErrorMessage = "Amount is required")]
1616
[Range(0.01, 1000000, ErrorMessage = "Amount must be between $0.01 and $1,000,000")]
17-
decimal Amount,
18-
17+
decimal Amount,
18+
1919
[Required(ErrorMessage = "Description is required")]
2020
[StringLength(200, MinimumLength = 5, ErrorMessage = "Description must be between 5 and 200 characters")]
2121
string Description);
@@ -30,3 +30,6 @@ public record OrderDeleted(string OrderId, DateTime DeletedAt);
3030

3131
// Order model
3232
public record Order(string Id, string CustomerId, decimal Amount, string Description, DateTime CreatedAt, DateTime? UpdatedAt = null);
33+
34+
// Counter stream request
35+
public record CounterStreamRequest { }

samples/ConsoleSample/SampleRunner.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public async Task RunAllSamplesAsync()
1919

2020
await RunSimpleExamples();
2121
await RunOrderCrudExamples();
22+
await RunCounterStreamExample();
2223
await RunEventPublishingExamples();
2324

2425
Console.WriteLine("\n🎉 All samples completed successfully!");
@@ -89,6 +90,28 @@ private async Task RunOrderCrudExamples()
8990
}
9091
}
9192

93+
private async Task RunCounterStreamExample()
94+
{
95+
Console.WriteLine("2️⃣ Counter Stream Example");
96+
Console.WriteLine("==========================\n");
97+
98+
Console.WriteLine("🔢 Starting counter stream...");
99+
100+
CancellationTokenSource cts = new();
101+
int count = 10;
102+
await foreach (var item in _mediator.Invoke<IAsyncEnumerable<int>>(new CounterStreamRequest(), cts.Token))
103+
{
104+
count--;
105+
if (count == 0)
106+
{
107+
cts.Cancel();
108+
}
109+
Console.WriteLine($"Counter: {item}");
110+
}
111+
112+
Console.WriteLine("✅ Counter stream completed.\n");
113+
}
114+
92115
private async Task RunEventPublishingExamples()
93116
{
94117
Console.WriteLine("3️⃣ Event Publishing (Multiple Handlers)");

0 commit comments

Comments
 (0)