diff --git a/libs/Task.js b/libs/Task.js index 94fac91..a0544f9 100644 --- a/libs/Task.js +++ b/libs/Task.js @@ -1,6 +1,7 @@ "use strict"; let assert = require('assert'); let fs = require('fs'); +let rmdir = require('rimraf'); let odmRunner = require('./odmRunner'); let statusCodes = require('./statusCodes'); @@ -13,9 +14,8 @@ module.exports = class Task{ this.uuid = uuid; this.name = name != "" ? name : "Task of " + (new Date()).toISOString(); this.dateCreated = new Date().getTime(); - this.status = { - code: statusCodes.QUEUED - }; + this.processingTime = -1; + this.setStatus(statusCodes.QUEUED); this.options = {}; this.output = []; this.runnerProcess = null; @@ -42,6 +42,11 @@ module.exports = class Task{ return `data/${this.uuid}`; } + // Deletes files and folders related to this task + cleanup(cb){ + rmdir(this.getProjectFolderPath(), cb); + } + setStatus(code, extra){ this.status = { code: code @@ -51,17 +56,53 @@ module.exports = class Task{ } } + updateProcessingTime(resetTime){ + this.processingTime = resetTime ? + -1 : + new Date().getTime() - this.dateCreated; + } + + startTrackingProcessingTime(){ + this.updateProcessingTime(); + if (!this._updateProcessingTimeInterval){ + this._updateProcessingTimeInterval = setInterval(() => { + this.updateProcessingTime(); + }, 1000); + } + } + + stopTrackingProcessingTime(resetTime){ + this.updateProcessingTime(resetTime); + if (this._updateProcessingTimeInterval){ + clearInterval(this._updateProcessingTimeInterval); + this._updateProcessingTimeInterval = null; + } + } + getStatus(){ return this.status.code; } + isCanceled(){ + return this.status.code === statusCodes.CANCELED; + } + // Cancels the current task (unless it's already canceled) cancel(cb){ if (this.status.code !== statusCodes.CANCELED){ + let wasRunning = this.status.code === statusCodes.RUNNING; this.setStatus(statusCodes.CANCELED); + + if (wasRunning && this.runnerProcess){ + // TODO: this does guarantee that + // the process will immediately terminate. + // In fact, often times ODM will continue running for a while + // This might need to be fixed on ODM's end. + this.runnerProcess.kill('SIGINT'); + this.runnerProcess = null; + } - console.log("Requested to cancel " + this.name); - // TODO + this.stopTrackingProcessingTime(true); cb(null); }else{ cb(new Error("Task already cancelled")); @@ -72,6 +113,7 @@ module.exports = class Task{ // This will spawn a new process. start(done){ if (this.status.code === statusCodes.QUEUED){ + this.startTrackingProcessingTime(); this.setStatus(statusCodes.RUNNING); this.runnerProcess = odmRunner.run({ projectPath: `${__dirname}/../${this.getProjectFolderPath()}` @@ -79,12 +121,16 @@ module.exports = class Task{ if (err){ this.setStatus(statusCodes.FAILED, {errorMessage: `Could not start process (${err.message})`}); }else{ - if (code === 0){ - this.setStatus(statusCodes.COMPLETED); - }else{ - this.setStatus(statusCodes.FAILED, {errorMessage: `Process exited with code ${code}`}); + // Don't evaluate if we caused the process to exit via SIGINT? + if (this.status.code !== statusCodes.CANCELED){ + if (code === 0){ + this.setStatus(statusCodes.COMPLETED); + }else{ + this.setStatus(statusCodes.FAILED, {errorMessage: `Process exited with code ${code}`}); + } } } + this.stopTrackingProcessingTime(); done(); }, output => { // Replace console colors @@ -103,10 +149,9 @@ module.exports = class Task{ restart(cb){ if (this.status.code === statusCodes.CANCELED || this.status.code === statusCodes.FAILED){ this.setStatus(statusCodes.QUEUED); - - console.log("Requested to restart " + this.name); - // TODO - + this.dateCreated = new Date().getTime(); + this.output = []; + this.stopTrackingProcessingTime(true); cb(null); }else{ cb(new Error("Task cannot be restarted")); @@ -119,6 +164,7 @@ module.exports = class Task{ uuid: this.uuid, name: this.name, dateCreated: this.dateCreated, + processingTime: this.processingTime, status: this.status, options: this.options, imagesCount: this.images.length diff --git a/libs/TaskManager.js b/libs/TaskManager.js index 28e771f..02a0493 100644 --- a/libs/TaskManager.js +++ b/libs/TaskManager.js @@ -64,10 +64,15 @@ module.exports = class TaskManager{ cancel(uuid, cb){ let task; if (task = this.find(uuid, cb)){ - task.cancel(err => { - this.removeFromRunningQueue(task); - cb(err); - }); + if (!task.isCanceled()){ + task.cancel(err => { + this.removeFromRunningQueue(task); + this.processNextTask(); + cb(err); + }); + }else{ + cb(null); // Nothing to be done + } } } @@ -76,9 +81,16 @@ module.exports = class TaskManager{ remove(uuid, cb){ this.cancel(uuid, err => { if (!err){ - delete(this.tasks[uuid]); - // TODO: other cleanup - cb(null); + let task; + if (task = this.find(uuid, cb)){ + task.cleanup(err => { + if (!err){ + delete(this.tasks[uuid]); + this.processNextTask(); + cb(null); + }else cb(err); + }); + }else; // cb is called by find on error }else cb(err); }); } @@ -89,7 +101,7 @@ module.exports = class TaskManager{ let task; if (task = this.find(uuid, cb)){ task.restart(err => { - this.processNextTask(); + if (!err) this.processNextTask(); cb(err); }); } diff --git a/package.json b/package.json index 8306055..17663f0 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,8 @@ "express": "^4.14.0", "morgan": "^1.7.0", "multer": "^1.1.0", - "node-uuid": "^1.4.7" + "node-uuid": "^1.4.7", + "rimraf": "^2.5.3" }, "devDependencies": { "nodemon": "^1.9.2" diff --git a/public/css/main.css b/public/css/main.css index 72dcc94..8b5d502 100644 --- a/public/css/main.css +++ b/public/css/main.css @@ -42,7 +42,7 @@ } @keyframes pulsateNegative { 0% {background-color: #fff;} - 50% {background-color: lightred;} + 50% {background-color: pink;} 100% {background-color: #fff;} } diff --git a/public/index.html b/public/index.html index 42d10a7..1497ea5 100644 --- a/public/index.html +++ b/public/index.html @@ -64,19 +64,24 @@