修复:限定幂等键精确业务域

This commit is contained in:
焦龙言
2026-07-27 18:54:50 +08:00
parent 4a321098f8
commit b6f3b1e1f0
18 changed files with 730 additions and 135 deletions
@@ -141,14 +141,14 @@ class TestDaoPublicContract(unittest.TestCase):
'get_return_by_request_idempotency_key': (
'db',
'idempotency_key',
'site_ids',
'warehouse_ids',
'source_site_id',
'target_warehouse_id',
),
'get_return_by_confirm_idempotency_key': (
'db',
'idempotency_key',
'site_ids',
'warehouse_ids',
'source_site_id',
'target_warehouse_id',
),
'get_inbound_by_id': ('db', 'inbound_id', 'warehouse_ids'),
'add_inbound': ('db', 'inbound'),
@@ -249,8 +249,6 @@ class TestDaoPublicContract(unittest.TestCase):
self.assertIs(True, return_list_signature.parameters['is_page'].default)
for method_name in (
'get_return_for_update',
'get_return_by_request_idempotency_key',
'get_return_by_confirm_idempotency_key',
'get_return_by_id',
'get_return_list',
):
@@ -259,6 +257,15 @@ class TestDaoPublicContract(unittest.TestCase):
self.assertIsNone(signature.parameters['site_ids'].default)
self.assertIsNone(signature.parameters['warehouse_ids'].default)
for method_name in (
'get_return_by_request_idempotency_key',
'get_return_by_confirm_idempotency_key',
):
with self.subTest(method=method_name):
signature = inspect.signature(getattr(OperationDao, method_name))
self.assertIs(inspect.Parameter.empty, signature.parameters['source_site_id'].default)
self.assertIs(inspect.Parameter.empty, signature.parameters['target_warehouse_id'].default)
def test_dao_source_never_controls_transaction_boundary(self) -> None:
for module in (inventory_dao_module, operation_dao_module):
with self.subTest(module=module.__name__):
@@ -609,26 +616,30 @@ class TestOperationDaoReads(unittest.IsolatedAsyncioTestCase):
OperationDao.get_inbound_by_confirm_idempotency_key,
BizInboundOrder,
'confirm_idempotency_key',
{},
),
(
OperationDao.get_shipment_by_confirm_idempotency_key,
BizShipmentOrder,
'confirm_idempotency_key',
{},
),
(OperationDao.get_filling_by_idempotency_key, BizFillingRecord, 'idempotency_key'),
(OperationDao.get_usage_by_idempotency_key, BizUsageRecord, 'idempotency_key'),
(OperationDao.get_filling_by_idempotency_key, BizFillingRecord, 'idempotency_key', {}),
(OperationDao.get_usage_by_idempotency_key, BizUsageRecord, 'idempotency_key', {}),
(
OperationDao.get_return_by_request_idempotency_key,
BizReturnOrder,
'request_idempotency_key',
{'source_site_id': 9, 'target_warehouse_id': 7},
),
(
OperationDao.get_return_by_confirm_idempotency_key,
BizReturnOrder,
'confirm_idempotency_key',
{'source_site_id': 9, 'target_warehouse_id': 7},
),
)
for method, model, key_column in cases:
for method, model, key_column, kwargs in cases:
with self.subTest(method=method.__name__):
self.db.reset_mock()
record = SimpleNamespace()
@@ -636,13 +647,17 @@ class TestOperationDaoReads(unittest.IsolatedAsyncioTestCase):
result.scalar_one_or_none.return_value = record
self.db.execute.return_value = result
actual = await method(self.db, 'same-key')
actual = await method(self.db, 'same-key', **kwargs)
self.assertIs(record, actual)
statement = self.db.execute.await_args.args[0]
sql = compile_sql(statement)
self.assertTrue(statement.get_final_froms()[0].compare(model.__table__))
self.assertIn(f"{model.__tablename__}.{key_column} = 'same-key'", sql)
if model is BizReturnOrder:
self.assertIn('biz_return_order.source_site_id = 9', sql)
self.assertIn('biz_return_order.target_warehouse_id = 7', sql)
self.assertNotIn(' OR ', sql)
self.assertNotIn('FOR UPDATE', sql)
async def test_inbound_confirm_key_pushes_warehouse_scope_into_sql(self) -> None: