durabull
Version:
A durable workflow engine built on top of BullMQ and Redis
84 lines (83 loc) • 2.94 kB
JavaScript
;
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;