修复:补强使用并发幂等复核

This commit is contained in:
焦龙言
2026-07-26 21:43:55 +08:00
parent bc774c74e6
commit 33228faffc
4 changed files with 359 additions and 13 deletions
@@ -132,8 +132,12 @@ class OperationDao:
key_column: InstrumentedAttribute,
idempotency_key: str,
*extra_conditions: ColumnElement[bool],
for_update: bool = False,
) -> Any | None:
result = await db.execute(select(model).where(key_column == idempotency_key, *extra_conditions))
statement = select(model).where(key_column == idempotency_key, *extra_conditions)
if for_update:
statement = statement.with_for_update().execution_options(populate_existing=True)
result = await db.execute(statement)
return result.scalar_one_or_none()
@staticmethod
@@ -373,6 +377,8 @@ class OperationDao:
db: AsyncSession,
idempotency_key: str,
site_ids: list[int] | None = None,
*,
for_update: bool = False,
) -> BizUsageRecord | None:
return await cls._get_by_key(
db,
@@ -380,6 +386,7 @@ class OperationDao:
BizUsageRecord.idempotency_key,
idempotency_key,
*cls._usage_scope_conditions(site_ids),
for_update=for_update,
)
@classmethod
@@ -169,6 +169,7 @@ class UsageService:
query_db,
page_object.idempotency_key,
site_ids=site_ids,
for_update=False,
)
if recovered is None:
raise ServiceException(message='使用失败,数据冲突')
@@ -344,6 +345,7 @@ class UsageService:
query_db,
page_object.idempotency_key,
site_ids=site_ids,
for_update=False,
)
if existing is not None:
if not cls._is_exact_idempotent_result(existing, page_object, request_hash):
@@ -385,12 +387,38 @@ class UsageService:
cls._raise_pallet_not_accessible(current_user)
pallet = locked_pallets[0]
filling = (
await OperationDao.get_active_filling_for_update(
query_db,
inventory.active_filling_id,
)
if inventory.active_filling_id is not None
else None
)
locked_existing = await OperationDao.get_usage_by_idempotency_key(
query_db,
page_object.idempotency_key,
site_ids=site_ids,
for_update=True,
)
if locked_existing is not None:
if locked_existing.site_id != inventory.site_id or not cls._is_exact_idempotent_result(
locked_existing,
page_object,
request_hash,
):
raise ServiceException(message='使用失败,幂等键已被其他请求使用')
await cls._lock_and_reauthorize_usage_site(
query_db,
locked_existing.site_id,
current_user,
)
usage_id = locked_existing.usage_id
await query_db.rollback()
return cls._success(usage_id)
if inventory.active_filling_id is None:
raise ServiceException(message='托盘不存在活动装填周期')
filling = await OperationDao.get_active_filling_for_update(
query_db,
inventory.active_filling_id,
)
if filling is None:
raise ServiceException(message='托盘活动装填周期不存在或已关闭')