You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cvm/lib/tasks/tracker.js

108 lines
2.7 KiB
JavaScript

'use strict';
const assureArray = require("assure-array");
const createEventEmitter = require("create-event-emitter");
const uuid = require("uuid");
const findAndSplice = require("../find-and-splice");
module.exports = function createTaskTracker() {
let tasks = [];
return createEventEmitter({
addTask: function addTask(name, indicator, userIds, roleIds, options) {
let mergedOptions = Object.assign({
removeWhenDone: true
}, options);
let indicatorType;
if (typeof indicator.completed === "function" && typeof indicator.finish === "function") {
indicatorType = "are-we-there-yet";
} else if (typeof indicator.await === "function" && typeof indicator.report === "function") {
indicatorType = "progress-indicator";
} else {
throw new Error("Unrecognized indicator type");
}
let task = createEventEmitter({
id: uuid.v4(),
name: name,
started: Date.now(),
userIds: assureArray(userIds),
roleIds: assureArray(roleIds),
indicator: indicator,
type: indicatorType,
progress: 0,
lastOperation: null,
lastUpdated: null
});
let reportChange = () => {
this.emit("progress", task, task.progress, task.lastOperation);
task.emit("progress", task.progress, task.lastOperation);
}
let reportCompleted = () => {
this.emit("completed", task);
task.emit("completed");
if (mergedOptions.removeWhenDone) {
this.removeTask(task);
}
}
tasks.push(task);
if (indicatorType === "are-we-there-yet") {
indicator.on("change", (name, completed, tracker) => {
task.progress = completed;
task.lastOperation = name;
task.lastUpdated = Date.now();
reportChange();
if (completed === 1) {
reportCompleted();
}
});
} else if (indicatorType === "progress-indicator") {
indicator.on("progress", (progress, description, completed, total) => {
task.progress = progress;
task.lastOperation = description;
task.lastUpdated = Date.now();
reportChange();
});
indicator.on("completed", () => {
reportCompleted();
});
}
this.emit("newTask", task);
assureArray(userIds).forEach((userId) => {
this.emit(`newTask:user:${userId}`, task);
});
assureArray(roleIds).forEach((roleId) => {
this.emit(`newTask:role:${roleId}`, task);
});
return task;
},
removeTask: function removeTask(task) {
// FIXME: Do we need to remove event handlers to prevent a memory leak here?
findAndSplice(tasks, task);
},
byUser: function getTasksByUser(userId) {
return tasks.filter((task) => task.userIds.includes(userId));
},
byRole: function getTasksByRole(roleId) {
return tasks.filter((task) => task.roleIds.includes(roleId))
},
all: function getAllTasks() {
return tasks;
}
});
}