yqueue
Version:
Yet another concurrent task queue
110 lines • 3.46 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.YBatch = exports.YBatchErrors = void 0;
const y_queue_1 = __importDefault(require("./y-queue"));
class YBatchErrors extends Error {
constructor(errors) {
var _a;
super(`Batch failed with ${errors.length} errors.`);
this.errors = errors;
this.name = new.target.name;
let s = (_a = this.stack) !== null && _a !== void 0 ? _a : super.toString();
s += '\nwrapped errors:';
this.errors.forEach((e, i) => {
s += `\n#${i}\n${e.stack}`;
});
this.stack = s;
}
toString() {
let s = super.toString();
s += '\nwrapped errors:';
for (const e of this.errors) {
s += '\n\t' + e.toString();
}
return s;
}
}
exports.YBatchErrors = YBatchErrors;
class YBatch {
constructor(options) {
this.options = options;
this.errors = [];
this.failFastWaits = [];
this.allSettledWaits = [];
this.running = 0;
this.queue = new y_queue_1.default({
concurrency: options.concurrency,
});
this.maxQueueLength =
options.maxQueueLength !== undefined && options.maxQueueLength > 0
? options.maxQueueLength
: this.queue.concurrency;
}
static isYBatchError(e) {
return e instanceof YBatchErrors;
}
async add(fn, options) {
this.running++;
await this.queue.onQueueSizeLessThan(this.maxQueueLength);
let error = null;
const task = this.queue.run(fn, options).catch(e => (error = e));
setImmediate(async () => {
await task;
if (error !== null) {
this.errors.push(error);
if (this.failFastWaits.length > 0) {
this.failFastWaits.forEach(ack => {
ack(this.errors[0]);
});
this.failFastWaits = [];
}
}
this.running--;
if (this.running === 0) {
this.allSettledWaits.forEach(ack => {
ack(this.errors);
});
this.allSettledWaits = [];
this.failFastWaits.forEach(ack => {
ack(this.errors[0]);
});
this.failFastWaits = [];
}
});
}
async failFast() {
if (this.errors.length > 0) {
throw this.errors[0];
}
if (this.running === 0) {
return;
}
return new Promise((f, r) => {
this.failFastWaits.push(e => {
if (e === undefined)
f();
else
r(e);
});
});
}
async allSettled() {
if (this.running === 0) {
if (this.errors.length === 0)
return;
throw new YBatchErrors(this.errors);
}
return new Promise(f => {
this.allSettledWaits.push(f);
}).then(errors => {
if (errors.length === 0)
return;
throw new YBatchErrors(errors);
});
}
}
exports.YBatch = YBatch;
//# sourceMappingURL=y-batch.js.map