test(fba): verify signed delivery ACK loss and original event recovery
This commit is contained in:
@@ -3,7 +3,7 @@ import { spawn, spawnSync } from 'node:child_process'
|
||||
import { createServer } from 'node:http'
|
||||
import { mkdtemp, readFile, rm } from 'node:fs/promises'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { join, dirname, basename, resolve } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import test from 'node:test'
|
||||
|
||||
@@ -78,6 +78,8 @@ async function fixture(selector = ['--loading-plan-id', '2100000000000000001'],
|
||||
child.kill(); await exited
|
||||
}
|
||||
await close(consumer)
|
||||
assert.equal(dirname(resolve(directory)), resolve(tmpdir()))
|
||||
assert.ok(basename(directory).startsWith('event-fault-offline-'))
|
||||
await rm(directory, { recursive: true })
|
||||
},
|
||||
}
|
||||
@@ -218,3 +220,43 @@ test('booking selector rejects malformed identities and mixed selection before s
|
||||
assert.ok(!result.stdout.includes('"ready"'))
|
||||
}
|
||||
})
|
||||
|
||||
test('delivery selector isolates the first exact delivery event and preserves its ACK-loss recovery', async t => {
|
||||
const deliveryId = '2100000000000000088'
|
||||
const proxy = await fixture(['--delivery-id', deliveryId], 'OverseasDeliveryCompleted')
|
||||
t.after(() => proxy.stop())
|
||||
await proxy.control('/mode', { mode: 'FAULT' })
|
||||
const signed = { ...event(), eventType: 'OverseasDeliveryCompleted',
|
||||
payload: { deliveryOrderId: deliveryId, sourceInboundId: '2100000000000000099' } }
|
||||
for (const unrelated of [
|
||||
{ ...signed, eventId: otherId, payload: { deliveryOrderId: '2100000000000000089' } },
|
||||
{ ...signed, eventId: otherId, payload: { deliveryId } },
|
||||
{ ...signed, eventId: otherId, payload: { loadingPlanId: deliveryId } },
|
||||
{ ...signed, eventId: otherId, eventType: 'OverseasContainerUnloaded' },
|
||||
]) assert.equal((await proxy.send(unrelated)).status, 200)
|
||||
assert.equal((await proxy.send(signed)).status, 503)
|
||||
assert.equal((await proxy.send(signed)).status, 503)
|
||||
assert.equal((await proxy.send({ ...signed, eventId: samePlanOtherId })).status, 200)
|
||||
const calls = proxy.calls.length
|
||||
assert.equal((await proxy.send({ ...signed, payload: { deliveryOrderId: '2100000000000000089' } })).status, 409)
|
||||
assert.equal(proxy.calls.length, calls)
|
||||
await proxy.control('/mode', { mode: 'PASS' })
|
||||
const recovered = await proxy.send(signed)
|
||||
assert.equal(recovered.status, 200)
|
||||
assert.equal(JSON.parse(recovered.raw).data.outcome, 'DUPLICATE')
|
||||
const status = await (await proxy.control('/status')).json()
|
||||
assert.equal(status.eventId, targetId)
|
||||
assert.deepEqual(status.records.filter(row => row.errorCode !== 'TARGET_EVENT_HASH_CONFLICT').map(row => row.outcome), ['APPLIED', 'DUPLICATE', 'DUPLICATE'])
|
||||
assert.ok(!(await readFile(proxy.log, 'utf8')).includes('sourceInboundId'))
|
||||
})
|
||||
|
||||
test('delivery selection rejects malformed IDs or a second selector before opening a listener', () => {
|
||||
for (const args of [['--delivery-id', '0'], ['--delivery-id', '../88'], ['--delivery-id', '88', '--event-id', targetId],
|
||||
['--delivery-id', '88', '--container-booking-id', '66'], ['--delivery-id', '88', '--loading-plan-id', '77']]) {
|
||||
const result = spawnSync(process.env.PYTHON || 'python', [script, '--upstream', 'http://127.0.0.1:1/internal/events',
|
||||
'--event-type', 'OverseasDeliveryCompleted', ...args], { encoding: 'utf8', timeout: 5000,
|
||||
env: { ...process.env, EVENT_FAULT_CONTROL_TOKEN: controlToken } })
|
||||
assert.equal(result.status, 2)
|
||||
assert.ok(!result.stdout.includes('"ready"'))
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user