ADR-0002. Một deployable, tách thành role api và worker lúc runtime
| Trường | Giá trị |
|---|---|
| Status | Accepted |
| Date | 2026-03-30 |
| Deciders | ledger-team |
| Supersedes | — |
Bối cảnh
- Bề mặt REST (enqueue, vòng đời, download) và pipeline tạo nặng có hồ sơ tài nguyên và scaling rất khác nhau.
- Gói mọi thứ vào mọi replica lãng phí CPU trên pod API và ràng ingress với năng lực render.
- Tách thành hai package riêng sẽ nhân đôi schema, wiring DI, và hạ tầng deploy.
Quyết định
Chúng ta sẽ ship một image duy nhất và chọn hành vi lúc boot bằng APP_ENV_APPLICATION_ROLES (CSV của api, worker; không hợp lệ/rỗng fallback cả hai). configureControllers() chỉ đăng ký controller cho api; configureServices()/configureComponents() đăng ký pipeline worker (LedgerWorkerService, generators), WebSocket emitter, và quét recovery chỉ cho worker. Kafka consumer và component recovery đăng ký vô điều kiện nhưng tự bỏ qua khi vắng role worker.
Hệ quả
| Ưu | Nhược |
|---|---|
| Scale API và worker độc lập | Cổng role rải rác qua application.ts + components |
| Một image, một artifact CI, schema/DI dùng chung | APP_ENV_APPLICATION_ROLES sai cấu hình lặng lẽ fallback cả hai |
Pod chỉ-worker không cần ingress | Phải xác minh role ở hai nơi (đăng ký + tự bỏ qua của component) |
Phương án đã cân nhắc
| Phương án | Ưu | Nhược | Vì sao loại |
|---|---|---|---|
| Hai package riêng | Cô lập cứng | Nhân đôi schema/DI, deploy đôi | Quá nhiều trùng lặp cho một bounded context |
| Luôn chạy cả hai role mỗi replica | Cấu hình đơn giản nhất | Lãng phí CPU trên pod API; scaling bị ràng | Phá vỡ mục đích tách role |
| Feature flag theo từng component | Tinh chi tiết | Bề mặt config tổ hợp | Hai role thô bao trùm mọi topology thực |
Tham chiếu
ledger/src/common/roles.ts(getAppRoles)ledger/src/application.ts(configureComponents/Services/Controllers)ledger/src/components/kafka.component.ts,recovery.component.ts(tự bỏ qua)- Configuration