kopia lustrzana https://github.com/OpenDroneMap/NodeODM
Task persistence after shutdown
rodzic
2b3411dadc
commit
6b3938d616
38
index.js
38
index.js
|
@ -10,8 +10,7 @@ let addRequestId = require('./libs/expressRequestId')();
|
|||
let multer = require('multer');
|
||||
let bodyParser = require('body-parser');
|
||||
let morgan = require('morgan');
|
||||
|
||||
let taskManager = new (require('./libs/taskManager'))();
|
||||
let TaskManager = require('./libs/taskManager');
|
||||
let Task = require('./libs/Task');
|
||||
|
||||
app.use(morgan('tiny'));
|
||||
|
@ -112,6 +111,35 @@ app.post('/task/restart', uuidCheck, (req, res) => {
|
|||
taskManager.restart(req.body.uuid, successHandler(res));
|
||||
});
|
||||
|
||||
app.listen(3000, () => {
|
||||
console.log('Server has started on port 3000');
|
||||
});
|
||||
let gracefulShutdown = done => {
|
||||
async.series([
|
||||
cb => { taskManager.dumpTaskList(cb) },
|
||||
cb => {
|
||||
console.log("Closing server");
|
||||
server.close();
|
||||
console.log("Exiting...");
|
||||
process.exit(0);
|
||||
}
|
||||
], done);
|
||||
};
|
||||
|
||||
// listen for TERM signal .e.g. kill
|
||||
process.on ('SIGTERM', gracefulShutdown);
|
||||
|
||||
// listen for INT signal e.g. Ctrl-C
|
||||
process.on ('SIGINT', gracefulShutdown);
|
||||
|
||||
// Startup
|
||||
let taskManager;
|
||||
let server;
|
||||
|
||||
async.series([
|
||||
cb => { taskManager = new TaskManager(cb); },
|
||||
cb => { server = app.listen(3000, err => {
|
||||
if (!err) console.log('Server has started on port 3000');
|
||||
cb(err);
|
||||
});
|
||||
}
|
||||
], err => {
|
||||
if (err) console.log("Error during startup: " + err.message);
|
||||
});
|
||||
|
|
39
libs/Task.js
39
libs/Task.js
|
@ -7,9 +7,9 @@ let odmRunner = require('./odmRunner');
|
|||
let statusCodes = require('./statusCodes');
|
||||
|
||||
module.exports = class Task{
|
||||
constructor(uuid, name, readyCb){
|
||||
constructor(uuid, name, done){
|
||||
assert(uuid !== undefined, "uuid must be set");
|
||||
assert(readyCb !== undefined, "ready must be set");
|
||||
assert(done !== undefined, "ready must be set");
|
||||
|
||||
this.uuid = uuid;
|
||||
this.name = name != "" ? name : "Task of " + (new Date()).toISOString();
|
||||
|
@ -22,14 +22,33 @@ module.exports = class Task{
|
|||
|
||||
// Read images info
|
||||
fs.readdir(this.getImagesFolderPath(), (err, files) => {
|
||||
if (err) readyCb(err);
|
||||
if (err) done(err);
|
||||
else{
|
||||
this.images = files;
|
||||
readyCb(null, this);
|
||||
done(null, this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static CreateFromSerialized(taskJson, done){
|
||||
new Task(taskJson.uuid, taskJson.name, (err, task) => {
|
||||
if (err) done(err);
|
||||
else{
|
||||
// Override default values with those
|
||||
// provided in the taskJson
|
||||
for (let k in taskJson){
|
||||
task[k] = taskJson[k];
|
||||
}
|
||||
|
||||
// Tasks that were running should be put back to QUEUED state
|
||||
if (task.status.code === statusCodes.RUNNING){
|
||||
task.status.code = statusCodes.QUEUED;
|
||||
}
|
||||
done(null, task);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Get path where images are stored for this task
|
||||
// (relative to nodejs process CWD)
|
||||
getImagesFolderPath(){
|
||||
|
@ -176,4 +195,16 @@ module.exports = class Task{
|
|||
getOutput(startFromLine = 0){
|
||||
return this.output.slice(startFromLine, this.output.length);
|
||||
}
|
||||
|
||||
// Returns the data necessary to serialize this
|
||||
// task to restore it later.
|
||||
serialize(){
|
||||
return {
|
||||
uuid: this.uuid,
|
||||
name: this.name,
|
||||
dateCreated: this.dateCreated,
|
||||
status: this.status,
|
||||
options: this.options
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,14 +1,51 @@
|
|||
"use strict";
|
||||
let assert = require('assert');
|
||||
let fs = require('fs');
|
||||
let Task = require('./Task');
|
||||
let statusCodes = require('./statusCodes');
|
||||
let async = require('async');
|
||||
|
||||
let PARALLEL_QUEUE_PROCESS_LIMIT = 2;
|
||||
const PARALLEL_QUEUE_PROCESS_LIMIT = 2;
|
||||
const TASKS_DUMP_FILE = "data/tasks.json";
|
||||
|
||||
module.exports = class TaskManager{
|
||||
constructor(){
|
||||
constructor(done){
|
||||
this.tasks = {};
|
||||
this.runningQueue = [];
|
||||
|
||||
async.series([
|
||||
cb => { this.restoreTaskListFromDump(cb); },
|
||||
cb => {
|
||||
this.processNextTask();
|
||||
cb();
|
||||
}
|
||||
], done);
|
||||
|
||||
}
|
||||
|
||||
// Load tasks that already exists (if any)
|
||||
restoreTaskListFromDump(done){
|
||||
fs.readFile(TASKS_DUMP_FILE, (err, data) => {
|
||||
if (!err){
|
||||
let tasks = JSON.parse(data.toString());
|
||||
|
||||
async.each(tasks, (taskJson, done) => {
|
||||
Task.CreateFromSerialized(taskJson, (err, task) => {
|
||||
if (err) done(err);
|
||||
else{
|
||||
this.tasks[task.uuid] = task;
|
||||
done();
|
||||
}
|
||||
});
|
||||
}, err => {
|
||||
console.log(`Initialized ${tasks.length} tasks`);
|
||||
if (done !== undefined) done();
|
||||
});
|
||||
}else{
|
||||
console.log("No tasks dump found");
|
||||
if (done !== undefined) done();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Finds the first QUEUED task.
|
||||
|
@ -113,4 +150,20 @@ module.exports = class TaskManager{
|
|||
if (!task && cb) cb(new Error(`${uuid} not found`));
|
||||
return task;
|
||||
}
|
||||
|
||||
// Serializes the list of tasks and saves it
|
||||
// to disk
|
||||
dumpTaskList(done){
|
||||
var output = [];
|
||||
|
||||
for (let uuid in this.tasks){
|
||||
output.push(this.tasks[uuid].serialize());
|
||||
}
|
||||
|
||||
fs.writeFile(TASKS_DUMP_FILE, JSON.stringify(output), err => {
|
||||
if (err) console.log(`Could not dump tasks: ${err.message}`);
|
||||
else console.log("Dumped tasks list.");
|
||||
if (done !== undefined) done();
|
||||
})
|
||||
}
|
||||
};
|
Ładowanie…
Reference in New Issue