Skip to content

ADR-0004. Worker idempotency qua lookup InventoryTracking

TrườngGiá trị
StatusAccepted
Date2026-02-12
Decidersinventory-team
Supersedes

Bối cảnh

  • Tất cả Kafka topic đều at-least-once. Cùng một message có thể được gửi lại khi consumer crash, rebalance, hoặc replay.
  • InventoryStockRepository.adjustStock không idempotent — áp dụng lại cùng delta sẽ tính kép.
  • Cần dedup theo (saleOrderId, stockId)(purchaseOrderId, stockId) mà tồn tại sau khi restart.

Quyết định

Trước bất kỳ stock mutation nào, worker truy vấn InventoryTracking theo (referenceType, referenceId, inventoryStockId):

  • Nếu có row → handler short-circuit, commit Kafka offset, không thay đổi stock.
  • Nếu không có row → tiếp tục với adjustStock + insert tracking row trong cùng luồng.

InventoryTracking là sổ cái dedup. Phần lớn idempotency của inventory là đọc từ nó trước khi ghi.

Hệ quả

ProsCons
Một cơ chế chung cho mọi worker handlerThêm 1 query mỗi lần stock mutation
Tracking row đóng vai trò vừa audit log vừa key dedupNếu insert tracking lỗi sau khi adjustStock thành công, lúc retry sẽ trừ kép (hiếm; giảm thiểu bằng transaction)
Không cần state store ngoài (Redis, bảng DB lock)Tracking lookup phải có index để đảm bảo hiệu năng
Replay tooling hoạt động với mọi khoảng thời gian quá khứTracking grow vô hạn — cần partition ở quy mô lớn

Idempotency keys theo topic

TopicKey
PAYMENT_SUCCESS(SALE_ORDER, saleOrderId, stockId)
KITCHEN_TICKET_ITEM_STATUS_CHANGED(KITCHEN_TICKET_ITEM, kitchenTicketItemId, materialStockId)
MATERIAL_TRANSFERRED(transferId, fromStockId) + (transferId, toStockId)
Merchant CDCensureDefaultLocation(merchantId) self-idempotent
ProductVariant CDCensureInventoryItem(...) self-idempotent

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

Phương ánProsConsLý do từ chối
Bảng IdempotencyKey riêngTách biệt khái niệm sạch hơnThêm một bảng nữa; cùng dữ liệu đã có ở trackingDư thừa
Redis SETEX với TTLLookup nhanhMất khi flush Redis; không có audit trailMong manh; tracking vẫn cần thiết
Mode transactional / exactly-once của KafkaPhối hợp DB-KafkaPhức tạp hơn đáng kể; ràng buộc phiên bản brokerQuá mức cho workload của ta

Tham chiếu

  • inventory/src/services/inventory-worker.service.ts (idempotency check pattern)
  • inventory/src/services/material-worker.service.ts (cùng pattern cho material)
  • core/src/models/schemas/inventory/inventory-tracking/schema.ts (deduplication index)

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