Files
galaxy-game/notification/docs/flows.md
T
2026-04-22 08:49:45 +02:00

131 lines
4.3 KiB
Markdown

# Main Flows
## Producer -> Notification
```mermaid
sequenceDiagram
participant Producer
participant Stream as Redis Stream notification:intents
participant Consumer as Intent consumer
participant Notify as Notification Service
participant Redis
Producer->>Stream: XADD normalized intent
Consumer->>Stream: XREAD from stored offset
Consumer->>Notify: decode and validate envelope
alt malformed intent
Notify->>Redis: record malformed-intent entry
Consumer->>Redis: save stream offset
else duplicate with same normalized content
Notify->>Redis: load accepted notification
Consumer->>Redis: save stream offset
else idempotency conflict
Notify->>Redis: record malformed-intent entry
Consumer->>Redis: save stream offset
else new valid intent
Notify->>Redis: store notification, routes, and idempotency record
Consumer->>Redis: save stream offset
end
```
Duplicate handling is scoped by `(producer, idempotency_key)`. `request_id` and
`trace_id` are observability-only metadata and do not participate in the
idempotency fingerprint.
## User-Targeted Enrichment
```mermaid
sequenceDiagram
participant Consumer as Intent consumer
participant Notify as Notification Service
participant User as User Service
participant Redis
Consumer->>Notify: accepted user-targeted intent
loop each recipient_user_id
Notify->>User: GET /api/v1/internal/users/{user_id}
alt user exists
User-->>Notify: email + preferred_language
else subject_not_found
Notify->>Redis: record malformed intent recipient_not_found
Consumer->>Redis: save stream offset
else temporary failure
Notify-->>Consumer: service unavailable
Consumer-->>Consumer: stop before stream-offset advance
end
end
Notify->>Redis: persist enriched routes
```
User-targeted routes are enriched before durable route write. The currently
supported resolved locale is exactly `en`; unsupported or empty values fall
back to `en`.
## Notification -> Gateway
```mermaid
sequenceDiagram
participant Push as Push publisher
participant Redis
participant Gateway as Edge Gateway
participant Client
Push->>Redis: load due push route
Push->>Redis: acquire temporary route lease
Push->>Push: encode FlatBuffers notification payload
Push->>Redis: XADD MAXLEN ~ gateway client-event stream
Push->>Redis: mark route published and remove from schedule
Gateway->>Redis: XREAD client-event stream
Gateway->>Gateway: sign outgoing GatewayEvent
Gateway-->>Client: fan out to all active user streams
```
`Notification Service` publishes `user_id`, `event_type`, `event_id`,
`payload_bytes`, and optional `request_id` / `trace_id`. It intentionally omits
`device_session_id`.
## Notification -> Mail
```mermaid
sequenceDiagram
participant Email as Email publisher
participant Redis
participant Mail as Mail Service
Email->>Redis: load due email route
Email->>Redis: acquire temporary route lease
Email->>Email: encode template-mode command
Email->>Redis: XADD mail:delivery_commands
Email->>Redis: mark route published and remove from schedule
Mail->>Redis: XREAD mail:delivery_commands
Mail->>Mail: accept template delivery command
```
Notification-generated mail always uses `source=notification`,
`payload_mode=template`, and `template_id == notification_type`.
Auth-code mail is not part of this flow and remains a direct
`Auth / Session Service -> Mail Service` request.
## Retry and Dead Letter
```mermaid
sequenceDiagram
participant Publisher
participant Redis
participant Downstream as Gateway or Mail Service
Publisher->>Redis: load due route
Publisher->>Redis: acquire temporary route lease
Publisher->>Downstream: append downstream stream entry
alt publication succeeds
Publisher->>Redis: mark published and remove schedule member
else retry budget remains
Publisher->>Redis: mark failed and schedule next attempt
else retry budget exhausted
Publisher->>Redis: mark dead_letter and write dead-letter entry
end
```
`push` and `email` retry independently. A dead-lettered route never rolls back
or invalidates a sibling route that already reached `published`.