fix(gateway,loop,tool): 解耦「工具互斥身份」与「checkpoint 归属」(修普通回合不受保护)
缺口:「1 普通回合 + 1 并行路」时普通回合既不登记也不被检查 —— 因为互斥身份取自 loop.ParallelLegFrom,而网关只给 parallel=true 那一路盖它。直接给普通回合盖 WithParallelLeg 会把它的 checkpoint 键从 sess 变成 sess#turn-x(改崩溃恢复语义),故改为两条独立通道: - 工具互斥身份:loop.WithToolLegID / ToolLegIDFrom(新增),网关在 beginLegLocked 内【无条件】盖, 取值 = 本路 turnID ⇒ 普通回合 / 队首续跑路 / 并行路 三条路都覆盖 - checkpoint 归属:WithParallelLeg 一行未改,仍只有真并行路 ⇒ 恢复语义零变化 守门断言 TestCheckpointOwnerIgnoresToolLegID:普通回合 ctx 下 AgentID 必须逐字仍是 sess。 变异 3 条:互斥身份回退只认 ParallelLegFrom(判忙失效)/ 顺手把 checkpoint 改读新通道 (守门断言红,证明确实解耦)/ 普通回合不盖身份(判忙失效)。 另修 race:-race -count=2 三包全绿;诚实边界含一个既有竞态(同一路并发登记共享,建议后续小切片)。
This commit is contained in:
1 parent
d64b26d499
commit
ef3dcb699b
9 files changed
+673
-53
No files matched your search
@@ -266,6 +266,15 @@ func TestParallelOmittedKeepsQueueingBehaviour(t *testing.T) {
|
||||
if loop.TurnIDFrom(calls[1].ctx) == loop.TurnIDFrom(calls[0].ctx) {
|
||||
t.Fatal("续跑路必须是一条**新路**,turnId 不能与上一路相同")
|
||||
}
|
||||
// 工具互斥身份是**另一条通道**(design/15 §2.5.7):续跑路同样必须带上它,
|
||||
// 取值就是它自己的 turnId —— 否则串行续跑路在写类工具上不受保护。它与
|
||||
// checkpoint 归属键无关,所以上面那条「空串」断言不该被它推翻。
|
||||
if got := loop.ToolLegIDFrom(calls[1].ctx); got != loop.TurnIDFrom(calls[1].ctx) {
|
||||
t.Fatalf("续跑路的互斥身份 = %q, want %q(每一路都要盖)", got, loop.TurnIDFrom(calls[1].ctx))
|
||||
}
|
||||
if loop.ToolLegIDFrom(calls[1].ctx) == loop.ToolLegIDFrom(calls[0].ctx) {
|
||||
t.Fatal("两条路的互斥身份必须不同,否则同文件写会被当成「同一路自己的调用」而放行")
|
||||
}
|
||||
drains := f.sink.ofType(EventPendingDrain)
|
||||
if len(drains) != 1 || stateInt(drains[0], "activeTurns") != 1 {
|
||||
t.Fatalf("pending_drain = %v, want 一帧且 activeTurns=1", drains)
|
||||
|
||||
Reference in new issue
Block a user