mirror of
https://github.com/WorldEditAxe/eaglerproxy.git
synced 2024-11-14 09:36:04 -08:00
60 lines
1.7 KiB
JavaScript
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);
|
||
|
}
|
||
|
}
|