Fix platform update logic
This commit is contained in:
65
src/apps.js
65
src/apps.js
@@ -54,7 +54,7 @@ exports = module.exports = {
|
||||
|
||||
restoreInstalledApps: restoreInstalledApps,
|
||||
configureInstalledApps: configureInstalledApps,
|
||||
resumeTasks: resumeTasks,
|
||||
schedulePendingTasks: schedulePendingTasks,
|
||||
|
||||
getDataDir: getDataDir,
|
||||
getIconPath: getIconPath,
|
||||
@@ -655,16 +655,18 @@ function addTask(appId, installationState, task, callback) {
|
||||
const { args, values } = task;
|
||||
// by default, a task can only run on installed state. if it's null, it can be run on any state
|
||||
const requiredState = 'requiredState' in task ? task.requiredState : exports.ISTATE_INSTALLED;
|
||||
const scheduleNow = 'scheduleNow' in task ? task.scheduleNow : true;
|
||||
const requireNullTaskId = 'requireNullTaskId' in task ? task.requireNullTaskId : true;
|
||||
|
||||
tasks.add(tasks.TASK_APP, [ appId, args ], function (error, taskId) {
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
|
||||
appdb.setTask(appId, _.extend({ installationState, taskId, error: null }, values), requiredState, function (error) {
|
||||
appdb.setTask(appId, _.extend({ installationState, taskId, error: null }, values), { requiredState, requireNullTaskId }, function (error) {
|
||||
if (error && error.reason === DatabaseError.ALREADY_EXISTS) return callback(new AppsError(AppsError.ALREADY_EXISTS, error.message));
|
||||
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new AppsError(AppsError.BAD_STATE, 'Another task is scheduled for this app')); // could be because app went away OR a taskId exists
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
|
||||
scheduleTask(appId, installationState, taskId, NOOP_CALLBACK);
|
||||
if (scheduleNow) scheduleTask(appId, installationState, taskId, NOOP_CALLBACK);
|
||||
|
||||
callback(null, { taskId });
|
||||
});
|
||||
@@ -1843,21 +1845,25 @@ function restoreInstalledApps(callback) {
|
||||
getAll(function (error, apps) {
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
apps = apps.filter(app => app.installationState !== exports.ISTATE_ERROR); // remove errored apps. let them be 'repaired' by hand
|
||||
apps = apps.filter(app => app.installationState !== exports.ISTATE_PENDING_RESTORE); // safeguard against tasks being created non-stop if we crash on startup
|
||||
|
||||
async.map(apps, function (app, iteratorDone) {
|
||||
async.eachSeries(apps, function (app, iteratorDone) {
|
||||
backups.getByAppIdPaged(1, 1, app.id, function (error, results) {
|
||||
const restoreConfig = !error && results.length ? { backupId: results[0].id, backupFormat: results[0].format, oldManifest: app.manifest } : null;
|
||||
const task = {
|
||||
args: { restoreConfig, overwriteDns: true },
|
||||
values: {},
|
||||
scheduleNow: false, // task will be scheduled by autoRestartTasks when platform is ready
|
||||
requireNullTaskId: false // ignore existing stale taskId
|
||||
};
|
||||
|
||||
debug(`marking ${app.fqdn} for restore using restore config ${JSON.stringify(restoreConfig)}`);
|
||||
debug(`restoreInstalledApps: marking ${app.fqdn} for restore using restore config ${JSON.stringify(restoreConfig)}`);
|
||||
|
||||
appdb.update(app.id, { taskId: null, error: null }, function (error) { // clear any stale taskId
|
||||
if (error) debug(`Error marking ${app.fqdn} for restore: ${JSON.stringify(error)}`);
|
||||
addTask(app.id, exports.ISTATE_PENDING_RESTORE, task, function (error, result) {
|
||||
if (error) debug(`restoreInstalledApps: error marking ${app.fqdn} for restore: ${JSON.stringify(error)}`);
|
||||
else debug(`restoreInstalledApps: marked ${app.id} for restore with taskId ${result.taskId}`);
|
||||
|
||||
const task = {
|
||||
args: { restoreConfig, overwriteDns: true },
|
||||
values: {}
|
||||
};
|
||||
addTask(app.id, exports.ISTATE_PENDING_RESTORE, task, () => iteratorDone()); // always succeed
|
||||
iteratorDone(); // ignore error
|
||||
});
|
||||
});
|
||||
}, callback);
|
||||
@@ -1870,31 +1876,34 @@ function configureInstalledApps(callback) {
|
||||
getAll(function (error, apps) {
|
||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||
apps = apps.filter(app => app.installationState !== exports.ISTATE_ERROR); // remove errored apps. let them be 'repaired' by hand
|
||||
apps = apps.filter(app => app.installationState !== exports.ISTATE_PENDING_CONFIGURE); // safeguard against tasks being created non-stop if we crash on startup
|
||||
|
||||
async.map(apps, function (app, iteratorDone) {
|
||||
debug(`marking ${app.fqdn} for reconfigure`);
|
||||
async.eachSeries(apps, function (app, iteratorDone) {
|
||||
debug(`configureInstalledApps: marking ${app.fqdn} for reconfigure`);
|
||||
|
||||
appdb.update(app.id, { taskId: null, error: null }, function (error) { // clear any stale taskId
|
||||
if (error) debug(`Error marking ${app.fqdn} for reconfigure: ${JSON.stringify(error)}`);
|
||||
const oldConfig = _.pick(app, 'location', 'domain', 'fqdn', 'alternateDomains', 'portBindings');
|
||||
const task = {
|
||||
args: { oldConfig },
|
||||
values: {},
|
||||
scheduleNow: false, // task will be scheduled by autoRestartTasks when platform is ready
|
||||
requireNullTaskId: false // ignore existing stale taskId
|
||||
};
|
||||
|
||||
const oldConfig = _.pick(app, 'location', 'domain', 'fqdn', 'alternateDomains', 'portBindings');
|
||||
const task = {
|
||||
args: { oldConfig },
|
||||
values: {}
|
||||
};
|
||||
addTask(app.id, exports.ISTATE_PENDING_CONFIGURE, task, () => iteratorDone()); // always succeed
|
||||
addTask(app.id, exports.ISTATE_PENDING_CONFIGURE, task, function (error, result) {
|
||||
if (error) debug(`configureInstalledApps: error marking ${app.fqdn} for configure: ${JSON.stringify(error)}`);
|
||||
else debug(`configureInstalledApps: marked ${app.id} for re-configure with taskId ${result.taskId}`);
|
||||
|
||||
iteratorDone(); // ignore error
|
||||
});
|
||||
}, callback);
|
||||
});
|
||||
}
|
||||
|
||||
// resume app tasks when platform is ready or after a crash
|
||||
function resumeTasks(callback) {
|
||||
// auto-restart app tasks after a crash
|
||||
function schedulePendingTasks(callback) {
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
debug('resuming tasks');
|
||||
|
||||
appTaskManager.initializeSync();
|
||||
debug('schedulePendingTasks: scheduling app tasks');
|
||||
|
||||
getAll(function (error, result) {
|
||||
if (error) return callback(error);
|
||||
@@ -1902,7 +1911,7 @@ function resumeTasks(callback) {
|
||||
result.forEach(function (app) {
|
||||
if (!app.taskId) return; // if not in any pending state, do nothing
|
||||
|
||||
debug(`resumeTask: schedule task for ${app.fqdn} ${app.id}: state=${app.installationState},taskId=${app.taskId}`);
|
||||
debug(`schedulePendingTasks: schedule task for ${app.fqdn} ${app.id}: state=${app.installationState},taskId=${app.taskId}`);
|
||||
|
||||
scheduleTask(app.id, app.installationState, app.taskId, NOOP_CALLBACK);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user