Notification Consumers
Summary
Exactly one consumer exists: NotificationEventConsumer, a hosted BackgroundService registered at startup. It handles connection, declaration, binding, parsing, scoping and acknowledgement.
Audience
Engineers, architects, QA, support, DevOps engineers and security reviewers.
Reference Content
The verified reference material for this topic is set out in the sections below.
Registration and lifecycle
Registered as the only hosted service. Its execute loop runs until cancellation: it connects and begins consuming, then awaits indefinitely so the loop does not spin. A cancellation exits cleanly; any other exception is logged as a warning naming the broker host and port, and the loop retries after a fixed delay.
This means a broker outage produces repeated warning-level reconnect attempts rather than a crash or a failed health state — the service stays up and reports healthy while consuming nothing. See event limitations.
Per-delivery handling
For each delivery the consumer:
- Captures the channel reference and returns silently if it is null.
- Parses AMQP properties, headers and body into an envelope.
- Creates a new dependency-injection scope.
- Resolves the dispatcher from that scope and awaits dispatch.
- Acknowledges the single delivery tag.
The scope-per-delivery step is what gives each message its own scoped persistence context, preventing change-tracker state from leaking between messages.
Cancellation token usage
The consumer passes its stopping token — not a per-delivery token — into dispatch and acknowledgement. On shutdown, an in-flight dispatch is therefore cancelled mid-processing, which given the many-small-saves persistence model can leave a partially processed event with no idempotency ledger row.
Acknowledgement behavior
| Outcome | Action |
|---|---|
| Dispatch completes without exception | Acknowledge the delivery tag, not multiple |
| Any exception escapes dispatch | Log as error, negatively acknowledge with requeue true |
| The negative acknowledgement itself fails | Log as error and continue |
There is no rejection without requeue and no bounded redelivery count, so a message that fails deterministically is requeued indefinitely. See retry and redelivery.
What counts as a failure
The dispatcher handles most business outcomes internally — duplicate, stale, no template, no recipient, suppressed and delivery failure all complete normally and are acknowledged. Only an infrastructure failure escaping the dispatcher, such as a persistence error, reaches the consumer's catch. The source comment states this intent directly.
Verified absence
There is no second consumer, no competing-consumer configuration in code, no consumer tag management, no manual channel recovery beyond the library's automatic recovery, and no concurrency limiter other than prefetch.
Classification
Implemented.
Requires confirmation
Whether shutdown should drain in-flight deliveries rather than cancel them requires confirmation.
Related Articles
See Also
Keywords
- Notification database
- Consumers
- Draft database documentation
Source References
microservices/src/notification-service/Messaging/NotificationEventConsumer.csmicroservices/src/notification-service/Program.csmicroservices/src/notification-service/Application/NotificationDispatcher.csmicroservices/src/notification-service/Application/NotificationOptions.cs
Revision Information
- Status: Draft
- Last reviewed: 2026-07-21
- Review cycle: Quarterly