diff --git a/src/platform.js b/src/platform.js index fdf2648ab..23c330f9a 100644 --- a/src/platform.js +++ b/src/platform.js @@ -2,6 +2,12 @@ exports = module.exports = { initialize: initialize, + uninitialize: uninitialize, + + events: new (require('events').EventEmitter)(), + EVENT_READY: 'ready', + + isReadySync: isReadySync, mailConfig: mailConfig }; @@ -22,7 +28,8 @@ var apps = require('./apps.js'), shell = require('./shell.js'), util = require('util'); -var gAddonVars = null; +var gAddonVars = null, + gPlatformReadyTimer = null; function initialize(callback) { if (process.env.BOX_ENV === 'test' && !process.env.CREATE_INFRA) return callback(); @@ -52,6 +59,24 @@ function initialize(callback) { mailboxes.setupAliases, fs.writeFile.bind(fs, paths.INFRA_VERSION_FILE, JSON.stringify(infra)) ], callback); + + // give 30 seconds for the platform to "settle". For example, mysql might still be initing the + // database dir and we cannot call service scripts until that's done. + // TODO: make this smarter to not wait for 30secs for the crash-restart case + gPlatformReadyTimer = setTimeout(function () { + gPlatformReadyTimer = null; + exports.events.emit(exports.EVENT_READY); + }, 30000); +} + +function uninitialize(callback) { + clearTimeout(gPlatformReadyTimer); + gPlatformReadyTimer = null; + callback(); +} + +function isReadySync() { + return gPlatformReadyTimer === null; } function removeOldImages(callback) { diff --git a/src/server.js b/src/server.js index 8ccd57704..983c1ecba 100644 --- a/src/server.js +++ b/src/server.js @@ -291,6 +291,7 @@ function stop(callback) { auth.uninitialize, cloudron.uninitialize, taskmanager.uninitialize, + platform.uninitialize, cron.uninitialize, mailer.uninitialize, database.uninitialize, diff --git a/src/taskmanager.js b/src/taskmanager.js index 98e231590..0ba48074f 100644 --- a/src/taskmanager.js +++ b/src/taskmanager.js @@ -19,14 +19,13 @@ var appdb = require('./appdb.js'), cloudron = require('./cloudron.js'), debug = require('debug')('box:taskmanager'), locker = require('./locker.js'), + platform = require('./platform.js'), sendFailureLogs = require('./logcollector.js').sendFailureLogs, util = require('util'), _ = require('underscore'); var gActiveTasks = { }; var gPendingTasks = [ ]; -var gPlatformReady = false; // PaaS (addons) up and running -var gPlatformReadyTimer = null; var TASK_CONCURRENCY = 5; var NOOP_CALLBACK = function (error) { if (error) console.error(error); }; @@ -36,15 +35,7 @@ function initialize(callback) { locker.on('unlocked', startNextTask); - gPlatformReadyTimer = setTimeout(function () { - gPlatformReady = true; - - if (cloudron.isConfiguredSync()) { - resumeTasks(); - } else { - cloudron.events.on(cloudron.EVENT_CONFIGURED, resumeTasks); - } - }, 30000); // wait 30 seconds to signal platform ready + platform.events.on(platform.EVENT_READY, platformReady); callback(); } @@ -54,9 +45,9 @@ function uninitialize(callback) { gPendingTasks = [ ]; // clear this first, otherwise stopAppTask will resume them - clearTimeout(gPlatformReadyTimer); - cloudron.events.removeListener(cloudron.EVENT_CONFIGURED, resumeTasks); + platform.events.removeListener(platform.EVENT_READY, platformReady); + locker.removeListener('unlocked', startNextTask); async.eachSeries(Object.keys(gActiveTasks), stopAppTask, callback); @@ -81,6 +72,14 @@ function waitForPendingTasks(callback) { checkTasks(); } +function platformReady() { + if (cloudron.isConfiguredSync()) { + resumeTasks(); + } else { + cloudron.events.on(cloudron.EVENT_CONFIGURED, resumeTasks); + } +} + // resume app installs and uninstalls function resumeTasks(callback) { callback = callback || NOOP_CALLBACK; @@ -119,7 +118,7 @@ function startAppTask(appId, callback) { return callback(new Error(util.format('Task for %s is already active', appId))); } - if (!gPlatformReady) { + if (!platform.isReadySync()) { debug('Platform not ready yet, queueing task for %s', appId); gPendingTasks.push(appId); return callback();