diff --git a/src/tasks.js b/src/tasks.js index 1506f4d0a..10e5502ac 100644 --- a/src/tasks.js +++ b/src/tasks.js @@ -59,9 +59,13 @@ function postProcess(result) { assert.strictEqual(typeof result, 'object'); result.active = !!gTasks[result.id]; + // we rely on 'percent' to determine success. maybe this can become a db field result.success = result.percent === 100 && !result.error; + // we rely on 'percent' to determine pending. maybe this can become a db field + result.pending = result.percent === 1; + // the error in db will be empty if we didn't get a chance to handle task exit if (!result.active && result.percent !== 100 && !result.error) { result.error = { message: 'Cloudron crashed/stopped', code: exports.ECRASHED }; @@ -127,7 +131,7 @@ function add(type, args, callback) { assert(Array.isArray(args)); assert.strictEqual(typeof callback, 'function'); - taskdb.add({ type: type, percent: 1, message: 'Queued', args: args }, function (error, taskId) { + taskdb.add({ type: type, percent: 0, message: 'Queued', args: args }, function (error, taskId) { if (error) return callback(error); callback(null, taskId); @@ -273,6 +277,6 @@ function getLogs(taskId, options, callback) { // removes all fields that are strictly private and should never be returned by API calls function removePrivateFields(task) { - var result = _.pick(task, 'id', 'type', 'percent', 'message', 'error', 'active', 'creationTime', 'result', 'ts', 'success'); + var result = _.pick(task, 'id', 'type', 'percent', 'message', 'error', 'active', 'pending', 'creationTime', 'result', 'ts', 'success'); return result; } diff --git a/src/taskworker.js b/src/taskworker.js index 3c298822e..fbff783c9 100755 --- a/src/taskworker.js +++ b/src/taskworker.js @@ -72,24 +72,32 @@ async.series([ tasks.get(taskId, function (error, task) { if (error) return process.exit(50); - const progressCallback = (progress, cb) => tasks.update(taskId, progress, cb || NOOP_CALLBACK); - const resultCallback = (error, result) => { - // Error object has properties with enumerable: false (https://mattcbaker.com/posts/stringify-javascript-error/) - const progress = { - result: result || null, - error: error ? JSON.parse(JSON.stringify(error, Object.getOwnPropertyNames(error))) : null + tasks.update(taskId, { percent: 2, error: null }, function (error) { + if (error) { + console.error(error); + return process.exit(50); + } + + const progressCallback = (progress, cb) => tasks.update(taskId, progress, cb || NOOP_CALLBACK); + const resultCallback = (error, result) => { + // Error object has properties with enumerable: false (https://mattcbaker.com/posts/stringify-javascript-error/) + const progress = { + result: result || null, + error: error ? JSON.parse(JSON.stringify(error, Object.getOwnPropertyNames(error))) : null + }; + + debug(`Task took ${(new Date() - startTime)/1000} seconds`); + + tasks.setCompleted(taskId, progress, () => process.exit(error ? 50 : 0)); }; - debug(`Task took ${(new Date() - startTime)/1000} seconds`); + try { + TASKS[task.type].apply(null, task.args.concat(progressCallback).concat(resultCallback)); + } catch (error) { + debug('Uncaught exception in task', error); + process.exit(1); // do not call setCompleted() intentionally. the task code must be resilient enough to handle it + } + }); - tasks.setCompleted(taskId, progress, () => process.exit(error ? 50 : 0)); - }; - - try { - TASKS[task.type].apply(null, task.args.concat(progressCallback).concat(resultCallback)); - } catch (error) { - debug('Uncaught exception in task', error); - process.exit(1); // do not call setCompleted() intentionally. the task code must be resilient enough to handle it - } }); });