UNPKG

taskon

Version:

A simple JavaScript/TypeScript tasks queue that supports dynamic concurrency control

177 lines 6.88 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TaskQueue = exports.MESSAGE_HUB_KEY = void 0; const base_1 = __importDefault(require("./base")); const message_hub_1 = require("./message-hub"); const type_1 = require("./type"); const utils_1 = require("./utils"); exports.MESSAGE_HUB_KEY = 'task-queue'; /** * Task queue with concurrency control. By default, all added tasks will be auto * scheduled and executed. You can use stop() and start() to control the * execution. */ class TaskQueue extends base_1.default { constructor(props = {}) { super(props); this.messageHub = new message_hub_1.MessageHub(); this.onTaskStatusUpdate = (status, task) => { this.messageHub.publish(exports.MESSAGE_HUB_KEY, status, task); }; } /** * Subscribe to the task status changes. * @param onTaskStatusUpdate The listener for task status updates */ subscribeTaskStatusChange(onTaskStatusUpdate) { this.messageHub.subscribe(exports.MESSAGE_HUB_KEY, onTaskStatusUpdate); return () => this.unsubscribeTaskStatusChange(onTaskStatusUpdate); } /** * Unsubscribe from the task status changes. * @param onTaskStatusUpdate The listener for task status updates */ unsubscribeTaskStatusChange(onTaskStatusUpdate) { this.messageHub.unsubscribe(exports.MESSAGE_HUB_KEY, onTaskStatusUpdate); } /** @internal */ async addTask(callback, taskIdOrOnStatusUpdate, onStatusUpdate) { if ((0, type_1.isTaskId)(taskIdOrOnStatusUpdate) || taskIdOrOnStatusUpdate === undefined) { return this._addTask(this._createTask(callback, taskIdOrOnStatusUpdate, onStatusUpdate)); } else { return this._addTask(this._createTask(callback, undefined, taskIdOrOnStatusUpdate)); } } /** @internal */ async addPrioritizedTask(callback, taskIdOrOnStatusUpdate, onStatusUpdate) { if ((0, type_1.isTaskId)(taskIdOrOnStatusUpdate) || taskIdOrOnStatusUpdate === undefined) { return this._addTask(this._createTask(callback, taskIdOrOnStatusUpdate, onStatusUpdate, 'important')); } else { return this._addTask(this._createTask(callback, undefined, taskIdOrOnStatusUpdate, 'important')); } } /** * Add tasks with callback functions to the queue. * @param tasks The array of tasks with callback functions, IDs, task status * update subscribers, and priorities */ async addTasks(tasks) { return Promise.all(tasks.map((task) => { var _a, _b; if (task.priority === 'important') { return this.addPrioritizedTask(task.callback, (_a = task.taskId) !== null && _a !== void 0 ? _a : (0, utils_1.getTaskId)(), task.onStatusUpdate); } else { return this.addTask(task.callback, (_b = task.taskId) !== null && _b !== void 0 ? _b : (0, utils_1.getTaskId)(), task.onStatusUpdate); } })); } /** * Clear all waited tasks from the queue. */ clearWaitedTasks() { // Wait for appending tasks to waiting queue Promise.resolve().then(() => { this.tasksWaitingQueue = []; this.prioritizedTasksWaitingQueue = []; this._log({ level: 'info' }, 'Cleared waited tasks'); }); } /** * Remove the task from waited task queue. * @param taskIdOrTask The ID of the task or task object */ removeWaitedTask(taskIdOrTask) { // Wait for appending tasks to waiting queue Promise.resolve().then(() => { const taskId = typeof taskIdOrTask === 'string' || typeof taskIdOrTask === 'number' ? taskIdOrTask : taskIdOrTask.taskId; this.tasksWaitingQueue = this.tasksWaitingQueue.filter((task) => task.taskId !== taskId); this.prioritizedTasksWaitingQueue = this.prioritizedTasksWaitingQueue.filter((task) => task.taskId !== taskId); this._log({ level: 'info' }, `Removed waited task ${taskId}`); }); } /** * Clear all failed retryable tasks from the queue. */ clearFailedRetryableTasks() { // Wait for appending tasks to waiting queue Promise.resolve().then(() => { this.failedRetryableTaskQueue = []; this._log({ level: 'info' }, 'Cleared failed retryable tasks'); }); } /** * Remove the task from failed retryable task queue. * @param taskIdOrTask The ID of the task or task object */ removeFailedRetryableTask(taskIdOrTask) { // Wait for appending tasks to waiting queue Promise.resolve().then(() => { const taskId = typeof taskIdOrTask === 'string' || typeof taskIdOrTask === 'number' ? taskIdOrTask : taskIdOrTask.taskId; this.failedRetryableTaskQueue = this.failedRetryableTaskQueue.filter((task) => task.taskId !== taskId); this._log({ level: 'info' }, `Removed failed retryable task ${taskId}`); }); } /** @internal */ _assertMemorizingTasksEnabled() { if (!this.memorizeTasks) { throw Error('Memorizing task details is not enabled'); } } /** * Get the task details with task ID. * @param taskId The ID of the task */ getTaskDetails(taskId) { this._assertMemorizingTasksEnabled(); return this.taskLookup[taskId]; } /** * Get all task details with optional matching status. * @param status The matched status or array of statuses */ getAllTasksDetails(status) { this._assertMemorizingTasksEnabled(); const allTasks = Object.values(this.taskLookup); if (Array.isArray(status)) { return allTasks.filter((task) => status.includes(task.status)); } else { return status ? allTasks.filter((task) => task.status === status) : allTasks; } } /** * Clear the task details with task ID. * @param taskId The ID of the task */ clearTaskDetails(taskId) { this._assertMemorizingTasksEnabled(); delete this.taskLookup[taskId]; this._log({ level: 'info' }, `Cleared task details ${taskId}`); } /** * Clear all task details. */ clearAllTasksDetails() { this._assertMemorizingTasksEnabled(); this.taskLookup = {}; this._log({ level: 'info' }, 'Cleared all task details'); } } exports.TaskQueue = TaskQueue; exports.default = TaskQueue; //# sourceMappingURL=index.js.map