24 lines
2.8 KiB
JavaScript
24 lines
2.8 KiB
JavaScript
import test from 'node:test';
|
|||
|
|
import assert from 'node:assert/strict';
|
||
|
|
import {collectorAdmission} from '../scripts/debug-collector-admission.mjs';
|
||
|
|
|
||
|
|
test('unfinished requests and accumulated body bytes have independent global bounds',()=>{
|
||
|
|
const gate=collectorAdmission({maxRequests:2,maxBufferedBytes:16,maxRequestBytes:12}),a=gate.acquire(),b=gate.acquire();assert.equal(gate.acquire(),null);
|
||
|
|
assert.equal(a.add(10),null);assert.equal(b.add(7),'buffer-limit');assert.equal(b.add(6),null);assert.equal(a.add(3),'body-limit');
|
||
|
|
assert.equal(gate.summary().activeRequests,2);assert.equal(gate.summary().bufferedBytes,16);a.release();a.release();assert.equal(gate.summary().bufferedBytes,6);b.release();
|
||
|
|
assert.equal(gate.summary().activeRequests,0);assert.equal(gate.summary().bufferedBytes,0);assert.equal(gate.summary().requestLimitRejected,1);assert.equal(gate.summary().bufferLimitRejected,1);assert.equal(gate.summary().bodyLimitRejected,1);
|
||
|
|
});
|
||
|
|
test('commit jobs serialize and acknowledge only after the held commit completes',async()=>{
|
||
|
|
const gate=collectorAdmission({maxRequests:2}),a=gate.acquire(),b=gate.acquire();let release;const held=new Promise(resolve=>{release=resolve;}),steps=[];
|
||
|
|
const first=a.enqueue(async()=>{steps.push('first-start');await held;steps.push('first-committed');return 'committed';});const second=b.enqueue(()=>{steps.push('second-committed');return 'second';});
|
||
|
|
await new Promise(resolve=>setImmediate(resolve));assert.deepEqual(steps,['first-start']);assert.equal(gate.summary().queuedCommits,1);release();assert.equal(await first,'committed');assert.equal(await second,'second');assert.deepEqual(steps,['first-start','first-committed','second-committed']);
|
||
|
|
a.release();b.release();const summary=gate.summary();assert.equal(summary.commits,2);assert.equal(summary.commitFailures,0);assert.ok(summary.maxQueueWaitMs>=0);assert.ok(summary.maxCommitMs>=0);
|
||
|
|
});
|
||
|
|
test('aborted queued requests cannot grow the waiting queue or execute cancelled work',async()=>{
|
||
|
|
const scheduled=[],gate=collectorAdmission({maxRequests:1,defer:fn=>scheduled.push(fn)});
|
||
|
|
for(let n=0;n<100;n++){const lease=gate.acquire();const rejected=assert.rejects(lease.enqueue(()=>assert.fail('Cancelled batch committed')));lease.release();await rejected;assert.equal(gate.summary().queuedCommits,0);}
|
||
|
|
for(const run of scheduled)await run();assert.equal(gate.summary().activeRequests,0);assert.equal(gate.summary().commits,0);
|
||
|
|
});
|
||
|
|
test('failed commits stay failed and record bounded numeric timings without raw errors',async()=>{
|
||
|
|
const gate=collectorAdmission(),lease=gate.acquire();await assert.rejects(lease.enqueue(()=>{throw Error('private-body');}));lease.release();const summary=gate.summary();assert.equal(summary.commits,0);assert.equal(summary.commitFailures,1);assert.equal(JSON.stringify(summary).includes('private-body'),false);
|
||
|
|
});
|