2025-05-26 07:56:05 -06:00
|
|
|
export default class TaskQueue {
|
2025-05-26 14:31:12 -06:00
|
|
|
constructor(
|
|
|
|
|
maxTasksPerSecond = 4,
|
|
|
|
|
maxSimultaneousTasks = 8,
|
|
|
|
|
maxQueueLength = 20
|
|
|
|
|
) {
|
2025-05-26 07:56:05 -06:00
|
|
|
this.maxTasksPerSecond = maxTasksPerSecond;
|
2025-05-26 14:31:12 -06:00
|
|
|
this.maxQueueLength = maxQueueLength;
|
2025-05-26 07:56:05 -06:00
|
|
|
this.maxSimultaneousTasks = maxSimultaneousTasks;
|
|
|
|
|
this.queue = [];
|
|
|
|
|
this.processing = false;
|
|
|
|
|
this.lastProcessTime = 0;
|
|
|
|
|
this.taskCount = 0;
|
|
|
|
|
this.tasksWaiting = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-26 14:31:12 -06:00
|
|
|
async enqueue(taskFunction, that = this, ...args) {
|
2025-05-26 07:56:05 -06:00
|
|
|
return new Promise((resolve, reject) => {
|
2025-05-26 14:31:12 -06:00
|
|
|
if (this.queue.length >= this.maxQueueLength) {
|
|
|
|
|
reject(new Error("Queue is full. Maximum queue size exceeded."));
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-05-26 07:56:05 -06:00
|
|
|
this.queue.push({
|
|
|
|
|
taskFunction,
|
|
|
|
|
that,
|
|
|
|
|
args,
|
|
|
|
|
resolve,
|
|
|
|
|
reject,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!this.processing) {
|
|
|
|
|
this.processQueue();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async processQueue() {
|
|
|
|
|
if (this.processing || this.queue.length === 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.processing = true;
|
|
|
|
|
|
|
|
|
|
while (this.queue.length > 0) {
|
|
|
|
|
const now = Date.now();
|
|
|
|
|
|
|
|
|
|
if (now - this.lastProcessTime >= 1000) {
|
|
|
|
|
this.taskCount = 0;
|
|
|
|
|
this.lastProcessTime = now;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
this.taskCount >= this.maxTasksPerSecond ||
|
|
|
|
|
this.tasksWaiting >= this.maxSimultaneousTasks
|
|
|
|
|
) {
|
|
|
|
|
const waitTime = 1000 - (now - this.lastProcessTime);
|
|
|
|
|
await this.sleep(waitTime);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const task = this.queue.shift();
|
|
|
|
|
this.taskCount++;
|
|
|
|
|
this.tasksWaiting++;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const result = await task.taskFunction.apply(task.that, task.args);
|
|
|
|
|
this.tasksWaiting--;
|
|
|
|
|
task.resolve(result);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
task.reject(error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.processing = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sleep(ms) {
|
|
|
|
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getStatus() {
|
|
|
|
|
return {
|
|
|
|
|
queueLength: this.queue.length,
|
|
|
|
|
maxQueueSize: this.maxQueueSize,
|
|
|
|
|
tasksPerSecond: this.maxTasksPerSecond,
|
|
|
|
|
currentTaskCount: this.taskCount,
|
|
|
|
|
isProcessing: this.processing,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|