UNPKG

redis-smq-common

Version:

Provides essential components and utilities shared across RedisSMQ packages.

88 lines 3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Backoff = void 0; const index_js_1 = require("../runnable/index.js"); const index_js_2 = require("../errors/index.js"); const index_js_3 = require("../timer/index.js"); const backoff_config_js_1 = require("./backoff-config.js"); class Backoff extends index_js_1.Runnable { constructor(logger, config = {}) { super(); this.attempts = 0; this.logger = logger.createLogger(this.constructor.name); this.config = backoff_config_js_1.BackoffConfig.parseConfig(config); this.timer = new index_js_3.Timer(this.logger); this.logger.debug(`Backoff initialized: baseDelay=${this.config.baseDelay}ms, maxDelay=${this.config.maxDelay}ms`); } runTask(task, callback) { if (!this.isOperational()) { return callback(new Error('Backoff is not operational')); } this.attempts++; task((err, result) => { if (err) { if (err instanceof index_js_2.AbortError) { return callback(err); } this.logger.debug(`Operation failed:`, err.message); if (this.config.maxAttempts && this.attempts >= this.config.maxAttempts) { return callback(err); } this.scheduleRetry(task, callback); return; } this.reset(); callback(null, result); }); } scheduleRetry(task, callback) { if (!this.isOperational()) { return callback(new Error('Backoff is not operational')); } const delay = this.calculateNextDelay(); this.timer.schedule(() => { this.runTask(task, callback); }, delay); } calculateNextDelay() { const { baseDelay, maxDelay, jitter } = this.config; let delay = this.getNextDelay(baseDelay, this.attempts); delay = Math.max(delay, baseDelay); if (jitter) { const range = delay * 0.2; delay = delay + (Math.random() * range * 2 - range); } delay = Math.min(delay, maxDelay); return Math.max(1, Math.floor(delay)); } goingUp() { return super.goingUp().concat([(cb) => this.timer.run(cb)]); } goingDown() { return [ (cb) => { this.reset(); this.timer.shutdown(cb); }, ].concat(super.goingDown()); } getConfig() { return Object.assign({}, this.config); } execute(task, callback) { if (!this.isOperational()) { return callback(new Error('Backoff instance is not operational')); } this.runTask(task, callback); } getAttempts() { return this.attempts; } reset() { this.timer.reset(); this.attempts = 0; } } exports.Backoff = Backoff; //# sourceMappingURL=backoff.js.map