@penkov/tasks_queue
Version:
A lightweight PostgreSQL-backed task queue system with scheduling, retries, backoff strategies, and priority handling. Designed for efficiency and observability in modern Node.js applications.
49 lines (48 loc) • 2.14 kB
JavaScript
import { MultiStepPayload } from "./multi-step-payload.js";
import { none, some } from "scats";
import { TaskStatus } from "./tasks-model.js";
import { TasksWorker } from "./tasks-worker.js";
export class MultiStepTask extends TasksWorker {
async handleResolvedChild(payload, activeChild, childTask, context) {
context.resolvedChildTask = some(childTask);
const nextPayload = payload.copy({
activeChild: none,
});
context.setPayload(nextPayload.toJson);
if (childTask.status === TaskStatus.finished) {
await this.childFinished(nextPayload, childTask, context, activeChild);
}
else if (childTask.status === TaskStatus.error) {
await this.childFailed(nextPayload, childTask, context, activeChild);
}
else {
throw new Error(`Inconsistent workflow state: child task with id=${childTask.id} is not terminal (status=${childTask.status})`);
}
}
async childFinished(payload, _childTask, context, _activeChild) {
await this.processNext(payload, context);
}
async childFailed(payload, childTask, _context, _activeChild) {
const childError = childTask.error === undefined ? "Unknown error" : childTask.error;
throw new Error(`Child task ${childTask.id} failed: ${childError}`);
}
async process(payload, context) {
const typedPayload = MultiStepPayload.fromJson(payload);
await typedPayload.activeChild.match({
some: async (activeChild) => {
const childTask = await context.findTask(activeChild.taskId);
await childTask.match({
some: async (task) => {
await this.handleResolvedChild(typedPayload, activeChild, task, context);
},
none: async () => {
throw new Error(`Child task with id=${activeChild.taskId} not found`);
},
});
},
none: async () => {
await this.processNext(typedPayload, context);
},
});
}
}