taskon
Version:
A simple JavaScript/TypeScript tasks queue that supports dynamic concurrency control
177 lines • 6.88 kB
JavaScript
;
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