queue-tea
Version:
A simple, robust, persistable job & task queue written in typescript. Full type safety included.
155 lines (147 loc) • 4.36 kB
JavaScript
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
var __export = (target, all) => {
__markAsModule(target);
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __reExport = (target, module2, desc) => {
if (module2 && typeof module2 === "object" || typeof module2 === "function") {
for (let key of __getOwnPropNames(module2))
if (!__hasOwnProp.call(target, key) && key !== "default")
__defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
}
return target;
};
var __toModule = (module2) => {
return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
};
// src/index.ts
__export(exports, {
default: () => src_default
});
// src/TaskQueue.ts
var import_nanoevents = __toModule(require("nanoevents"));
// src/Queue.ts
var Queue = class {
constructor(elements) {
this.tasks = [];
this.enqueue = (e) => {
this.tasks = [...this.tasks, e];
};
this.dequeue = () => {
const task = this.peek();
this.tasks = this.tasks.slice(1);
return task;
};
this.isEmpty = () => {
return this.tasks.length === 0;
};
this.peek = () => {
return !this.isEmpty() ? this.tasks[0] : void 0;
};
this.length = () => {
return this.tasks.length;
};
this.tasks = elements;
}
};
// src/utils/sleep.ts
var sleep = (delay) => new Promise((res) => setTimeout(res, delay));
// src/utils/uuid.ts
var uuid = () => "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
const r = Math.random() * 16 | 0;
return (c === "x" ? r : r & 3 | 8).toString(16);
});
// src/TaskQueue.ts
var defaultCalculateBackoff = (retryCount) => {
const noise = Math.random() * 100;
return Math.min(retryCount * 1e3, 5e3) + noise;
};
var TaskQueue = ({
initialState = [],
tasks,
onChange,
retryDelay = defaultCalculateBackoff
}) => {
const events = (0, import_nanoevents.createNanoEvents)();
const queuedTasks = new Queue(initialState);
let state = "paused";
const queueTask = (name, ...options) => {
const id = uuid();
queuedTasks.enqueue({
id,
name,
retries: 0,
options: options[0],
createdAt: Date.now()
});
if (state === "idle") {
run();
}
const task = new Promise((res, rej) => {
events.on("success", (task2) => {
if (task2.id === id) {
res();
}
events.on("fail", (task3, error) => {
if (task3.id === id) {
rej(error);
}
});
});
});
return { id, task };
};
const pause = () => {
state = "paused";
};
const isPaused = () => state === "paused";
const run = async () => {
state = "running";
while (!queuedTasks.isEmpty()) {
if (isPaused()) {
break;
}
const task = queuedTasks.peek();
if (!task) {
break;
}
try {
await tasks[task.name](task.options, {
createdAt: task.createdAt,
retries: task.retries
});
queuedTasks.dequeue();
onChange == null ? void 0 : onChange(queuedTasks.tasks);
events.emit("success", task);
} catch (e) {
events.emit("fail", task, e);
await sleep(retryDelay(++task.retries));
} finally {
events.emit("change", {
tasks: [...queuedTasks.tasks],
remainingTasks: queuedTasks.length()
});
}
}
state = "idle";
};
return {
run,
getState: () => state,
pause,
getQueueItems: () => [...queuedTasks.tasks],
addEventListener: (event, callback) => events.on(event, callback),
queueTask
};
};
// src/index.ts
var src_default = TaskQueue;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {});