Skip to content

ADR-0001. EventBus in-process + BullMQ cho đồng bộ sản phẩm đa merchant

TrườngGiá trị
StatusAccepted
Ngày2026-03-01
Người quyết địnhcommerce-team
Thay thế

Bối cảnh

  • Một sản phẩm được tạo/cập nhật cho một merchant thường phải được sao chép tới các merchant bổ sung của cùng organizer (chuỗi cửa hàng dùng chung catalog).
  • Việc create/update aggregate đã là một transaction DB duy nhất (Product + Info + identifiers + liên kết kênh + variant mặc định). Sao chép động chạm nhiều hàng qua N merchant và có thể chậm.
  • không được chặn hoặc làm fail response aggregate chính, và phải sống sót qua lỗi một phần (bản sao của một merchant fail không nên rollback bản chính).
  • Commerce đã chạy sẵn một kết nối BullMQ Redis và một vai trò worker.

Quyết định

Tách sao chép thành hai giai đoạn kết nối bởi một EventBus in-process (eventemitter3) và một hàng đợi BullMQ:

  1. ProductCreateService / ProductUpdateService commit aggregate chính, rồi phát product.aggregate.{created,updated} trên EventBus (khóa EVENT_EMITTER trong src/common/event.ts).
  2. ProductAggregateCreatedListener / ProductAggregateUpdatedListener xử lý sự kiện. Listener created cũng đánh dấu bước onboarding merchant PRODUCT. Cả hai gọi pushJobToQueue() — nhưng chỉ khi syncMerchantIds.length > 0.
  3. Job rơi vào SYNC_PRODUCT_QUEUE (@nx/commerce/sync-product-queue) trên BullMQ Redis.
  4. SyncProductWorker tiêu thụ nó (tên job .create vs .update) và gọi ProductCreateSyncService / ProductUpdateSyncService.syncToAdditionalMerchants().

EventBus tách rời phát khỏi enqueue; BullMQ cung cấp độ bền, retry, và concurrency có giới hạn (APP_ENV_BULLMQ_WORKER_CONCURRENCY).

Hệ quả

ƯuNhược
Response aggregate chính nhanh — sao chép hoàn toàn asyncPhát xảy ra sau commit; crash giữa commit và enqueue làm mất trigger sync
Lỗi theo từng merchant được cô lập, retry bởi BullMQHai chặng infra (EventBus → hàng đợi Redis) phải suy luận
Bước onboarding + sync dùng chung một sự kiện, đăng ký hai lầnEventBus chỉ in-process — không phân phối cross-replica
Concurrency worker điều chỉnh được; chỉ chạy ở vai trò workerNhất quán cuối cùng: merchant được sao chép trễ hơn bản chính

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

Tùy chọnƯuNhượcVì sao bị từ chối
Sao chép đồng bộ bên trong TX aggregateNhất quán mạnhResponse chậm; một merchant xấu rollback tất cảUX + bán kính tác động không chấp nhận được
Kafka topic cho fan-out syncCross-replica, bềnThêm đấu nối consumer; commerce chỉ producer theo ADR-0002Quá mức cho một job nội bộ, cùng dịch vụ
Enqueue BullMQ trực tiếp từ service (không EventBus)Ít chặng hơnGắn service với hàng đợi; side-effect bước onboarding cần đường thứ haiEventBus đa hợp gọn sự kiện tới cả hai listener

Tham khảo

  • src/common/event.ts (EVENT_EMITTER.PRODUCT.*)
  • src/components/event-bus/component.ts (registry, đăng ký kép created)
  • src/events/listeners/product-aggregate-created.listener.ts / ...updated.listener.ts
  • src/components/queues/queue.component.ts, src/components/workers/sync-product.worker.ts
  • src/services/product/product-create.service.ts:225, product-update.service.ts:228

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