修复:消除使用幂等缺失键间隙锁

This commit is contained in:
焦龙言
2026-07-26 22:34:46 +08:00
parent 33228faffc
commit cda87a4d65
4 changed files with 291 additions and 100 deletions
@@ -169,7 +169,6 @@ class UsageService:
query_db,
page_object.idempotency_key,
site_ids=site_ids,
for_update=False,
)
if recovered is None:
raise ServiceException(message='使用失败,数据冲突')
@@ -340,17 +339,16 @@ class UsageService:
try:
request_hash = cls._build_request_hash(page_object)
user_id, user_name = cls._current_identity(current_user)
site_ids = await cls._site_scope(query_db, current_user)
preflight_site_ids = await cls._site_scope(query_db, current_user)
existing = await OperationDao.get_usage_by_idempotency_key(
query_db,
page_object.idempotency_key,
site_ids=site_ids,
for_update=False,
site_ids=preflight_site_ids,
)
if existing is not None:
if not cls._is_exact_idempotent_result(existing, page_object, request_hash):
raise ServiceException(message='使用失败,幂等键已被其他请求使用')
if site_ids is not None and existing.site_id not in site_ids:
if preflight_site_ids is not None and existing.site_id not in preflight_site_ids:
cls._raise_usage_not_accessible(current_user)
await cls._lock_and_reauthorize_usage_site(
query_db,
@@ -367,10 +365,12 @@ class UsageService:
)
if scanned_pallet is None:
cls._raise_pallet_not_accessible(current_user)
scanned_pallet_id = int(scanned_pallet.pallet_id)
await query_db.rollback()
inventory = await InventoryDao.get_inventory_for_update(
query_db,
scanned_pallet.pallet_id,
scanned_pallet_id,
)
if inventory is None:
cls._raise_pallet_not_accessible(current_user, '托盘库存不存在')
@@ -378,6 +378,7 @@ class UsageService:
cls._raise_pallet_not_accessible(current_user, '托盘不在客户现场')
expected_site_id = inventory.site_id
await cls._assert_pallet_site_access(query_db, current_user, inventory.site_id)
locked_site_ids = await cls._site_scope(query_db, current_user)
locked_pallets = await InventoryDao.get_pallets_by_ids(
query_db,
@@ -398,8 +399,7 @@ class UsageService:
locked_existing = await OperationDao.get_usage_by_idempotency_key(
query_db,
page_object.idempotency_key,
site_ids=site_ids,
for_update=True,
site_ids=locked_site_ids,
)
if locked_existing is not None:
if locked_existing.site_id != inventory.site_id or not cls._is_exact_idempotent_result(