diff --git a/src/apps.js b/src/apps.js index cf1260ec4..068dd4070 100644 --- a/src/apps.js +++ b/src/apps.js @@ -86,6 +86,7 @@ var appdb = require('./appdb.js'), split = require('split'), superagent = require('superagent'), taskmanager = require('./taskmanager.js'), + tasks = require('./tasks.js'), TransformStream = require('stream').Transform, updateChecker = require('./updatechecker.js'), util = require('util'), @@ -573,6 +574,22 @@ function mailboxNameForLocation(location, manifest) { return (location ? location : manifest.title.toLowerCase().replace(/[^a-zA-Z0-9]/g, '')) + '.app'; } +function startAppTask(appId, callback) { + let task = tasks.startTask(tasks.TASK_APP, [ appId ]); + task.on('start', function (taskId) { + appdb.update(appId, { taskId: taskId }, function (error) { + if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error)); + + get(appId, function (error, result) { + if (error) return callback(error); + + callback(null, result); + }); + }); + }); + task.on('error', (error) => callback(new AppsError(AppsError.INTERNAL_ERROR, error))); +} + function install(data, user, auditSource, callback) { assert(data && typeof data === 'object'); assert(user && typeof user === 'object'); @@ -701,10 +718,7 @@ function install(data, user, auditSource, callback) { if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, 'Error setting cert: ' + error.message)); } - taskmanager.restartAppTask(appId); - - // fetch fresh app object for eventlog - get(appId, function (error, result) { + startAppTask(appId, function (error, result) { if (error) return callback(error); eventlog.add(eventlog.ACTION_APP_INSTALL, auditSource, { appId: appId, app: result }); diff --git a/src/apptask.js b/src/apptask.js index a8c82f9d5..e566b6869 100644 --- a/src/apptask.js +++ b/src/apptask.js @@ -6,6 +6,8 @@ exports = module.exports = { initialize: initialize, startTask: startTask, + run: run, + // exported for testing _reserveHttpPort: reserveHttpPort, _configureReverseProxy: configureReverseProxy, @@ -954,6 +956,41 @@ function startTask(appId, callback) { }); } +function run(appId, progressCallback, callback) { + assert.strictEqual(typeof appId, 'string'); + assert.strictEqual(typeof progressCallback, 'function'); + assert.strictEqual(typeof callback, 'function'); + + // determine what to do + apps.get(appId, function (error, app) { + if (error) return callback(error); + + debugApp(app, 'startTask installationState: %s runState: %s', app.installationState, app.runState); + + switch (app.installationState) { + case appdb.ISTATE_PENDING_UNINSTALL: return uninstall(app, callback); + case appdb.ISTATE_PENDING_CONFIGURE: return configure(app, callback); + + case appdb.ISTATE_PENDING_UPDATE: return update(app, callback); + case appdb.ISTATE_PENDING_FORCE_UPDATE: return update(app, callback); + + case appdb.ISTATE_PENDING_INSTALL: return install(app, callback); + case appdb.ISTATE_PENDING_CLONE: return install(app, callback); + case appdb.ISTATE_PENDING_RESTORE: return install(app, callback); + + case appdb.ISTATE_PENDING_BACKUP: return backup(app, callback); + case appdb.ISTATE_INSTALLED: return handleRunCommand(app, callback); + + case appdb.ISTATE_ERROR: + debugApp(app, 'Internal error. apptask launched with error status.'); + return callback(null); + default: + debugApp(app, 'apptask launched with invalid command'); + return callback(new Error('Unknown command in apptask:' + app.installationState)); + } + }); +} + if (require.main === module) { assert.strictEqual(process.argv.length, 3, 'Pass the appid as argument'); diff --git a/src/tasks.js b/src/tasks.js index 14e60823c..ae379b623 100644 --- a/src/tasks.js +++ b/src/tasks.js @@ -15,6 +15,7 @@ exports = module.exports = { TaskError: TaskError, // task types. if you add a task here, fill up the function table in taskworker + TASK_APP: 'app', TASK_BACKUP: 'backup', TASK_UPDATE: 'update', TASK_RENEW_CERTS: 'renewcerts', diff --git a/src/taskworker.js b/src/taskworker.js index 0c00db447..68af3eb58 100755 --- a/src/taskworker.js +++ b/src/taskworker.js @@ -2,7 +2,8 @@ require('supererror')({ splatchError: true }); -var assert = require('assert'), +var apptask = require('./apptask.js'), + assert = require('assert'), async = require('async'), backups = require('./backups.js'), database = require('./database.js'), @@ -16,6 +17,7 @@ var assert = require('assert'), const NOOP_CALLBACK = function (error) { if (error) debug(error); }; const TASKS = { // indexed by task type + app: apptask.run, backup: backups.backupBoxAndApps, update: updater.update, renewcerts: reverseProxy.renewCerts,