IIqcPostingStore.cs 1.6 KB

123456789101112131415161718192021222324252627
  1. using Admin.NET.Plugin.AiDOP.MaterialWarehouse.InventoryPosting.Entity;
  2. namespace Admin.NET.Plugin.AiDOP.MaterialWarehouse.InventoryPosting.Idempotency;
  3. /// <summary>
  4. /// IQC 过账头幂等存储抽象。唯一性由 (tenant_id, domain_code, fbillno) 的 DB UNIQUE 保证;
  5. /// TryInsertAsync 依赖唯一约束原子占位——**不是** SELECT-不存在-INSERT(无并发窗口)。
  6. /// 生产实现走 SqlSugar + duplicate-key(1062) 捕获;测试实现走线程安全内存。
  7. /// </summary>
  8. public interface IIqcPostingStore
  9. {
  10. /// <summary>尝试插入过账头(PROCESSING)。UNIQUE 冲突 → Inserted=false 并尽量带出既有记录。</summary>
  11. Task<PostingInsertResult> TryInsertAsync(AdoIqcInventoryPosting posting);
  12. /// <summary>按幂等键读取既有过账头。</summary>
  13. Task<AdoIqcInventoryPosting> GetAsync(long tenantId, string domainCode, string fbillNo);
  14. /// <summary>业务提交成功/失败后回写过账状态(POSTED / FAILED)。</summary>
  15. Task UpdateStatusAsync(AdoIqcInventoryPosting posting, string status);
  16. /// <summary>
  17. /// 原子抢占 stale PROCESSING(Phase 7C):仅当 status=PROCESSING 且 update_time &lt; <paramref name="staleBefore"/>
  18. /// 时把 update_time 刷新为 <paramref name="now"/> 并返回 true(心跳续租=抢占成功)。**单条件更新原子完成**,
  19. /// 不做 SELECT-then-UPDATE,杜绝竞态窗口——并发多路仅一路 rows=1。lease 未过期或已被他路抢占 → false。
  20. /// </summary>
  21. Task<bool> TryRecoverStaleAsync(long tenantId, string domainCode, string fbillNo, DateTime staleBefore, DateTime now);
  22. }