cockatiel
Version:
A resilience and transient-fault-handling library that allows developers to express policies such as Backoff, Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent and thread-safe manner. Inspired by .NET Polly.
85 lines • 2.78 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BulkheadPolicy = void 0;
const abort_1 = require("./common/abort");
const defer_1 = require("./common/defer");
const Event_1 = require("./common/Event");
const Executor_1 = require("./common/Executor");
const BulkheadRejectedError_1 = require("./errors/BulkheadRejectedError");
const Errors_1 = require("./errors/Errors");
class BulkheadPolicy {
/**
* Returns the number of available execution slots at this point in time.
*/
get executionSlots() {
return this.capacity - this.active;
}
/**
* Returns the number of queue slots at this point in time.
*/
get queueSlots() {
return this.queueCapacity - this.queue.length;
}
/**
* Bulkhead limits concurrent requests made.
*/
constructor(capacity, queueCapacity) {
this.capacity = capacity;
this.queueCapacity = queueCapacity;
this.active = 0;
this.queue = [];
this.onRejectEmitter = new Event_1.EventEmitter();
this.executor = new Executor_1.ExecuteWrapper();
/**
* @inheritdoc
*/
this.onSuccess = this.executor.onSuccess;
/**
* @inheritdoc
*/
this.onFailure = this.executor.onFailure;
/**
* Emitter that fires when an item is rejected from the bulkhead.
*/
this.onReject = this.onRejectEmitter.addListener;
}
/**
* Executes the given function.
* @param fn Function to execute
* @throws a {@link BulkheadRejectedException} if the bulkhead limits are exceeeded
*/
async execute(fn, signal = abort_1.neverAbortedSignal) {
if (signal.aborted) {
throw new Errors_1.TaskCancelledError();
}
if (this.active < this.capacity) {
this.active++;
try {
return await fn({ signal });
}
finally {
this.active--;
this.dequeue();
}
}
if (this.queue.length < this.queueCapacity) {
const { resolve, reject, promise } = (0, defer_1.defer)();
this.queue.push({ signal, fn, resolve, reject });
return promise;
}
this.onRejectEmitter.emit();
throw new BulkheadRejectedError_1.BulkheadRejectedError(this.capacity, this.queueCapacity);
}
dequeue() {
const item = this.queue.shift();
if (!item) {
return;
}
Promise.resolve()
.then(() => this.execute(item.fn, item.signal))
.then(item.resolve)
.catch(item.reject);
}
}
exports.BulkheadPolicy = BulkheadPolicy;
//# sourceMappingURL=BulkheadPolicy.js.map