ADR-0002. Triển khai theo mode (FULL / API / WORKER)
| Trường | Giá trị |
|---|---|
| Trạng thái | Accepted |
| Ngày | 2026-02-05 |
| Người quyết định | Phat Nguyen |
| Thay thế | - |
Bối cảnh
- Service payment xử lý hai loại tải khác biệt:
- Tiếp nhận REST + IPN - đồng bộ, nhạy với độ trễ, scale theo lưu lượng nhà cung cấp.
- BullMQ worker - bất đồng bộ (scheduler + xác nhận), scale theo độ sâu queue.
- Chạy cả hai trong một tiến trình làm hạn chế khả năng scale độc lập và khuếch đại phạm vi ảnh hưởng khi sập.
- Tuy vậy, môi trường dev cần gói mọi thứ trong một pod.
Quyết định
Một image, ba mode triển khai chọn qua APP_ENV_MQ_PAY_MODE:
| Mode | Controllers | Queue producer | Workers | Trường hợp dùng |
|---|---|---|---|---|
FULL (mặc định) | ✓ | ✓ | ✓ | Dev - một pod |
API | ✓ | ✓ | ✗ | Tầng REST production - scale theo tốc độ request |
WORKER | ✗ | ✗ | ✓ | Tầng worker production - scale theo độ sâu queue |
Mẫu hình production: 1× API + N× WORKER. Mỗi pod WORKER phải có APP_ENV_NODE_ID duy nhất (Snowflake worker ID = 91, 92, …).
Hệ quả
| Ưu điểm | Nhược điểm |
|---|---|
| REST và worker scale độc lập | Ba manifest triển khai phải duy trì |
| Worker sập không làm sập API | Bắt buộc dùng chung khoá mã hoá (APP_ENV_APPLICATION_SECRET) |
| Dev vẫn dùng một pod (FULL) | Pod WORKER cần snowflake ID duy nhất - dễ sai sót |
| Cấu trúc "API + worker" chuẩn mực | Cấu hình mode sai lệch có thể gây queue chết âm thầm |
Phương án đã cân nhắc
| Lựa chọn | Ưu điểm | Nhược điểm | Lý do từ chối |
|---|---|---|---|
| Một mode duy nhất (luôn full) | Vận hành đơn giản hơn | Không thể scale REST và worker độc lập | Đánh đổi sai cho production |
| Tách image API và WORKER | Ranh giới rõ ràng | Build pipeline phức tạp; rủi ro lệch image | Một image nhiều mode là tiêu chuẩn ngành |
| Worker không trạng thái, không dùng BullMQ | Không phụ thuộc Redis | Không có retry / scheduler / lưu bền | mq-pay cần ngữ nghĩa queue |
Tham chiếu
@nx/mq-pay/src/common/constants.ts:11-14(MQPayRunModes)@nx/mq-pay/src/component.ts:437-444(kiểm tra mode)src/components/payment.component.ts:124-125(phân giải mode)