fix(test): require precise database lock conflict during rollback
This commit is contained in:
@@ -67,6 +67,11 @@ export function requestRollbackDeparture(context,path,body,token) {
|
||||
// database timeout needs the existing 60-second, single-attempt request path.
|
||||
return context.requestWithBody('POST',path,body,token)
|
||||
}
|
||||
export function assertDatabaseLockConflict(response) {
|
||||
demand(response?.http===200&&String(response.body?.code)==='A0409'
|
||||
&&response.body?.message==='资源正在处理中,请稍后重试'
|
||||
&&response.requestId&&response.traceId,'EXPECTED_DATABASE_LOCK_CONFLICT_REQUIRED')
|
||||
}
|
||||
async function remote(env,scope,mode) {
|
||||
const script=buildRollbackRemoteScript(scope,mode,env.FBA_CORE_JENKINS_AGENT)
|
||||
const response=await fetch(new URL('scriptText',env.JENKINS_URL.replace(/\/?$/,'/')),{method:'POST',redirect:'error',signal:AbortSignal.timeout(mode==='LEASE'?95000:45000),headers:{Authorization:'Basic '+Buffer.from(env.JENKINS_USER+':'+env.JENKINS_API_TOKEN).toString('base64'),'Content-Type':'application/x-www-form-urlencoded'},body:new URLSearchParams({script})})
|
||||
@@ -110,8 +115,7 @@ export function createDepartureRollbackVerifier(env,config,runtime) {
|
||||
report.consistentSnapshot={beforeSha256:createHash('sha256').update(canonical(ready)).digest('hex'),afterSha256:createHash('sha256').update(canonical(restored)).digest('hex')}
|
||||
demand(report.consistentSnapshot.beforeSha256===report.consistentSnapshot.afterSha256,'FULL_TWO_CUSTOMER_ROLLBACK_SNAPSHOT_CHANGED')
|
||||
demand(!report.response.error&&report.response.value?.http!==0,'DEPARTURE_OUTCOME_UNKNOWN_RETAIN_ORIGINAL_COMMAND')
|
||||
const response=report.response.value
|
||||
demand(response.http===500||(response.http===200&&String(response.body?.code)==='S0500'),'EXPECTED_DATABASE_FAILURE_RESPONSE_REQUIRED')
|
||||
assertDatabaseLockConflict(report.response.value)
|
||||
// The caller also checks restoration before sending the same original command.
|
||||
report.verified=true;return report
|
||||
}catch(error){report.error=error.message;throw error}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import test from 'node:test'
|
||||
import assert from 'node:assert/strict'
|
||||
import { validateRollbackScope, rollbackSql, buildRollbackRemoteScript, assertMidTransactionObservation, runTripRollback, requestRollbackDeparture } from './fleet-trip-rollback-test-env.mjs'
|
||||
import { validateRollbackScope, rollbackSql, buildRollbackRemoteScript, assertMidTransactionObservation, runTripRollback, requestRollbackDeparture, assertDatabaseLockConflict } from './fleet-trip-rollback-test-env.mjs'
|
||||
const scope={marker:'OWN_RUN',tripNo:'TR-OWN',firstCustomerId:'101',secondCustomerId:'102',firstDispatchId:'201',secondDispatchId:'202',firstOutboundId:'301',secondPalletId:'401',firstDispatchNo:'DS-OWN',expectedImage:'sha256:'+'a'.repeat(64)}
|
||||
const rows=()=>[{collection:'lease',connectionId:11,lockId:'99'},{collection:'wait',requester:12,blocker:11,lockId:'99'},
|
||||
{collection:'firstDispatch',id:'201',status:'DEPARTED',shipped:1},{collection:'firstOutbound',id:'301',status:'OUTBOUNDED'},{collection:'firstReplay',count:1}]
|
||||
@@ -10,6 +10,12 @@ test('fault request allows database timeout and never retries an unknown write',
|
||||
assert.equal((await requestRollbackDeparture(context,'/owned/depart',body,'owned-token')).http,0)
|
||||
assert.deepEqual(calls,[['POST','/owned/depart',body,'owned-token']])
|
||||
})
|
||||
test('database conflict requires exact handler response and trace, not arbitrary rejection',()=>{
|
||||
const response={http:200,body:{code:'A0409',message:'资源正在处理中,请稍后重试'},requestId:'request',traceId:'trace'}
|
||||
assert.doesNotThrow(()=>assertDatabaseLockConflict(response))
|
||||
for(const wrong of [{http:0},{http:500},{body:{code:'S0500',message:'error'}},{body:{code:'A0409',message:'请完成拣货'}},{traceId:null}])
|
||||
assert.throws(()=>assertDatabaseLockConflict({...response,...wrong}))
|
||||
})
|
||||
test('plan and import are network-free; execution rejects missing TEST profile before any network',async()=>{
|
||||
const plan=await runTripRollback({execute:false},{env:{}})
|
||||
assert.equal(plan.businessSqlWrites,false);assert.equal(plan.deployment,false)
|
||||
|
||||
Reference in New Issue
Block a user