template-monorepo/internal/model/notification/SDD.md

9.2 KiB
Raw Blame History

Notification Service

Notification Service — SRS/SDD Document

Version Version Date Editor Memo
1.0.0 2026/05/21 Gateway Team 初版Gateway Notification 模組 SDD

1. Introduction

1.1 Purpose

Notification 模組為 TianTing Gateway 的統一對外通知入口,支援 Email 與 SMS 的同步寄送、異步佇列、冪等、租戶配額、指數退避重試與 DLQDead Letter Queue管理。

1.2 Scope

範圍內:

  • 同步 Send:渲染模板後立即送達
  • 異步 EnqueueMongo 寫入 pending + Redis ZSET 排程 + RetryWorker 背景投遞
  • 冪等Redis cache + Mongo unique index
  • 租戶每日 Email/SMS 配額
  • 模板渲染embed HTML / SMS / Subject多語系
  • Provider chainSMTP、SES、Mitake、Mock
  • Admin DLQ 查詢與手動重試

範圍外:

  • Push / Webhookenum 已定義,尚未實作)
  • 專用 HTTP API目前僅內部 logic 呼叫;擴充路徑見 README

1.3 Definitions, Acronyms, and Abbreviation

縮寫 說明
NotifyKind 通知類型verify_email、tenant_welcome 等)
Channel 通道email / sms / push / webhook
DLQ Dead Letter Queue超過 MaxRetry 的失敗通知
IdempotencyKey 冪等鍵,同 tenant+kind+key 不重複寄送
TargetHash SHA-256(target)Mongo 不存明文 email/phone
RetryJob Redis ZSET 成員,含 target僅 Redis不落 Mongo

1.4 Technologies to be used

項目 技術
Application Language Go 1.22+
Framework go-zero
Database MongoDBnotifications、notification_dlq
Cache / Queue Redis冪等、配額、retry ZSET
Templates go:embed + Go text/html template
Email Providers SMTP、AWS SES、Mock
SMS Providers Mitake三竹、Mock

1.5 Overview

Notification 為 library-style domain package嵌入 Gateway process 內執行:

  1. SendCaller → 冪等檢查 → 配額 → Insert pending → Render → Provider chain → Update sent/failed
  2. Enqueue:同上至 Insert → ZADD Redis → 回傳 pendingRetryWorker 背景 ClaimDue → 投遞
  3. DLQattempts ≥ MaxRetry → status=dropped + 寫入 notification_dlq

2. System Overview

Notification 模組解耦業務邏輯與實際寄送:

  • Auth 註冊 OTP、Member 業務驗證等 logic 層呼叫 Notifier.Send
  • 歡迎信等可容忍延遲的通知可走 Enqueue + Worker
  • 隱私設計Mongo / DLQ 只存 target_hash,明文 target 僅在 Redis RetryJob 生命週期內存在

Worker 由 ServiceContext.StartWorkers 啟動,與 Gateway 同 process 運行。


3. System Architecture

3.1 System Architecture

flowchart TB
    subgraph Callers["Internal Callers"]
        AuthLogic[logic/auth]
        MemberLogic[logic/member]
    end

    subgraph NotificationModule["internal/model/notification"]
        Notifier[NotifierUseCase]
        Admin[AdminNotifierUseCase]
        Worker[RetryWorker]
        Factory[Provider Factory]
        Renderer[Template Renderer]
    end

    subgraph Providers["Providers"]
        EmailChain[email.Chain<br/>SMTP / SES / Mock]
        SMSChain[sms.Chain<br/>Mitake / Mock]
    end

    subgraph Storage["Storage"]
        Mongo[(MongoDB)]
        Redis[(Redis)]
    end

    AuthLogic --> Notifier
    MemberLogic --> Notifier
    Notifier --> Renderer
    Notifier --> Factory
    Notifier --> Mongo
    Notifier --> Redis
    Factory --> EmailChain
    Factory --> SMSChain
    Worker --> Redis
    Worker --> Mongo
    Worker --> EmailChain
    Worker --> SMSChain
    Admin --> Mongo
    Admin --> Redis

3.2 Decomposition Description

套件 職責
config/ Async、Rate、Email、SMS 設定
domain/entity/ Notification、NotificationDLQ
domain/enum/ Channel、NotifyKind、NotifyStatus、Severity
domain/repository/ Notification、DLQ、Store、RetryQueue 介面
domain/usecase/ Notifier、Admin 介面 + DTO
domain/template/ 模板 Spec、Renderer、Registry 介面
repository/ Mongo + Redis 實作
usecase/ Notifier、Admin、RetryWorker、factory、module
provider/email/ SMTP、SES、Mock sender + chain
provider/sms/ Mitake、Mock sender + chain
template/ embed 模板 + render

3.3 Send同步

sequenceDiagram
    participant C as Caller
    participant N as NotifierUseCase
    participant R as Redis
    participant M as Mongo
    participant P as Provider

    C->>N: Send(SendRequest)
    N->>R: Get idempotency
    alt cache hit
        N-->>C: cached DTO
    else miss
        N->>M: FindByIdempotency / Insert pending
        N->>R: Incr quota
        N->>N: Render template
        N->>P: Email/SMS chain.Send
        N->>M: UpdateDelivery (sent/failed)
        N->>R: Set idempotency cache
        N-->>C: NotificationDTO
    end

3.4 Enqueue + RetryWorker異步

sequenceDiagram
    participant C as Caller
    participant N as NotifierUseCase
    participant M as Mongo
    participant R as Redis
    participant W as RetryWorker
    participant P as Provider

    C->>N: Enqueue(SendRequest)
    N->>M: Insert (pending)
    N->>R: ZADD RetryJob (score=now)
    N-->>C: pending DTO

    loop every 1s
        W->>R: ClaimDue (ZREM)
        W->>M: FindByID
        W->>P: Render + deliver
        alt success
            W->>M: status=sent
        else attempts < MaxRetry
            W->>M: status=retrying
            W->>R: ZADD (score=now+backoff)
        else
            W->>M: status=dropped
            W->>M: Insert DLQ
        end
    end

退避序列(預設): [1, 5, 30, 300, 1800]


4. Data Design

4.1 Data Dictionary

notificationsMongoDB

Field Type Comment Index
_id ObjectId PK PK
tenant_id String 租戶 ID Unique(tenant_id, kind, idempotency_key)
uid String 會員 UID (tenant_id, uid, occurred_at desc)
channel String email / sms
kind String NotifyKind Unique(tenant_id, kind, idempotency_key)
target_hash String SHA-256(target)
template_key String 模板 key
locale String 語系
body String 渲染後內容OTP 類可省略)
provider String 實際使用的 provider
provider_message_id String 外部 message ID
status String pending/sent/failed/retrying/dropped (status, attempts, occurred_at)
attempts Int 投遞嘗試次數
last_error String 最後錯誤
idempotency_key String 冪等鍵 Unique(tenant_id, kind, idempotency_key)
severity String info/warn/critical
occurred_at Int64 事件時間 ms
delivered_at Int64 送達時間 ms
create_at Int64 建立時間 ms
update_at Int64 更新時間 ms

notification_dlqMongoDB

Field Type Comment Index
_id ObjectId PK PK
notification_id String 原 notification ID
tenant_id String 租戶 ID
uid String 會員 UID
channel String 通道
kind String 通知類型
target_hash String target hash
last_error String 最後錯誤
attempts Int 總嘗試次數
payload Object 重試 metadatalocale、data 等,不含 target
occurred_at Int64 事件時間 ms
create_at Int64 建立時間 ms

Redis Keys

Key Pattern 用途 TTL
notif:idem:{tenant}:{kind}:{key} 冪等 cache 24h
notif:quota:{tenant}:{channel}:{yyyyMMdd} 每日配額計數 25h
notif:retry:zset可配置 RetryJob ZSETscore=run_at_ms

NotifyKind 一覽

Kind 通道 說明
verify_email email 業務 email OTP
verify_phone sms 業務 phone OTP
verify_registration_email email 註冊 email OTP
step_up_email email Email step-up
step_up_phone sms Phone step-up
account_suspended email 帳號停權通知
tenant_welcome email 租戶歡迎信

5. API Design

現況: 尚無專用 HTTP API。Notification 由內部 logic 呼叫:

呼叫方 方法 用途
logic/auth/register_logic.go Notifier.Send 註冊 email OTP
logic/member/verify_helper.go Notifier.Send 業務 email/phone OTP
cmd/notify-test Send / Enqueue / Admin 本機測試 CLI

擴充 HTTP API 路徑:

  1. generate/api/ 定義路由
  2. make gen-api
  3. internal/logic 映射 types ↔ DTO

6. Resource

資源 路徑
模組原始碼 internal/model/notification/
開發 README internal/model/notification/README.md
測試指南 docs/notification-testing.md
測試 CLI cmd/notify-testmake notify-test
Worker internal/worker/notification_retry/
設定範例 etc/gateway.dev.example.yamlNotification 區塊
設計參考 docs/identity-member-design.md §11