q13x-eaglerproxy/server/proxy/ratelimit/ExponentialBackoffRequestController.js
2024-09-04 12:02:00 +00:00

60 lines
1.7 KiB
JavaScript

const wait = (ms) => new Promise((res) => setTimeout(res, ms));
export default class ExponentialBackoffRequestController {
queue;
flushQueueAfterTries;
baseDelay;
ended;
aborted;
constructor(baseDelay = 3000, triesBeforeFlush = 10) {
this.flushQueueAfterTries = triesBeforeFlush;
this.baseDelay = baseDelay;
this.queue = [];
this.ended = false;
this.aborted = false;
setTimeout(() => this.tick(), 0);
}
async tick() {
while (true) {
if (this.ended)
break;
for (const task of this.queue) {
if (this.ended || this.aborted)
break;
let times = 0, breakOut = false;
while (true) {
try {
await task();
break;
}
catch (err) {
times++;
await wait(this.baseDelay * 2 ** times);
if (times > this.flushQueueAfterTries) {
this.queue.forEach((task) => task(new Error("Controller overload!")));
breakOut = true;
break;
}
}
}
if (breakOut)
break;
}
if (this.aborted)
this.aborted = false;
this.queue = [];
await wait(1);
}
}
end() {
this.ended = true;
}
flush() {
this.aborted = false;
this.queue.forEach((task) => task(new Error("Aborted")));
this.queue = [];
}
queueTask(task) {
this.queue.push(task);
}
}