ADR-0001. Provisioning thuế điều khiển bởi CDC với reconcile idempotent
| Field | Value |
|---|---|
| Status | Accepted |
| Date | 2026-04-01 |
| Deciders | taxation-team |
| Supersedes | — |
Bối cảnh
- Commerce sở hữu
Product(gồmtaxGroupIdcủa nó); taxation không được gọi commerce đồng bộ trên mỗi lần ghi sản phẩm. - Thuế phải giữ nhất quán khi sản phẩm được tạo, đổi tax group, mất tax group, hoặc bị xóa.
- Debezium đã stream thay đổi
public.Product; tái dùng stream đó tránh một API contract mới. - Delivery at-least-once + restart consumer nghĩa là cùng một thay đổi có thể được xử lý nhiều lần.
Quyết định
Chúng tôi consume topic Debezium public.Product trong một ApplicationKafkaComponent duy nhất và route mọi thay đổi tới TaxationWorkerService.handleProductCDC, vốn reconcile thay vì áp delta: c/u/r → provision khi taxGroupId được set (ngược lại deprovision), d → deprovision. Provisioning idempotent — TaxProvisioningService skip khi một TaxSet ACTIVATED đã tồn tại với sourceType = TaxGroup và sourceId khớp.
Hệ quả
| Ưu | Nhược |
|---|---|
| Không coupling đồng bộ với commerce | Không backfill: fallbackMode: latest skip thay đổi trước offset |
| Reconcile tự chữa lành khi redeliver | TaxSet DEACTIVATED tích lũy (không bao giờ hard-delete) |
| Một topic, một consumer — bề mặt tối thiểu | Không DLQ; onMessageError chỉ log |
Idempotency key (sourceType, sourceId) tránh TaxSet trùng | Một Snowflake worker id hardcode chặn horizontal scale |
Các phương án đã cân nhắc
| Phương án | Ưu | Nhược | Lý do loại bỏ |
|---|---|---|---|
| Commerce gọi taxation REST khi ghi sản phẩm | Tức thì, không Kafka | Coupling đồng bộ; commerce phải biết taxation; phức tạp retry | Ghép write path; CDC đã sẵn có |
| Xử lý dựa-delta (chỉ áp diff) | Ít việc hơn mỗi message | Mong manh khi redeliver / sai thứ tự | Reconcile đơn giản hơn và tự chữa lành |
fallbackMode: earliest + backfill | Bắt được dòng lịch sử | Replay toàn bộ lịch sử mỗi lần reset group | Nặng về vận hành; endpoint provision thủ công là đủ |
Tham chiếu
packages/taxation/src/components/kafka/component.tspackages/taxation/src/services/taxation-worker.service.tspackages/taxation/src/services/tax-provisioning.service.ts:provisionForProductpackages/core/src/common/kafka/topics.ts:CDCKafkaTopics.PRODUCT