100 lines
3.5 KiB
TypeScript
100 lines
3.5 KiB
TypeScript
import { tap, expect } from '@push.rocks/tapbundle';
|
|
import * as lik from '../ts/index.js';
|
|
|
|
let testAsyncExecutionStack: lik.AsyncExecutionStack;
|
|
|
|
tap.test('should create a valid instance of AsyncExectionStack', async () => {
|
|
testAsyncExecutionStack = new lik.AsyncExecutionStack();
|
|
expect(testAsyncExecutionStack).toBeInstanceOf(lik.AsyncExecutionStack);
|
|
});
|
|
|
|
tap.test('should run in parallel', async (toolsArg) => {
|
|
await testAsyncExecutionStack.getExclusiveExecutionSlot(async () => {
|
|
await toolsArg.delayFor(2000);
|
|
console.log('should run first');
|
|
}, 2500);
|
|
testAsyncExecutionStack.getNonExclusiveExecutionSlot(async () => {
|
|
await toolsArg.delayFor(2000);
|
|
console.log('should run third');
|
|
}, 2500);
|
|
testAsyncExecutionStack.getNonExclusiveExecutionSlot(async () => {
|
|
await toolsArg.delayFor(1000);
|
|
console.log('should run second');
|
|
}, 2500);
|
|
await testAsyncExecutionStack.getExclusiveExecutionSlot(async () => {
|
|
console.log('should run fourth');
|
|
}, 0);
|
|
});
|
|
|
|
// Test default non-exclusive unlimited concurrency (no cap means all run together)
|
|
tap.test('default non-exclusive unlimited concurrency', async (tools) => {
|
|
const stack = new lik.AsyncExecutionStack();
|
|
// default maxConcurrency should be unlimited (Infinity)
|
|
expect(Number.isFinite(stack.getNonExclusiveMaxConcurrency())).toBe(false);
|
|
const activeCounts: number[] = [];
|
|
const tasks: Promise<void>[] = [];
|
|
for (let i = 0; i < 4; i++) {
|
|
tasks.push(
|
|
stack.getNonExclusiveExecutionSlot(async () => {
|
|
activeCounts.push(stack.getActiveNonExclusiveCount());
|
|
await tools.delayFor(20);
|
|
})
|
|
);
|
|
}
|
|
await Promise.all(tasks);
|
|
const maxActive = Math.max(...activeCounts);
|
|
expect(maxActive).toBe(4);
|
|
});
|
|
// Test respecting a non-exclusive concurrency limit
|
|
tap.test('non-exclusive respects maxConcurrency', async (tools) => {
|
|
const stack = new lik.AsyncExecutionStack();
|
|
stack.setNonExclusiveMaxConcurrency(2);
|
|
const activeCounts: number[] = [];
|
|
const tasks: Promise<void>[] = [];
|
|
for (let i = 0; i < 5; i++) {
|
|
tasks.push(
|
|
stack.getNonExclusiveExecutionSlot(async () => {
|
|
activeCounts.push(stack.getActiveNonExclusiveCount());
|
|
await tools.delayFor(50);
|
|
})
|
|
);
|
|
}
|
|
await Promise.all(tasks);
|
|
// never more than 2 at once
|
|
const maxActive = Math.max(...activeCounts);
|
|
expect(maxActive).toBeLessThanOrEqual(2);
|
|
});
|
|
|
|
// Test concurrency stats (active vs pending) for non-exclusive tasks
|
|
tap.test('non-exclusive concurrency stats reflect active and pending', async (tools) => {
|
|
const stack = new lik.AsyncExecutionStack();
|
|
stack.setNonExclusiveMaxConcurrency(2);
|
|
// initially, no tasks
|
|
expect(stack.getActiveNonExclusiveCount()).toBe(0);
|
|
expect(stack.getPendingNonExclusiveCount()).toBe(0);
|
|
|
|
// enqueue three tasks
|
|
const p1 = stack.getNonExclusiveExecutionSlot(async () => {
|
|
await tools.delayFor(30);
|
|
});
|
|
const p2 = stack.getNonExclusiveExecutionSlot(async () => {
|
|
await tools.delayFor(30);
|
|
});
|
|
const p3 = stack.getNonExclusiveExecutionSlot(async () => {
|
|
await tools.delayFor(30);
|
|
});
|
|
|
|
// give time for scheduling
|
|
await tools.delayFor(10);
|
|
// two should be running, one pending
|
|
expect(stack.getActiveNonExclusiveCount()).toBe(2);
|
|
expect(stack.getPendingNonExclusiveCount()).toBe(1);
|
|
|
|
await Promise.all([p1, p2, p3]);
|
|
// after completion, counts reset
|
|
expect(stack.getActiveNonExclusiveCount()).toBe(0);
|
|
expect(stack.getPendingNonExclusiveCount()).toBe(0);
|
|
});
|
|
|
|
export default tap.start();
|