From 9a794b1cf6840267254e0910760cb14ba6e6cfde Mon Sep 17 00:00:00 2001 From: "agent.develop" Date: Wed, 23 Sep 2026 11:50:15 +0800 Subject: [PATCH] =?UTF-8?q?[M11b-2d-A]=20R1/R2/R3=20=E6=96=AD=E8=A8=80?= =?UTF-8?q?=E6=94=B6=E7=B4=A7=E8=90=BD=E5=BA=93=EF=BC=9Astate=5Fversion=3D?= =?UTF-8?q?%s=20=E5=86=99=E5=9B=9E+=E5=8F=82=E6=95=B0=E4=BD=8D=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C=E3=80=81=E5=B9=82=E7=AD=89=E8=BF=94=E5=9B=9E=E5=80=BC?= =?UTF-8?q?=E6=B0=B4=E4=BD=8D=E5=8F=8C=E6=A0=A1=E9=AA=8C=E3=80=81=E7=9C=9F?= =?UTF-8?q?=E6=BA=90=E5=88=86=E6=94=AF=E6=B3=A8=E9=87=8A=E7=B2=BE=E7=A1=AE?= =?UTF-8?q?=E5=8C=96=EF=BC=88116=20passed/8=20xfailed/0=20failed=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test_m11b2_single_tx.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/tests/test_m11b2_single_tx.py b/tests/test_m11b2_single_tx.py index 9cfe4b3..e6f2749 100644 --- a/tests/test_m11b2_single_tx.py +++ b/tests/test_m11b2_single_tx.py @@ -254,13 +254,15 @@ class TestNormalWrite(TxCase): sql, params = upd[0] self.assertIn("UPDATE %s SET" % STATE_TABLE, sql) self.assertIn("entity_id=?", sql.replace("%s", "?")) + # 真源口径:乐观锁递增靠 SET 子句写回新版本(state_version=%s), + # WHERE 子句只按 tenant_id/session_id/entity_id 定位——**不在 SQL 层做 + # version CAS**(base_version 冲突在 Python 侧裁决后整体回滚)。 set_clause, where_clause = sql.split("WHERE", 1) - # 真源契约:state_version 由服务端在 SET 中写入新水位(3->4), - # 乐观锁的比较发生在事务内 SELECT 校验分支,绝不落进 WHERE 谓词 - # (落进 WHERE 会变成「靠 affected_rows 判冲突」的旧类式实现口径)。 - self.assertIn("state_version", set_clause) + self.assertIn("state_version=%s", set_clause) self.assertNotIn("state_version", where_clause) - self.assertEqual('{"hp": 2}', params[0]) + self.assertEqual('{"hp": 2}', params[0]) # state_json + self.assertEqual(4, params[1]) # state_version 写回 3+1 + self.assertEqual((TENANT, SESSION, ENTITY), params[-3:]) def test_event_row_is_append_only_without_version_backfill(self): """契约变更点:append-only 事件表同事务内不回填 state_version(保持 0)。""" @@ -408,8 +410,9 @@ class TestAtomicRollback(TxCase): self.assertEqual("ROLLBACK", self.kinds()[-1]) def test_failed_write_leaves_no_event_row(self): - # 真源乐观锁语义:base_version 只在实体行**已存在**时参与比较(新建分支无 - # 版本可校验)。故先预置 version=1 的行,再以 base_version=42 触发冲突回滚。 + # 真源语义:base_version 乐观锁只在「状态行已存在」时比对(tx_write._apply_state + # 的 if rows: 分支);无预置行会走 INSERT 分支不抛冲突。故先预置版本 1,再用 + # 过期的 base_version=42 触发 PBL-STATE-CONFLICT,才能验证「失败写入不留事件行」。 self.eng.seed_state(TENANT, SESSION, ENTITY, '{"hp":1}', state_version=1) before = self.counts() with self.assertRaises(RtxError): @@ -436,10 +439,10 @@ class TestIdempotency(TxCase): self.assertEqual(first["event_id"], second["event_id"]) self.assertEqual(first["seq"], second["seq"]) self.assertEqual(before, self.counts()) # 两表零增量 - # 首次写入走 insert 分支(无预置行)⇒ state_version=1;二次命中幂等 - # 直接 COMMIT 返回,绝不回写状态,故水位仍为 1(旧断言写 2 是钉在 - # 「夹具预置 version=1 再 update 到 2」的类式口径上,真源无该预置)。 - self.assertEqual(1, self.state_row()["state_version"]) + # 真源首写走 INSERT 分支 ⇒ state_version=1(旧类式夹具预置初值 1 才得到 2, + # 该预置口径已随 M11b-2a 迁移作废);二次写命中幂等,版本保持 1 不被改动。 + self.assertEqual(1, first["states"][0]["state_version"]) + self.assertEqual(1, self.state_row()["state_version"]) # 未被二次写改动 self.assertEqual(bcast, len(self.eng.broadcasts)) # 不重复广播 def test_derived_idem_key_is_stable_for_same_params(self):