Skip to content

ADR-0002. Phát sự kiện chỉ qua WebSocket trong tiến trình, không Kafka

FieldValue
StatusAccepted
Date2026-05-01
DecidersPhat Nguyen
Supersedes-

Bối cảnh

  • Phần lớn service BANA phát Kafka event cho CDC và điều phối liên service.
  • Outreach thu thập yêu cầu và đăng ký từ trang công khai. Phía tiêu thụ ở hạ nguồn duy nhất là BO dashboard, vốn muốn một thông báo nổi (toast) thời gian thực khi có yêu cầu mới.
  • Không service nào khác cần phản ứng với một yêu cầu hay đăng ký như một sự kiện nghiệp vụ. Bản ghi lâu bền là dòng dữ liệu trong PostgreSQL.

Quyết định

Outreach không có Kafka producer, không có Kafka consumer, và không có BullMQ worker. Bề mặt bất đồng bộ duy nhất của nó là một WebSocketEmitter dựa trên Redis (outreach-ws-emitter), phát quảng bá INQUIRY_SUBMITTED tới các observation room khi một yêu cầu được gửi lên.

Việc phát đi theo kiểu gửi rồi quên: yêu cầu được ghi vào database trước, sau đó OutreachSocketEventService.notifyInquirySubmitted() chạy mà không chờ kết quả, được bảo vệ bởi isReady() và dùng Promise.allSettled trên các room. Một WS event bị rớt không bao giờ làm mất dữ liệu - BO có thể tải lại qua GET /inquiries.

Hệ quả

ƯuNhược
Hạ tầng tối thiểu: không có Kafka topic, schema, consumer group, hay DLQ phải vận hànhNếu sau này có service cần inquiry event, nó phải poll REST hoặc phải bổ sung một seam Kafka
Trải nghiệm BO thời gian thực qua Redis fan-out (hoạt động trên nhiều replica)Việc gửi qua WS chỉ ở mức nỗ lực tối đa, không bảo đảm lâu bền
Service đơn giản hơn: ít chế độ lỗi hơn, phạm vi ảnh hưởng nhỏ hơnKhông nhất quán với chuẩn Kafka-CDC ở các nơi khác trong nền tảng
Database vẫn là nguồn dữ liệu đúng duy nhấtPhân tích trên các yêu cầu phải đọc DB, không phải một luồng event

Các phương án đã cân nhắc

Phương ánƯuNhượcLý do loại bỏ
Phát Kafka inquiry.submittedLâu bền, fan-out tới bất kỳ consumer nào, hợp chuẩn nền tảngGánh nặng vận hành (topic, consumer, DLQ) cho một consumer nội bộHiện chưa có consumer lâu bền nào
Debezium CDC trên bảng InquiryKhông cần code ứng dụng; ghi nhận mọi thao tác ghiHạ tầng nặng cho một bảng lưu lượng thấp; ràng buộc consumer vào schemaKhông tương xứng với nhu cầu
Chờ WS notify ngay trong requestĐảm bảo gửi thông báo trước khi trả 201Ràng buộc độ trễ/khả dụng của thao tác gửi vào tình trạng của RedisThao tác gửi phải thành công ngay cả khi Redis sập

Tham chiếu

  • packages/outreach/src/components/websocket/component.ts (ApplicationWebSocketComponent)
  • packages/outreach/src/components/websocket/socket-event.service.ts (notifyInquirySubmitted)
  • packages/outreach/src/application.ts (không cấu hình component Kafka/BullMQ nào)
  • API Events

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.