# Overview

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 … │ │  │
│              │  └──────────────────────────────────────┘ │  │
│              └───────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────┘
```

1. You register resolver/registry services with `AddSubscriptions()`.
2. `AddSubscriptions()` also wires `EventDispatcher` into the publisher pipeline during DI registration.
3. For each event, the dispatcher queries **all** `IEventSubscriptionResolver` instances and aggregates matches.
4. Every matched subscription's `HandleAsync` is invoked sequentially.

## Quick Start

### 1. Install the package

```bash
dotnet add package Hermodr.Subscriptions
```

### 2. Register subscriptions in DI

```csharp
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

```csharp
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](/event-subscriptions/filtering.md)        | `EventFilter` factory methods, `EventFilterBuilder` fluent API, envelope attribute filters, data-field filters, and combining expressions             |
| [Filter Expressions](/event-subscriptions/filter-expressions.md) | The `FilterExpression` model, `EventFilter` / `EventFilterBuilder`, `FilterExpressionType`, evaluator behaviour, serialization, and direct evaluation |
| [Event Dispatcher](/event-subscriptions/dispatcher.md)           | How the dispatcher works, DI setup, and error handling                                                                                                |
| [Routing Subscriptions](/event-subscriptions/routing.md)         | Re-publishing matched events to a different channel                                                                                                   |
| [Custom Resolvers](/event-subscriptions/custom-resolver.md)      | Reading subscriptions from a database or remote service                                                                                               |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://hermodr.deveel.org/event-subscriptions/subscriptions.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
