Skip to content

ADR-0001. EventBus nội bộ tiến trình + BullMQ cho luồng sự kiện (không Kafka)

TrườngGiá trị
StatusAccepted
Ngày2026-04-01
Người quyết địnhPhat Nguyen
Thay thế-

Bối cảnh

  • Helpdesk cần phản ứng với các sự kiện nghiệp vụ (tạo ticket, đổi trạng thái, phân công, thêm tin nhắn) và chạy các tác vụ nặng theo cơ chế bất đồng bộ (phân công, giám sát SLA, escalation, gửi thông báo, làm giàu ngữ cảnh, khảo sát).
  • Chuẩn của nền tảng cho luồng sự kiện giữa các service là Kafka. @platformatic/kafka thậm chí còn được khai báo trong package.json.
  • Tuy nhiên, mọi luồng sự kiện của helpdesk đều nằm trong một service: một sự kiện do use-case phát ra được một listener trong chính service đó tiếp nhận rồi phân phối ra các job chạy nền. Không service nào khác lắng nghe sự kiện của helpdesk, và helpdesk cũng không lắng nghe topic bên ngoài nào.

Quyết định

Dùng cơ chế hai tầng nội bộ service và không dùng Kafka:

  1. EventBus nội bộ tiến trình (eventemitter3, EventBusComponent) - use-case phát sự kiện TicketEventTypes qua TicketEmitter; các listener trong src/application/events/listeners/ xử lý đồng bộ ngay trong tiến trình API. Lỗi của handler được bắt và ghi log, không bao giờ làm sập emitter.
  2. Các queue BullMQ (QueueComponent, WorkerComponent) - listener phân phối ra các queue bền vững lưu trên Redis; một worker process riêng (RUN_MODE=worker) tiêu thụ chúng với cơ chế retry/backoff theo từng queue.

@platformatic/kafka vẫn được khai báo nhưng không dùng (dependency thừa).

Hệ quả

ƯuNhược
Không phụ thuộc cụm Kafka cho một service khép kínSự kiện không quan sát được từ bên ngoài - service khác không thể lắng nghe
Phát sự kiện đồng bộ giúp response HTTP nhanh (tác vụ được hoãn cho BullMQ)EventBus chạy theo cơ chế at-most-once; nếu sập giữa lúc phát và lúc đưa vào queue thì mất phần phân phối
BullMQ cho retry bền vững + DLQ mà không cần brokerPhải nắm hai mô hình phân phối (nội bộ tiến trình + queue)
Phát triển cục bộ đơn giản hơn (chỉ cần Redis)Dependency @platformatic/kafka thừa gây hiểu lầm cho người đọc và làm phình quá trình cài đặt

Phương án đã cân nhắc

Tùy chọnVì sao bị từ chối
Kafka cho mọi luồng sự kiệnQuá cồng kềnh cho luồng nội bộ service; thêm phụ thuộc broker mà không có ai lắng nghe từ bên ngoài
Chỉ dùng BullMQ (không có bus nội bộ tiến trình)Ép mọi phản ứng nghiệp vụ phải đi qua Redis ngay cả khi xử lý đồng bộ nội bộ tiến trình là đủ
Outbox giao dịch + CDCQuá nặng cho một service không có ai tiêu thụ sự kiện từ bên ngoài

Tham khảo

  • src/components/event-bus/event-bus.ts (eventemitter3)
  • src/components/event-bus/event-registry.ts
  • src/application/events/emitters/ticket.emitter.ts
  • src/components/queue.component.ts
  • package.json (@platformatic/kafka được khai báo, không dùng)

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