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

4.3 KiB

Main Flows

Producer -> Notification

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

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

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

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

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.