fix(lastleg): read committed order command replays after lock waits

This commit is contained in:
2026-10-03 12:13:34 +08:00
parent 34cac9c42a
commit eadb431f33
6 changed files with 100 additions and 8 deletions
@@ -178,6 +178,12 @@ test('fresh immutable IDs drive two full cycles and preserve independent HOLD ac
await verifyReceivedOrderHold(context)
const proof=context.createdResources.phase4TailOrderControls.holdInventoryProof
assert.equal(proof.status,'VERIFIED');assert.equal(proof.restored,true);assert.equal(order.version,8)
assert.equal(proof.concurrentCommands.length,2)
for(const command of proof.concurrentCommands) {
assert.equal(command.copies,2)
assert.deepEqual(command.replies[0],command.replies[1])
assert.equal(command.replies[0].version,command.expectedVersion+1)
}
assert.equal(proof.snapshots.C2_RELEASED.positions.find(row=>row.id==='22').holdPackages,1)
assert.equal(proof.snapshots.AFTER.balances[0].availablePackages,4)
assert.equal(calls.filter(c=>c.path.endsWith('/manual')).length,2)
@@ -185,6 +191,41 @@ test('fresh immutable IDs drive two full cycles and preserve independent HOLD ac
assert.equal(calls.filter(c=>c.method==='POST'&&c.path.endsWith('/inventory/release')).length,1)
})
test('hold duplicate requests are in flight together, with bounded concurrency of two',async()=>{
const {context}=holdModel()
const originalRequest=context.request
let active=0,peak=0
context.request=async(method,path,...args)=>{
if(method!=='PUT'||!path.includes('/orders/')) return originalRequest(method,path,...args)
active++;peak=Math.max(peak,active)
try { await new Promise(resolve=>setImmediate(resolve));return await originalRequest(method,path,...args) }
finally {active--}
}
await verifyReceivedOrderHold(context)
assert.equal(peak,2)
assert.equal(active,0)
})
test('ambiguous parallel hold waits for its sibling and never starts recovery writes',async()=>{
const {context,calls}=holdModel()
const originalRequest=context.request
let holdRequests=0,siblingSettled=false
context.request=async(method,path,body,...args)=>{
if(method==='PUT' && body?.held && ++holdRequests<=2) {
if(holdRequests===1) throw new Error('lost response')
await new Promise(resolve=>setImmediate(resolve))
const response=await originalRequest(method,path,body,...args)
siblingSettled=true
return response
}
return originalRequest(method,path,body,...args)
}
await assert.rejects(verifyReceivedOrderHold(context),/lost response/)
assert.equal(siblingSettled,true)
assert.equal(context.createdResources.phase4TailOrderControls.holdInventoryProof.uncertainWrite,true)
assert.ok(!calls.some(call=>call.path.endsWith('/inventory/release')||call.body?.held===false))
})
for(const fault of ['stale marker','no evidence','wrong immutable customer','missing position','unsafe bucket','not enough stock','moved source']) {
test(`missing or unsafe fresh hold prerequisite blocks all writes: ${fault}`,async()=>{
const {context,calls}=holdModel(fault)