Files
CTFCUP-25/aws_sigma_service/api/src/functions/execution.queue.ts
2025-12-05 07:14:11 +00:00

65 lines
1.5 KiB
TypeScript

export class ExecutionQueueOverflowError extends Error {
constructor(message = "Execution queue is full") {
super(message);
this.name = "ExecutionQueueOverflowError";
}
}
type Task<T> = () => Promise<T>;
interface PendingTask {
task: () => Promise<unknown>;
resolve: (value: unknown) => void;
reject: (reason?: unknown) => void;
}
export class ExecutionQueue {
private running = 0;
private readonly queue: PendingTask[] = [];
constructor(
private readonly concurrency: number,
private readonly queueLimit: number
) {}
run<T>(task: Task<T>): Promise<T> {
if (this.running < this.concurrency) {
return this.execute(task);
}
const limit = this.queueLimit;
if (Number.isFinite(limit) && limit >= 0 && this.queue.length >= limit) {
throw new ExecutionQueueOverflowError();
}
return new Promise<T>((resolve, reject) => {
this.queue.push({
task: () => task(),
resolve: (value) => resolve(value as T),
reject,
});
});
}
private async execute<T>(task: Task<T>): Promise<T> {
this.running += 1;
try {
return await task();
} finally {
this.running -= 1;
this.processQueue();
}
}
private processQueue(): void {
while (this.running < this.concurrency && this.queue.length > 0) {
const next = this.queue.shift();
if (!next) {
return;
}
this.execute(next.task).then(next.resolve).catch(next.reject);
}
}
}