@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.
420 lines (419 loc) • 12.8 kB
JavaScript
import { __decorate, __metadata } from "tslib";
import { ApiProperty } from "@nestjs/swagger";
import { BackoffType, MissedRunStrategy, TaskPeriodType, TaskStatus, } from "./tasks-model.js";
export class TaskDto {
id;
parentId;
queue;
created;
initialStart;
started;
lastHeartbeat;
finished;
status;
missedRunStrategy;
priority;
error;
backoff;
backoffType;
timeout;
name;
startAfter;
repeatInterval;
cronExpression;
repeatType;
maxAttempts;
attempt;
payload;
result;
constructor(id, parentId, queue, created, initialStart, started, lastHeartbeat, finished, status, missedRunStrategy, priority, error, backoff, backoffType, timeout, name, startAfter, repeatInterval, cronExpression, repeatType, maxAttempts, attempt, payload, result) {
this.id = id;
this.parentId = parentId;
this.queue = queue;
this.created = created;
this.initialStart = initialStart;
this.started = started;
this.lastHeartbeat = lastHeartbeat;
this.finished = finished;
this.status = status;
this.missedRunStrategy = missedRunStrategy;
this.priority = priority;
this.error = error;
this.backoff = backoff;
this.backoffType = backoffType;
this.timeout = timeout;
this.name = name;
this.startAfter = startAfter;
this.repeatInterval = repeatInterval;
this.cronExpression = cronExpression;
this.repeatType = repeatType;
this.maxAttempts = maxAttempts;
this.attempt = attempt;
this.payload = payload;
this.result = result;
}
}
export class TasksResult {
items;
total;
constructor(items, total) {
this.items = items;
this.total = total;
}
}
export var TaskDateSortField;
(function (TaskDateSortField) {
TaskDateSortField["id"] = "id";
TaskDateSortField["created"] = "created";
TaskDateSortField["initialStart"] = "initial_start";
TaskDateSortField["started"] = "started";
TaskDateSortField["lastHeartbeat"] = "last_heartbeat";
TaskDateSortField["finished"] = "finished";
TaskDateSortField["startAfter"] = "start_after";
})(TaskDateSortField || (TaskDateSortField = {}));
export var TaskSortDirection;
(function (TaskSortDirection) {
TaskSortDirection["asc"] = "asc";
TaskSortDirection["desc"] = "desc";
})(TaskSortDirection || (TaskSortDirection = {}));
export class TaskView {
id;
parentId;
queue;
created;
initialStart;
started;
lastHeartbeat;
finished;
status;
missedRunStrategy;
priority;
error;
backoff;
backoffType;
timeout;
name;
startAfter;
repeatInterval;
cronExpression;
repeatType;
maxAttempts;
attempt;
payload;
result;
static fromDto(dto) {
const res = new TaskView();
res.id = dto.id;
res.parentId = dto.parentId.orUndefined;
res.queue = dto.queue;
res.created = dto.created.getTime();
res.initialStart = dto.initialStart.getTime();
res.started = dto.started.map((d) => d.getTime()).orUndefined;
res.lastHeartbeat = dto.lastHeartbeat.map((d) => d.getTime()).orUndefined;
res.finished = dto.finished.map((d) => d.getTime()).orUndefined;
res.status = dto.status;
res.missedRunStrategy = dto.missedRunStrategy;
res.priority = dto.priority;
res.error = dto.error.orUndefined;
res.backoff = dto.backoff;
res.backoffType = dto.backoffType;
res.timeout = dto.timeout;
res.name = dto.name.orUndefined;
res.startAfter = dto.startAfter.map((d) => d.getTime()).orUndefined;
res.repeatInterval = dto.repeatInterval.orUndefined;
res.cronExpression = dto.cronExpression.orUndefined;
res.repeatType = dto.repeatType.orUndefined;
res.maxAttempts = dto.maxAttempts;
res.attempt = dto.attempt;
res.payload = dto.payload;
res.result = dto.result;
return res;
}
}
__decorate([
ApiProperty({ description: "Persistent task id." }),
__metadata("design:type", Number)
], TaskView.prototype, "id", void 0);
__decorate([
ApiProperty({
required: false,
description: "Parent task id for child tasks, if any.",
}),
__metadata("design:type", Number)
], TaskView.prototype, "parentId", void 0);
__decorate([
ApiProperty({ description: "Queue name." }),
__metadata("design:type", String)
], TaskView.prototype, "queue", void 0);
__decorate([
ApiProperty({ description: "Task creation time as Unix milliseconds." }),
__metadata("design:type", Number)
], TaskView.prototype, "created", void 0);
__decorate([
ApiProperty({
description: "Original schedule anchor as Unix milliseconds.",
}),
__metadata("design:type", Number)
], TaskView.prototype, "initialStart", void 0);
__decorate([
ApiProperty({
required: false,
description: "Current attempt start time as Unix milliseconds, if the task is active.",
}),
__metadata("design:type", Number)
], TaskView.prototype, "started", void 0);
__decorate([
ApiProperty({
required: false,
description: "Last heartbeat time as Unix milliseconds, if the task is active and has reported heartbeat.",
}),
__metadata("design:type", Number)
], TaskView.prototype, "lastHeartbeat", void 0);
__decorate([
ApiProperty({
required: false,
description: "Finish or retry-transition time as Unix milliseconds, if present.",
}),
__metadata("design:type", Number)
], TaskView.prototype, "finished", void 0);
__decorate([
ApiProperty({
enum: TaskStatus,
enumName: "TaskStatus",
description: "Current task status.",
}),
__metadata("design:type", String)
], TaskView.prototype, "status", void 0);
__decorate([
ApiProperty({
enum: MissedRunStrategy,
enumName: "MissedRunStrategy",
description: "Periodic missed-run strategy.",
}),
__metadata("design:type", String)
], TaskView.prototype, "missedRunStrategy", void 0);
__decorate([
ApiProperty({ description: "Queue priority." }),
__metadata("design:type", Number)
], TaskView.prototype, "priority", void 0);
__decorate([
ApiProperty({
required: false,
description: "Last persisted error message, if any.",
}),
__metadata("design:type", String)
], TaskView.prototype, "error", void 0);
__decorate([
ApiProperty({ description: "Base retry backoff in milliseconds." }),
__metadata("design:type", Number)
], TaskView.prototype, "backoff", void 0);
__decorate([
ApiProperty({
enum: BackoffType,
enumName: "BackoffType",
description: "Retry backoff formula.",
}),
__metadata("design:type", String)
], TaskView.prototype, "backoffType", void 0);
__decorate([
ApiProperty({ description: "Attempt timeout in milliseconds." }),
__metadata("design:type", Number)
], TaskView.prototype, "timeout", void 0);
__decorate([
ApiProperty({
required: false,
description: "Unique periodic task name, if periodic.",
}),
__metadata("design:type", String)
], TaskView.prototype, "name", void 0);
__decorate([
ApiProperty({
description: "Next eligible start time as Unix milliseconds, if any.",
}),
__metadata("design:type", Number)
], TaskView.prototype, "startAfter", void 0);
__decorate([
ApiProperty({
description: "Repeat interval in milliseconds for interval-based periodic tasks.",
}),
__metadata("design:type", Number)
], TaskView.prototype, "repeatInterval", void 0);
__decorate([
ApiProperty({
description: "Cron expression for cron-based periodic tasks.",
}),
__metadata("design:type", String)
], TaskView.prototype, "cronExpression", void 0);
__decorate([
ApiProperty({
enum: TaskPeriodType,
enumName: "TaskPeriodType",
description: "Periodic scheduling mode, if any.",
}),
__metadata("design:type", String)
], TaskView.prototype, "repeatType", void 0);
__decorate([
ApiProperty({ description: "Maximum attempts allowed." }),
__metadata("design:type", Number)
], TaskView.prototype, "maxAttempts", void 0);
__decorate([
ApiProperty({ description: "Persisted attempt counter." }),
__metadata("design:type", Number)
], TaskView.prototype, "attempt", void 0);
__decorate([
ApiProperty({ description: "Persisted worker input and runtime state." }),
__metadata("design:type", Object)
], TaskView.prototype, "payload", void 0);
__decorate([
ApiProperty({
required: false,
description: "Persisted final result, if any.",
}),
__metadata("design:type", Object)
], TaskView.prototype, "result", void 0);
export class TasksResultView {
items;
total;
}
__decorate([
ApiProperty({
type: TaskView,
isArray: true,
description: "Page items converted to plain task views.",
}),
__metadata("design:type", Array)
], TasksResultView.prototype, "items", void 0);
__decorate([
ApiProperty({
description: "Total number of matching rows before pagination.",
}),
__metadata("design:type", Number)
], TasksResultView.prototype, "total", void 0);
export class QueueStat {
queueName;
p50;
p75;
p95;
p99;
p999;
constructor(queueName, p50, p75, p95, p99, p999) {
this.queueName = queueName;
this.p50 = p50;
this.p75 = p75;
this.p95 = p95;
this.p99 = p99;
this.p999 = p999;
}
}
export class TasksCount {
queueName;
status;
count;
constructor(queueName, status, count) {
this.queueName = queueName;
this.status = status;
this.count = count;
}
}
export class QueueStatView {
queueName;
p50;
p75;
p95;
p99;
p999;
static fromDto(o) {
const res = new QueueStatView();
res.queueName = o.queueName;
res.p50 = o.p50;
res.p75 = o.p75;
res.p95 = o.p95;
res.p99 = o.p99;
res.p999 = o.p999;
return res;
}
}
__decorate([
ApiProperty({ description: "Queue name these percentiles belong to." }),
__metadata("design:type", String)
], QueueStatView.prototype, "queueName", void 0);
__decorate([
ApiProperty({ description: "50th percentile in seconds." }),
__metadata("design:type", Number)
], QueueStatView.prototype, "p50", void 0);
__decorate([
ApiProperty({ description: "75th percentile in seconds." }),
__metadata("design:type", Number)
], QueueStatView.prototype, "p75", void 0);
__decorate([
ApiProperty({ description: "95th percentile in seconds." }),
__metadata("design:type", Number)
], QueueStatView.prototype, "p95", void 0);
__decorate([
ApiProperty({ description: "99th percentile in seconds." }),
__metadata("design:type", Number)
], QueueStatView.prototype, "p99", void 0);
__decorate([
ApiProperty({ description: "99.9th percentile in seconds." }),
__metadata("design:type", Number)
], QueueStatView.prototype, "p999", void 0);
export class TasksCountView {
queueName;
status;
count;
static fromDto(o) {
const res = new TasksCountView();
res.queueName = o.queueName;
res.status = o.status;
res.count = o.count;
return res;
}
}
__decorate([
ApiProperty({ description: "Queue name." }),
__metadata("design:type", String)
], TasksCountView.prototype, "queueName", void 0);
__decorate([
ApiProperty({
enum: TaskStatus,
enumName: "TaskStatus",
description: "Task status represented by this count.",
}),
__metadata("design:type", String)
], TasksCountView.prototype, "status", void 0);
__decorate([
ApiProperty({
type: "integer",
description: "Number of tasks in this queue/status bucket.",
}),
__metadata("design:type", Number)
], TasksCountView.prototype, "count", void 0);
export class QueuesStat {
waitTime;
workTime;
tasksCount;
}
__decorate([
ApiProperty({
type: QueueStatView,
isArray: true,
description: "Queue wait-time percentile stats.",
}),
__metadata("design:type", Array)
], QueuesStat.prototype, "waitTime", void 0);
__decorate([
ApiProperty({
type: QueueStatView,
isArray: true,
description: "Queue work-time percentile stats.",
}),
__metadata("design:type", Array)
], QueuesStat.prototype, "workTime", void 0);
__decorate([
ApiProperty({
type: TasksCountView,
isArray: true,
description: "Queue/status task counts.",
}),
__metadata("design:type", Array)
], QueuesStat.prototype, "tasksCount", void 0);