diff --git a/src/boxerror.js b/src/boxerror.js index 80fcb1117..a0e832bb7 100644 --- a/src/boxerror.js +++ b/src/boxerror.js @@ -34,6 +34,7 @@ util.inherits(BoxError, Error); BoxError.ACCESS_DENIED = 'Access Denied'; BoxError.ALREADY_EXISTS = 'Already Exists'; BoxError.BAD_FIELD = 'Bad Field'; +BoxError.BAD_STATE = 'Bad State'; BoxError.COLLECTD_ERROR = 'Collectd Error'; BoxError.CONFLICT = 'Conflict'; BoxError.DATABASE_ERROR = 'Database Error'; diff --git a/src/cloudron.js b/src/cloudron.js index 5ec87f96e..950e1be3f 100644 --- a/src/cloudron.js +++ b/src/cloudron.js @@ -50,7 +50,6 @@ var apps = require('./apps.js'), split = require('split'), sysinfo = require('./sysinfo.js'), tasks = require('./tasks.js'), - TaskError = require('./tasks.js').TaskError, users = require('./users.js'); var REBOOT_CMD = path.join(__dirname, 'scripts/reboot.sh'); @@ -96,7 +95,7 @@ function notifyUpdate(callback) { if (error) return callback(error); tasks.setCompletedByType(tasks.TASK_UPDATE, { error: null }, function (error) { - if (error && error.reason !== TaskError.NOT_FOUND) return callback(error); // when hotfixing, task may not exist + if (error && error.reason !== BoxError.NOT_FOUND) return callback(error); // when hotfixing, task may not exist safe.fs.writeFileSync(paths.VERSION_FILE, constants.VERSION, 'utf8'); diff --git a/src/routes/tasks.js b/src/routes/tasks.js index 2a0f0d004..e4d9fae84 100644 --- a/src/routes/tasks.js +++ b/src/routes/tasks.js @@ -10,18 +10,30 @@ exports = module.exports = { }; let assert = require('assert'), + BoxError = require('../boxerror.js'), HttpError = require('connect-lastmile').HttpError, HttpSuccess = require('connect-lastmile').HttpSuccess, - TaskError = require('../tasks.js').TaskError, tasks = require('../tasks.js'); +function toHttpError(appError) { + switch (appError.reason) { + case BoxError.NOT_FOUND: + return new HttpError(404, appError); + case BoxError.BAD_STATE: + return new HttpError(409, appError); + case BoxError.BAD_FIELD: + return new HttpError(400, appError); + case BoxError.DATABASE_ERROR: + default: + return new HttpError(500, appError); + } +} + function stopTask(req, res, next) { assert.strictEqual(typeof req.params.taskId, 'string'); tasks.stopTask(req.params.taskId, function (error) { - if (error && error.reason === TaskError.NOT_FOUND) return next(new HttpError(404, 'No such task')); - if (error && error.reason === TaskError.BAD_STATE) return next(new HttpError(409, error.message)); - if (error) return next(new HttpError(500, error)); + if (error) return next(toHttpError(error)); next(new HttpSuccess(204, {})); }); @@ -31,8 +43,7 @@ function get(req, res, next) { assert.strictEqual(typeof req.params.taskId, 'string'); tasks.get(req.params.taskId, function (error, task) { - if (error && error.reason === TaskError.NOT_FOUND) return next(new HttpError(404, 'No such task')); - if (error) return next(new HttpError(500, error)); + if (error) return next(toHttpError(error)); next(new HttpSuccess(200, tasks.removePrivateFields(task))); }); @@ -48,7 +59,7 @@ function list(req, res, next) { if (req.query.type && typeof req.query.type !== 'string') return next(new HttpError(400, 'type must be a string')); tasks.listByTypePaged(req.query.type || null, page, perPage, function (error, result) { - if (error) return next(new HttpError(500, error)); + if (error) return next(toHttpError(error)); result = result.map(tasks.removePrivateFields); @@ -69,8 +80,7 @@ function getLogs(req, res, next) { }; tasks.getLogs(req.params.taskId, options, function (error, logStream) { - if (error && error.reason === TaskError.NOT_FOUND) return next(new HttpError(404, 'No such task')); - if (error) return next(new HttpError(500, error)); + if (error) return next(toHttpError(error)); res.writeHead(200, { 'Content-Type': 'application/x-logs', @@ -100,8 +110,7 @@ function getLogStream(req, res, next) { }; tasks.getLogs(req.params.taskId, options, function (error, logStream) { - if (error && error.reason === TaskError.NOT_FOUND) return next(new HttpError(404, 'No such task')); - if (error) return next(new HttpError(500, error)); + if (error) return next(toHttpError(error)); res.writeHead(200, { 'Content-Type': 'text/event-stream', diff --git a/src/tasks.js b/src/tasks.js index cbf4fa5bd..af776af5a 100644 --- a/src/tasks.js +++ b/src/tasks.js @@ -16,8 +16,6 @@ exports = module.exports = { removePrivateFields: removePrivateFields, - TaskError: TaskError, - // task types. if you add a task here, fill up the function table in taskworker TASK_APP: 'app', TASK_BACKUP: 'backup', @@ -41,6 +39,7 @@ exports = module.exports = { let assert = require('assert'), async = require('async'), + BoxError = require('./boxerror.js'), child_process = require('child_process'), DatabaseError = require('./databaseerror.js'), debug = require('debug')('box:tasks'), @@ -49,36 +48,12 @@ let assert = require('assert'), spawn = require('child_process').spawn, split = require('split'), taskdb = require('./taskdb.js'), - util = require('util'), _ = require('underscore'); let gTasks = {}; // indexed by task id const NOOP_CALLBACK = function (error) { if (error) debug(error); }; -function TaskError(reason, errorOrMessage) { - assert.strictEqual(typeof reason, 'string'); - assert(errorOrMessage instanceof Error || typeof errorOrMessage === 'string' || typeof errorOrMessage === 'undefined'); - - Error.call(this); - Error.captureStackTrace(this, this.constructor); - - this.name = this.constructor.name; - this.reason = reason; - if (typeof errorOrMessage === 'undefined') { - this.message = reason; - } else if (typeof errorOrMessage === 'string') { - this.message = errorOrMessage; - } else { - this.message = 'Internal error'; - this.nestedError = errorOrMessage; - } -} -util.inherits(TaskError, Error); -TaskError.INTERNAL_ERROR = 'Internal Error'; -TaskError.BAD_STATE = 'Bad State'; -TaskError.NOT_FOUND = 'Not Found'; - function postProcess(result) { assert.strictEqual(typeof result, 'object'); @@ -97,8 +72,8 @@ function get(id, callback) { assert.strictEqual(typeof callback, 'function'); taskdb.get(id, function (error, task) { - if (error && error.reason == DatabaseError.NOT_FOUND) return callback(new TaskError(TaskError.NOT_FOUND)); - if (error) return callback(new TaskError(TaskError.INTERNAL_ERROR, error)); + if (error && error.reason == DatabaseError.NOT_FOUND) return callback(new BoxError(BoxError.NOT_FOUND)); + if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error)); postProcess(task); @@ -114,8 +89,8 @@ function update(id, task, callback) { debug(`${id}: ${JSON.stringify(task)}`); taskdb.update(id, task, function (error) { - if (error && error.reason == DatabaseError.NOT_FOUND) return callback(new TaskError(TaskError.NOT_FOUND)); - if (error) return callback(new TaskError(TaskError.INTERNAL_ERROR, error)); + if (error && error.reason == DatabaseError.NOT_FOUND) return callback(new BoxError(BoxError.NOT_FOUND)); + if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error)); callback(); }); @@ -137,11 +112,11 @@ function setCompletedByType(type, task, callback) { assert.strictEqual(typeof callback, 'function'); listByTypePaged(type, 1, 1, function (error, results) { - if (error) return callback(new TaskError(TaskError.INTERNAL_ERROR, error)); - if (results.length !== 1) return callback(new TaskError(TaskError.NOT_FOUND)); + if (error) return callback(error); + if (results.length !== 1) return callback(new BoxError(BoxError.NOT_FOUND)); setCompleted(results[0].id, task, function (error) { - if (error) return callback(new TaskError(TaskError.INTERNAL_ERROR, error)); + if (error) return callback(error); callback(); }); @@ -154,7 +129,7 @@ function add(type, args, callback) { assert.strictEqual(typeof callback, 'function'); taskdb.add({ type: type, percent: 0, message: 'Starting ...', args: args }, function (error, taskId) { - if (error) return callback(new TaskError(TaskError.INTERNAL_ERROR, error)); + if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error)); callback(null, taskId); }); @@ -169,7 +144,7 @@ function startTask(taskId, options, callback) { let fd = safe.fs.openSync(logFile, 'a'); // will autoclose. append is for apptask logs if (!fd) { debug(`startTask: unable to get log filedescriptor ${safe.error.message}`); - return callback(new TaskError(TaskError.INTERNAL_ERROR, safe.error)); + return callback(new BoxError(BoxError.FS_ERROR, safe.error)); } debug(`startTask - starting task ${taskId}. logs at ${logFile}`); @@ -218,7 +193,7 @@ function stopTask(id, callback) { assert.strictEqual(typeof id, 'string'); assert.strictEqual(typeof callback, 'function'); - if (!gTasks[id]) return callback(new TaskError(TaskError.BAD_STATE, 'task is not active')); + if (!gTasks[id]) return callback(new BoxError(BoxError.BAD_STATE, 'task is not active')); debug(`stopTask: stopping task ${id}`); @@ -242,7 +217,7 @@ function listByTypePaged(type, page, perPage, callback) { assert.strictEqual(typeof callback, 'function'); taskdb.listByTypePaged(type, page, perPage, function (error, tasks) { - if (error) return callback(new TaskError(TaskError.INTERNAL_ERROR, error)); + if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error)); tasks.forEach(postProcess);