Files
taskbuffer/test/test.8.bufferedrun.ts

152 lines
3.8 KiB
TypeScript
Raw Normal View History

import { tap, expect } from '@git.zone/tstest/tapbundle';
2021-11-11 19:59:56 +01:00
2022-03-25 12:14:49 +01:00
import * as taskbuffer from '../ts/index.js';
import * as smartdelay from '@push.rocks/smartdelay';
2021-11-11 19:59:56 +01:00
// Test 1: Basic buffered execution with afterTask chain
tap.test('should run buffered tasks with afterTask chain', async () => {
let counter1 = 0;
let counter2 = 0;
let counter3 = 0;
2021-11-11 19:59:56 +01:00
const task3 = new taskbuffer.Task({
name: 'buffered-chain-3',
2021-11-11 19:59:56 +01:00
taskFunction: async () => {
counter3++;
await smartdelay.delayFor(50);
2021-11-11 19:59:56 +01:00
},
buffered: true,
bufferMax: 1,
});
2021-11-11 19:59:56 +01:00
const task2 = new taskbuffer.Task({
name: 'buffered-chain-2',
2021-11-11 19:59:56 +01:00
taskFunction: async () => {
counter2++;
await smartdelay.delayFor(50);
2021-11-11 19:59:56 +01:00
},
buffered: true,
bufferMax: 1,
afterTask: () => task3,
2021-11-11 19:59:56 +01:00
});
const task1 = new taskbuffer.Task({
name: 'buffered-chain-1',
2021-11-11 19:59:56 +01:00
taskFunction: async () => {
counter1++;
await smartdelay.delayFor(50);
2021-11-11 19:59:56 +01:00
},
buffered: true,
2021-11-11 20:48:31 +01:00
bufferMax: 1,
afterTask: () => task2,
});
// Trigger 3 times with enough spacing for the chain to complete
for (let i = 0; i < 3; i++) {
task1.trigger();
await smartdelay.delayFor(250); // enough for chain of 3 x 50ms tasks
}
// Wait for final chain to finish
await smartdelay.delayFor(500);
// Each task in the chain should have run at least once
expect(counter1).toBeGreaterThanOrEqual(1);
expect(counter2).toBeGreaterThanOrEqual(1);
expect(counter3).toBeGreaterThanOrEqual(1);
// afterTask chain means task2 count should match task1 (each trigger chains)
expect(counter2).toEqual(counter1);
expect(counter3).toEqual(counter1);
});
// Test 2: bufferMax limits concurrent buffered executions
tap.test('should respect bufferMax for concurrent buffered calls', async () => {
let running = 0;
let maxRunning = 0;
let totalRuns = 0;
const task = new taskbuffer.Task({
name: 'buffer-max-test',
taskFunction: async () => {
running++;
maxRunning = Math.max(maxRunning, running);
totalRuns++;
await smartdelay.delayFor(100);
running--;
},
buffered: true,
bufferMax: 2,
2021-11-11 19:59:56 +01:00
});
// Fire many triggers rapidly — only bufferMax should run concurrently
for (let i = 0; i < 10; i++) {
2021-11-11 19:59:56 +01:00
task.trigger();
}
// Wait for all buffered executions to complete
await smartdelay.delayFor(1000);
expect(maxRunning).toBeLessThanOrEqual(2);
expect(totalRuns).toBeGreaterThanOrEqual(1);
});
// Test 3: bufferMax limits how many runs are queued during execution
tap.test('should limit queued runs to bufferMax during execution', async () => {
let runCount = 0;
const task = new taskbuffer.Task({
name: 'buffer-queue-test',
taskFunction: async () => {
runCount++;
await smartdelay.delayFor(100);
},
buffered: true,
bufferMax: 2,
});
// Rapid-fire 5 triggers — bufferMax:2 means counter caps at 2
// so only 2 runs will happen (the initial run + 1 buffered rerun)
task.trigger();
task.trigger();
task.trigger();
task.trigger();
task.trigger();
await smartdelay.delayFor(500);
expect(runCount).toEqual(2);
});
// Test 4: Triggers spaced after completion queue new runs
tap.test('should re-trigger after previous buffered run completes', async () => {
let runCount = 0;
const task = new taskbuffer.Task({
name: 'retrigger-test',
taskFunction: async () => {
runCount++;
await smartdelay.delayFor(50);
},
buffered: true,
bufferMax: 1,
});
// First trigger starts execution
task.trigger();
// Wait for it to complete
await smartdelay.delayFor(100);
// Second trigger starts a new execution (task is now idle)
task.trigger();
await smartdelay.delayFor(100);
// Third trigger
task.trigger();
await smartdelay.delayFor(100);
expect(runCount).toEqual(3);
2021-11-11 20:48:31 +01:00
});
2021-11-11 19:59:56 +01:00
export default tap.start();