@nerjs/batchloader
Version:
`BatchLoader` is a tool for batching data requests with support for deduplication, caching, and parallel task management. It is designed to enhance flexibility and performance in scenarios requiring asynchronous data processing. This module was inspired b
60 lines • 2.67 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LimitedTimekeeper = void 0;
const errors_1 = require("../utils/errors");
const unlimited_timekeeper_1 = require("./unlimited.timekeeper");
const debug_1 = require("debug");
const debug = (0, debug_1.default)('batchloader:timekeeper');
class LimitedTimekeeper extends unlimited_timekeeper_1.UnlimitedTimekeeper {
constructor({ concurrencyLimit, maxWaitingTimeMs, ...options }, metrics) {
super(options, metrics);
this.waitingTasks = [];
this.limitedOptions = { concurrencyLimit, maxWaitingTimeMs };
}
waiting() {
return this.waitingTasks.map(task => task.inner);
}
runNextWaitingTask() {
const next = this.waitingTasks.shift();
if (next) {
if (next.tid)
clearTimeout(next.tid);
debug(`Attempting to run a task from the waiting list. id="${next.id}"`);
this.runTask(next);
}
}
runTask(task) {
if (this.runnedTasks.size < this.limitedOptions.concurrencyLimit) {
super.runTask(task);
task.defer.promise.finally(() => this.runNextWaitingTask()).catch(() => { });
return;
}
const runnedTime = Date.now();
task.tid = setTimeout(() => {
debug(`A task on the waiting list is waiting longer than it should. id="${task.id}"; time="${Date.now() - runnedTime}"; maxWaitingTimeMs="${this.limitedOptions.maxWaitingTimeMs}"`);
this.abort(task.id, new errors_1.TimeoutError(this.limitedOptions.maxWaitingTimeMs));
}, this.limitedOptions.maxWaitingTimeMs)?.unref();
this.waitingTasks.push(task);
this.metrics?.waitTask?.(this.waitingTasks.length);
debug(`The task has been added to the waiting list. id="${task.id}"`);
}
findTaskById(id) {
return super.findTaskById(id) || this.waitingTasks.find(task => task.id === id) || null;
}
rejectPendingTask(task, error) {
if (this.currentTask?.id === task.id)
return super.rejectPendingTask(task, error);
this.waitingTasks = this.waitingTasks.filter(({ id }) => id !== task.id);
if (task.tid)
clearTimeout(task.tid);
this.metrics?.rejectTask?.(error, task.inner);
this.callAbortedRunner(task, error);
debug(`The task was rejected. id="${task.id}"`);
}
clear() {
super.clear();
this.waitingTasks.forEach(task => this.abort(task.inner, new errors_1.SilentAbortError('timekeeper')));
}
}
exports.LimitedTimekeeper = LimitedTimekeeper;
//# sourceMappingURL=limited.timekeeper.js.map