Task start working, console output

pull/1/head
Piero Toffanin 2016-07-09 11:58:14 -05:00
rodzic 7a4bee53b9
commit 48e292a6cf
6 zmienionych plików z 99 dodań i 36 usunięć

Wyświetl plik

@ -39,7 +39,7 @@ let upload = multer({
})
});
app.post('/newTask', addRequestId, upload.array('images'), (req, res) => {
app.post('/task/new', addRequestId, upload.array('images'), (req, res) => {
if (req.files.length === 0) res.json({error: "Need at least 1 file."});
else{
// Move to data
@ -81,11 +81,11 @@ let getTaskFromUuid = (req, res, next) => {
}else res.json({error: `${req.params.uuid} not found`});
}
app.get('/taskInfo/:uuid', getTaskFromUuid, (req, res) => {
app.get('/task/:uuid/info', getTaskFromUuid, (req, res) => {
res.json(req.task.getInfo());
});
app.get('/taskOutput/:uuid', getTaskFromUuid, (req, res) => {
res.json(req.task.getOutput());
app.get('/task/:uuid/output', getTaskFromUuid, (req, res) => {
res.json(req.task.getOutput(req.query.line));
});
let uuidCheck = (req, res, next) => {
@ -100,15 +100,15 @@ let successHandler = res => {
};
};
app.post('/cancelTask', uuidCheck, (req, res) => {
app.post('/task/cancel', uuidCheck, (req, res) => {
taskManager.cancel(req.body.uuid, successHandler(res));
});
app.post('/removeTask', uuidCheck, (req, res) => {
app.post('/task/remove', uuidCheck, (req, res) => {
taskManager.remove(req.body.uuid, successHandler(res));
});
app.post('/restartTask', uuidCheck, (req, res) => {
app.post('/task/restart', uuidCheck, (req, res) => {
taskManager.restart(req.body.uuid, successHandler(res));
});

Wyświetl plik

@ -33,7 +33,13 @@ module.exports = class Task{
// Get path where images are stored for this task
// (relative to nodejs process CWD)
getImagesFolderPath(){
return `data/${this.uuid}/images`;
return `${this.getProjectFolderPath()}/images`;
}
// Get path of project (where all images and assets folder are contained)
// (relative to nodejs process CWD)
getProjectFolderPath(){
return `data/${this.uuid}`;
}
setStatus(code, extra){
@ -68,7 +74,7 @@ module.exports = class Task{
if (this.status.code === statusCodes.QUEUED){
this.setStatus(statusCodes.RUNNING);
this.runnerProcess = odmRunner.run({
projectPath: `${__dirname}/../${this.getImagesFolderPath()}`
projectPath: `${__dirname}/../${this.getProjectFolderPath()}`
}, (err, code, signal) => {
if (err){
this.setStatus(statusCodes.FAILED, {errorMessage: `Could not start process (${err.message})`});
@ -81,6 +87,8 @@ module.exports = class Task{
}
done();
}, output => {
// Replace console colors
output = output.replace(/\x1b\[[0-9;]*m/g, "");
this.output.push(output);
});
@ -120,7 +128,6 @@ module.exports = class Task{
// Returns the output of the OpenDroneMap process
// Optionally starting from a certain line number
getOutput(startFromLine = 0){
let lineNum = Math.min(this.output.length, startFromLine);
return this.output.slice(lineNum, this.output.length);
return this.output.slice(startFromLine, this.output.length);
}
};

Wyświetl plik

@ -3,7 +3,7 @@ let assert = require('assert');
let Task = require('./Task');
let statusCodes = require('./statusCodes');
let PARALLEL_QUEUE_PROCESS_LIMIT = 1;
let PARALLEL_QUEUE_PROCESS_LIMIT = 2;
module.exports = class TaskManager{
constructor(){
@ -50,8 +50,6 @@ module.exports = class TaskManager{
this.runningQueue = this.runningQueue.filter(t => {
return t !== task;
});
console.log("New queue length: " + this.runningQueue.length);
}
addNew(task){
@ -90,7 +88,10 @@ module.exports = class TaskManager{
restart(uuid, cb){
let task;
if (task = this.find(uuid, cb)){
task.restart(cb);
task.restart(err => {
this.processNextTask();
cb(err);
});
}
}

Wyświetl plik

@ -48,4 +48,11 @@
.task .actionButtons{
text-align: right;
}
.task .consoleOutput{
width: 100%;
height: 200px;
font-family: monospace;
font-size: 90%;
}

Wyświetl plik

@ -64,6 +64,8 @@
<div class="taskItem"><strong>Name:</strong> <span data-bind="text: info().name"></span></div>
<div class="taskItem"><strong>Images:</strong> <span data-bind="text: info().imagesCount"></span></div>
<div class="taskItem"><strong>Status:</strong> <span data-bind="text: statusDescr()"></span></div>
<div class="taskItem"><strong>Output:</strong> <a href="javascript:void(0);" data-bind="click: viewOutput, visible: !viewingOutput()">View</a><a href="javascript:void(0);" data-bind="click: hideOutput, visible: viewingOutput()">Hide</a></div>
<textarea class="consoleOutput" data-bind="value: output().join(''), visible: viewingOutput(), event: {mouseover: consoleMouseOver, mouseout: consoleMouseOut}, attr: {id: 'console_' + uuid}"></textarea>
<span data-bind="css: 'statusIcon glyphicon ' + icon()"></span>

Wyświetl plik

@ -7,7 +7,7 @@ $(function(){
return new Task(uuid);
}));
}
TaskList.prototype.addNew = function(task) {
TaskList.prototype.add = function(task) {
this.tasks.push(task);
this.saveTaskListToLocalStorage();
};
@ -30,6 +30,8 @@ $(function(){
this.uuid = uuid;
this.loading = ko.observable(true);
this.info = ko.observable({});
this.viewingOutput = ko.observable(false);
this.resetOutput();
var statusCodes = {
10: {
@ -64,7 +66,6 @@ $(function(){
this.icon = ko.pureComputed(function(){
if (this.info().status && this.info().status.code){
if(statusCodes[this.info().status.code]){
console.log(statusCodes[this.info().status.code].icon);
return statusCodes[this.info().status.code].icon;
}else return "glyphicon-question-sign";
}else return "";
@ -73,14 +74,11 @@ $(function(){
return this.info().status && this.info().status.code === 50;
}, this);
this.refreshInfo();
this.refreshInterval = setInterval(function(){
self.refreshInfo();
}, 2000);
this.startRefreshingInfo();
}
Task.prototype.refreshInfo = function(){
var self = this;
var url = "/taskInfo/" + this.uuid;
var url = "/task/" + this.uuid + "/info";
$.get(url)
.done(self.info)
.fail(function(){
@ -88,9 +86,61 @@ $(function(){
})
.always(function(){ self.loading(false); });
};
Task.prototype.consoleMouseOver = function(){ this.autoScrollOutput = false; }
Task.prototype.consoleMouseOut = function(){ this.autoScrollOutput = true; }
Task.prototype.resetOutput = function(){
this.viewOutputLine = 0;
this.autoScrollOutput = true;
this.output = ko.observableArray();
};
Task.prototype.viewOutput = function(){
var self = this;
function fetchOutput(){
var url = "/task/" + self.uuid + "/output";
$.get(url, {line: self.viewOutputLine})
.done(function(output){
for (var i in output){
self.output.push(output[i]);
}
if (output.length){
self.viewOutputLine += output.length;
if (self.autoScrollOutput){
var $console = $("#console_" + self.uuid);
$console.scrollTop($console[0].scrollHeight - $console.height())
}
}
})
.fail(function(){
self.info({error: url + " is unreachable."});
});
}
this.fetchOutputInterval = setInterval(fetchOutput, 2000);
fetchOutput();
this.viewingOutput(true);
};
Task.prototype.hideOutput = function(){
if (this.fetchOutputInterval) clearInterval(this.fetchOutputInterval);
this.viewingOutput(false);
};
Task.prototype.startRefreshingInfo = function() {
var self = this;
this.stopRefreshingInfo();
this.refreshInfo();
this.refreshInterval = setInterval(function(){
self.refreshInfo();
}, 2000);
};
Task.prototype.stopRefreshingInfo = function() {
if (this.refreshInterval){
clearInterval(this.refreshInterval);
this.refreshInterval = null;
}
};
Task.prototype.remove = function() {
var self = this;
var url = "/removeTask";
var url = "/task/remove";
$.post(url, {
uuid: this.uuid
@ -102,13 +152,11 @@ $(function(){
self.info({error: json.error});
}
if (self.refreshInterval){
clearInterval(self.refreshInterval);
self.refreshInterval = null;
}
self.stopRefreshingInfo();
})
.fail(function(){
self.info({error: url + " is unreachable."});
self.stopRefreshingInfo();
});
};
@ -116,34 +164,32 @@ $(function(){
return function(){
var self = this;
// TODO: maybe there's a better way
// to handle refreshInfo here...
$.post(url, {
uuid: this.uuid
})
.done(function(json){
if (json.success){
self.refreshInfo();
self.startRefreshingInfo();
}else{
self.stopRefreshingInfo();
self.info({error: json.error});
}
})
.fail(function(){
self.info({error: url + " is unreachable."});
self.stopRefreshingInfo();
});
}
};
Task.prototype.cancel = genApiCall("/cancelTask");
Task.prototype.restart = genApiCall("/restartTask");
Task.prototype.cancel = genApiCall("/task/cancel");
Task.prototype.restart = genApiCall("/task/restart");
var taskList = new TaskList();
ko.applyBindings(taskList);
// Handle uploads
$("#images").fileinput({
uploadUrl: '/newTask',
uploadUrl: '/task/new',
showPreview: false,
allowedFileExtensions: ['jpg', 'jpeg'],
elErrorContainer: '#errorBlock',
@ -170,7 +216,7 @@ $(function(){
$("#images").fileinput('reset');
if (params.response.success && params.response.uuid){
taskList.addNew(new Task(params.response.uuid));
taskList.add(new Task(params.response.uuid));
}
})
.on('filebatchuploadcomplete', function(){