feat: consume transactional email notifications

Add contract validation, SMTP delivery results, terminal failure context, neutral development seeding, and local Docker setup.

Ref: IT-1033
This commit is contained in:
2026-08-04 12:32:28 +03:00
parent b8435ac07b
commit 2757869176
37 changed files with 1465 additions and 122 deletions
+104 -7
View File
@@ -1,5 +1,98 @@
# hrynco-notification-service
## Documentation
- [ItemTracker outbox email consumer](docs/itemtracker-outbox-email-consumer.md)
## Development environment
The development Docker Compose stack runs PostgreSQL, RabbitMQ, database migrations,
the Notification Service Web and Worker applications, Seq, and Mailpit.
Prerequisite: install and start Docker Desktop. Then run the installation script from
the repository root:
```powershell
.\docker\environments\install-development.cmd
```
The script validates Docker and the Compose configuration, builds the application
images, starts the complete stack in the background, and prints container status and
the main development URLs. It can also be launched directly from File Explorer or
from another working directory.
To validate the setup without building images or creating containers, run:
```powershell
.\docker\environments\install-development.cmd --validate-only
```
By default, the script uses the tracked `docker/environments/.env.Development` file:
```dotenv
DB_NAME=notification_service
DB_USER=postgres
DB_PASS=postgres
VOLUME_PREFIX=ns-dev
RABBITMQ_USER=guest
RABBITMQ_PASSWORD=guest
RABBITMQ_AMQP_PORT=5672
RABBITMQ_MANAGEMENT_PORT=15672
WEB_PORT=5200
DEVELOPMENT_EMAIL_SERVICE_NAME=TestService
```
To use personal values, copy it to the Git-ignored
`docker/environments/.env.local`, adjust the values, and run Docker Compose manually:
```powershell
docker compose --env-file docker/environments/.env.local `
-f docker/environments/docker-compose.yml `
-f docker/environments/docker-compose.Development.yml `
up --build -d
```
After startup, the main development endpoints are:
- Notification Service admin: `http://localhost:5200/admin/channels`
- Notification templates: `http://localhost:5200/admin/templates`
- RabbitMQ management: `http://localhost:15672` (`guest` / `guest`)
- Mailpit inbox: `http://localhost:8025`
- Seq logs: `http://localhost:5342`
- PostgreSQL: `localhost:5433`
During development migrations, the stack idempotently creates an active Mailpit SMTP
channel and a neutral English `TestEmail` template for
`DEVELOPMENT_EMAIL_SERVICE_NAME`. Existing channels and templates are never
overwritten. Change that environment value when the publisher uses another service
name.
Check container status and follow Worker logs:
```powershell
docker compose --env-file docker/environments/.env.local `
-f docker/environments/docker-compose.yml `
-f docker/environments/docker-compose.Development.yml `
ps
docker compose --env-file docker/environments/.env.local `
-f docker/environments/docker-compose.yml `
-f docker/environments/docker-compose.Development.yml `
logs -f worker
```
Stop the environment without deleting its database and RabbitMQ volumes:
```powershell
docker compose --env-file docker/environments/.env.local `
-f docker/environments/docker-compose.yml `
-f docker/environments/docker-compose.Development.yml `
down
```
See the [ItemTracker consumer guide](docs/itemtracker-outbox-email-consumer.md#local-end-to-end-setup)
for the complete end-to-end setup.
## Notification worker flow
```mermaid
@@ -7,11 +100,15 @@ flowchart TD
A[Worker host starts] --> B[Load config and register services]
B --> C[Start SendEmailConsumer]
C --> D[Receive message from notification.send-email]
D --> E[Resolve SendEmailService]
E --> F[Pick channel and template]
F --> G[Render email content]
G --> H[Send via SMTP]
H --> I[Update usage counters]
I --> J[Optionally publish result to reply queue]
H -. failure .-> K[Log and rethrow]
D --> E[Validate Notification.SendEmail.v1 metadata and payload]
E --> F[Resolve SendEmailService]
F --> G[Pick channel and exact-language template]
G --> H[Validate variables and render email content]
H --> I[Send via SMTP]
I --> J[Update usage counters]
J --> K[Optionally publish result to reply queue]
K --> L[Acknowledge RabbitMQ delivery]
I -. failure .-> M[Log and retry]
M -->|retries exhausted| N[Publish terminal failure result]
N --> O[Nack original delivery without requeue]
```