ADR-0001. Cấp phát thuế dựa trên CDC với đối soát idempotent
| Field | Value |
|---|---|
| Status | Accepted |
| Date | 2026-04-01 |
| Deciders | Phat Nguyen |
| Supersedes | - |
Bối cảnh
- Commerce sở hữu
Product(gồm cảtaxGroupId); taxation không được gọi commerce đồng bộ mỗi lần ghi sản phẩm. - Thuế phải luôn nhất quán khi sản phẩm được tạo, đổi tax group, mất tax group, hoặc bị xoá.
- Debezium đã phát luồng thay đổi
public.Product; tái dùng luồng này giúp tránh phải định nghĩa một API contract mới. - Giao nhận at-least-once cộng với việc consumer khởi động lại nghĩa là cùng một thay đổi có thể bị xử lý nhiều lần.
Quyết định
Chúng tôi tiêu thụ topic Debezium public.Product trong một ApplicationKafkaComponent duy nhất và định tuyến mọi thay đổi tới TaxationWorkerService.handleProductCDC. Hàm này đối soát thay vì áp dụng delta: c/u/r → cấp phát khi taxGroupId có giá trị (ngược lại thì thu hồi), d → thu hồi. Việc cấp phát là idempotent - TaxProvisioningService bỏ qua khi đã tồn tại một TaxSet ACTIVATED với sourceType = TaxGroup và sourceId khớp.
Hệ quả
| Ưu | Nhược |
|---|---|
| Không phụ thuộc đồng bộ vào commerce | Không nạp lại dữ liệu cũ: fallbackMode: latest bỏ qua các thay đổi trước offset |
| Đối soát tự khôi phục khi bị giao lại | Các TaxSet DEACTIVATED tích lũy dần (không bao giờ bị xoá cứng) |
| Một topic, một consumer - bề mặt tối thiểu | Không có DLQ; onMessageError chỉ ghi log |
Idempotency key (sourceType, sourceId) tránh TaxSet trùng | Một Snowflake worker id cố định cứng chặn việc mở rộng theo chiều ngang |
Các phương án đã cân nhắc
| Phương án | Ưu | Nhược | Lý do loại bỏ |
|---|---|---|---|
| Commerce gọi taxation qua REST khi ghi sản phẩm | Tức thì, không cần Kafka | Phụ thuộc đồng bộ; commerce phải biết taxation; logic retry phức tạp | Ràng buộc vào đường ghi; CDC đã có sẵn |
| Xử lý theo delta (chỉ áp dụng phần khác biệt) | Ít việc hơn mỗi message | Dễ vỡ khi bị giao lại hoặc sai thứ tự | Đối soát đơn giản hơn và tự khôi phục |
fallbackMode: earliest + nạp lại dữ liệu cũ | Bắt được các dòng lịch sử | Phát lại toàn bộ lịch sử mỗi lần reset group | Nặng về vận hành; các endpoint cấp phát 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