ADR-0002. Activity notification do Kafka cấp, lưu trong core, rồi push
| Trường | Giá trị |
|---|---|
| Status | Accepted |
| Date | 2026-05-20 |
| Deciders | signal-team |
| Supersedes | — |
Bối cảnh
- Sự kiện domain (vd thanh toán thành công) cần trở thành notification bền vững, theo từng user hiển thị trong UI "chuông" và một gợi ý WS live.
- Producer biết điều gì xảy ra và một phạm vi người nhận (org / merchant / users rõ ràng) nhưng không biết danh sách người nhận cụ thể.
- Signal đã sở hữu edge WebSocket nhưng không có schema; bảng
ActivityNotificationtập trung trong@nx/core. - Notification phải sống sót qua một socket lỡ — client có thể offline khi sự kiện bắn.
Quyết định
Chúng ta sẽ cấp activity notification cho Signal qua Kafka (signal.activity-notification), và để worker giải → lưu → push:
- Consume
TActivityNotificationMessage; từ chốieventTypelạ. - Giải người nhận phía server —
org/merchantquaPolicyDefinitionRepository,usersquarecipientIdsrõ ràng (fallback[actorId]). - Dựng
content+htmltừ một markdown decorator, lưu một hàngActivityNotificationmỗi người nhận quacreateAll. - Push
observation/signal/notification/createdtới mỗi roomsignal/notification/{recipientId}.
Consumer chạy với autocommit: false, commit theo từng message sau khi handler return, và fallbackMode: latest.
Hệ quả
| Ưu | Nhược |
|---|---|
| Notification bền vững (DB) và live (WS) | Re-delivery tạo hàng trùng — không dedup hôm nay |
| Producer giữ chỉ-scope; Signal sở hữu giải người nhận | Giải người nhận là một lần hit DB đồng bộ mỗi message |
Tái dùng schema/repo tập trung @nx/core | Lỗi handler được log nhưng không retry/DLQ |
| Commit thủ công cho an toàn at-least-once | Hiện chỉ hiện thực nội dung PAYMENT_SUCCESS |
Phương án đã cân nhắc
| Phương án | Ưu | Nhược | Vì sao loại |
|---|---|---|---|
| Chỉ push WS (không lưu) | Đơn giản nhất | Mất nếu client offline; không lịch sử | UI chuông cần lịch sử bền vững |
| Producer giải người nhận + ghi hàng | Signal giữ ngu | Mỗi producer lặp giải + kiến thức schema | Tập trung trong Signal DRY hơn |
| Autocommit + idempotency key | Ít code thủ công | Cần store dedup; chưa xây | Hoãn; commit thủ công là an toàn tạm |
Tham chiếu
signal/src/components/notification/component.ts(config consumer)signal/src/services/activity-notification-worker.service.ts(giải/lưu/push)core/src/common/kafka/types.ts(TActivityNotificationMessage)- API Events — idempotency