UNPKG

durabull

Version:

A durable workflow engine built on top of BullMQ and Redis

84 lines (83 loc) 2.94 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Activity = void 0; const errors_1 = require("./errors"); class Activity { constructor() { this.tries = 0; // 0 = retry forever this.timeout = 0; // seconds, 0 = no limit this.lastHeartbeat = Date.now(); } backoff() { return [1, 2, 5, 10, 30, 60, 120]; } heartbeat() { this.lastHeartbeat = Date.now(); if (this.context) { void this.context.heartbeat(); } } workflowId() { if (!this.context) { throw new Error('workflowId() can only be called during activity execution'); } return this.context.workflowId; } get signal() { return this.context?.signal; } _setContext(context) { this.context = context; this.lastHeartbeat = Date.now(); } _getLastHeartbeat() { return this.lastHeartbeat; } async _executeWithRetry(...args) { const maxAttempts = this.tries === 0 ? 1000000 : (this.tries || 1); const backoffSchedule = this.backoff(); let attempt = 0; let lastError; while (attempt < maxAttempts) { try { if (this.context) { this.context.attempt = attempt; } if (this.timeout && this.timeout > 0) { const timeoutMs = this.timeout * 1000; return await new Promise((resolve, reject) => { const timer = setTimeout(() => { reject(new Error(`Activity timeout after ${timeoutMs}ms`)); }, timeoutMs); this.execute(...args) .then(result => { clearTimeout(timer); resolve(result); }) .catch(error => { clearTimeout(timer); reject(error); }); }); } return await this.execute(...args); } catch (error) { lastError = error; if (error instanceof errors_1.NonRetryableError) { throw error; } attempt++; if (attempt >= maxAttempts) { break; } const backoffIndex = Math.min(attempt - 1, backoffSchedule.length - 1); const delaySec = backoffSchedule[backoffIndex] || backoffSchedule[backoffSchedule.length - 1]; const delayMs = delaySec * 1000; await new Promise(resolve => setTimeout(resolve, delayMs)); } } throw lastError || new Error('Activity execution failed'); } } exports.Activity = Activity;