Event Subscriptions
The Hermodr.Subscriptions package adds an event dispatcher middleware that routes published CloudEvent instances to matching subscriber handlers.
Overview
Subscriptions are evaluated by one or more IEventSubscriptionResolver implementations. The built-in EventSubscriptionRegistry keeps subscriptions in memory, but resolvers can read from any source — a local store, a relational database, a remote subscription service, or any combination. In future releases, subscription evaluation may even be delegated entirely to a remote system.
Why Use Subscriptions?
- Fan-out within an application — notify multiple services without a broker.
- Integration testing — assert that specific events are handled without external infrastructure.
- Side-effects on publish — trigger audit logging, cache invalidation, or read-model projection.
- Event routing — conditionally re-publish events to a different channel based on payload content.
- Dynamic, database-backed rules — load subscription filters from a store, update them at runtime, and let resolvers pick up the changes without restarting the application.
Architecture Overview
┌─────────────────────────────────────────────────────────────┐
│ Your application │
│ │
│ ┌──────────────┐ ┌────────────────────────────┐ │
│ │ Event data │─────▶│ EventPublisher │ │
│ └──────────────┘ └────────────┬───────────────┘ │
│ │ fan-out │
│ ┌──────────────┴──────────────┐ │
│ │ │ │
│ ┌────────▼────────┐ ┌──────────▼───┐ │
│ │ EventDispatcher │ │ Channel B │ │
│ │ (middleware) │ │ (Azure SB …) │ │
│ └────────┬────────┘ └──────────────┘ │
│ │ resolves matching subscriptions │
│ ┌────────┴──────────────────────────────────┐ │
│ │ IEventSubscriptionResolver (× N) │ │
│ │ ┌──────────────────────────────────────┐ │ │
│ │ │ EventSubscriptionRegistry (default) │ │ │
│ │ │ DatabaseResolver / RemoteResolver … │ │ │
│ │ └──────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
- You register resolver/registry services with
AddSubscriptions(). AddSubscriptions()also wiresEventDispatcherinto the publisher pipeline during DI registration.- For each event, the dispatcher queries all
IEventSubscriptionResolverinstances and aggregates matches. - Every matched subscription's
HandleAsyncis invoked sequentially.
Quick Start
1. Install the package
dotnet add package Hermodr.Subscriptions
2. Register subscriptions in DI
services.AddEventPublisher()
.AddSubscriptions()
.Subscribe("com.example.order.*", async (cloudEvent, ct) =>
{
Console.WriteLine($"Order event received: {cloudEvent.Type}");
await Task.CompletedTask;
}, name: "log-orders");
3. Publish
var publisher = serviceProvider.GetRequiredService<IEventPublisher>();
await publisher.PublishAsync(new OrderPlaced { OrderId = "42" });
// ↑ "log-orders" subscription fires because "com.example.order.placed" matches "com.example.order.*"
Configure EventDispatcherOptions during registration through AddSubscriptions(options => ...) or subs.ConfigureOptions(...). The legacy UseDispatcher() extension remains for source compatibility but is a no-op.
Pages in This Section
| Page | Description |
|---|---|
| Subscription Filters | EventFilter factory methods, EventFilterBuilder fluent API, envelope attribute filters, data-field filters, and combining expressions |
| Filter Expressions | The FilterExpression model, EventFilter / EventFilterBuilder, FilterExpressionType, evaluator behaviour, serialization, and direct evaluation |
| Event Dispatcher | How the dispatcher works, DI setup, and error handling |
| Routing Subscriptions | Re-publishing matched events to a different channel |
| Custom Resolvers | Reading subscriptions from a database or remote service |