A publisher used for commands and queries based on the Mediator Design Pattern.
%% sequence displaying pipeline
sequenceDiagram
Publish-->>Behavior: wraps handler with middleware
Behavior-->>Handler: process notification
Handler-->>Publisher: returns to caller
Below is a brief snip of code to get you started before reading more.
- Add a reference to the
Scribbly.Broker.MicrosoftHosting
package
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScribblyBroker(options =>
{
options.AsScoped = true;
options.AddHandlersFromAssembly<Program>();
options
.AddBehavior<TracingBehavior>()
.AddBehavior<ExceptionBehavior>();
});
- Create some notifications
INotification
public record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary) : INotification
{
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
- Create some queries
INotification<TResult>
(these accept data and return a result)
public record WeatherQuery(string Summary) : INotification<WeatherForecast>;
- Create handlers
INotificationHandler
for the notifications
public sealed class WeatherForecastHandler(ILogger<WeatherForecastHandler> logger) : INotificationHandler<WeatherForecast>
{
/// <inheritdoc />
public Task Handle(WeatherForecast notification, CancellationToken cancellationToken = default)
{
logger.LogInformation("Handled Weather: {Weather}", notification);
return Task.CompletedTask;
}
}
- Create query handlers
INotificationHandler
for the messages that return results
public sealed class RandomQueryHandler: INotificationHandler<WeatherQuery, WeatherForecast>
{
private static Random Random = new Random();
/// <inheritdoc />
public Task<WeatherForecast> Handle(WeatherQuery notification, CancellationToken cancellationToken = default)
{
return Task.FromResult(new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(Random.Next(1, 20))),
Random.Next(12, 55),
notification.Summary
));
}
}
- Publish and query
app.MapGet("/weather", async (IBrokerStream streamer, IBrokerPublisher publisher) =>
{
var forecasts = new List<WeatherForecast>();
foreach (var summary in summaries)
{
await foreach (var forecast in streamer.QueryStream<WeatherQuery, WeatherForecast>(new WeatherQuery(summary)))
{
forecasts.Add(forecast);
await publisher.Publish(forecast);
}
}
return forecasts;
});
Simply public interfaces and delegates used to interface with the framework.
The core framework executing and routing notificaitons to handlers.
A wraper leveraging the Microsoft DI container to resolve services and handlers.
An extension to allow asynconouse tracing and message tracking through the Broker framework