diff --git a/src/platform.js b/src/platform.js index 8e71e74ce..381a0ee3f 100644 --- a/src/platform.js +++ b/src/platform.js @@ -146,7 +146,7 @@ async function startInfra(restoreOptions) { } if (existingInfra.version === 'none') await volumes.mountAll(); // when restoring, mount all volumes gStatus.message = 'Starting services, this can take a while'; - await services.startServices(existingInfra); + await services.startServices(existingInfra, function progresCallback({ message }) { gStatus.message = message; }); await fs.promises.writeFile(paths.INFRA_VERSION_FILE, JSON.stringify(infra, null, 4)); break; } catch (error) { diff --git a/src/services.js b/src/services.js index 36a7e9640..c71d5ad1d 100644 --- a/src/services.js +++ b/src/services.js @@ -797,41 +797,30 @@ async function applyMemoryLimit(id) { await docker.update(containerName, memoryLimit); } -async function startServices(existingInfra) { +async function startServices(existingInfra, progressCallback) { assert.strictEqual(typeof existingInfra, 'object'); + assert.strictEqual(typeof progressCallback, 'function'); - const startFuncs = []; + // name must match the image name in infra + const services = [ + { name: 'mail', label: 'Mail', fn: mailServer.start }, // start this first to reduce email downtime + { name: 'turn', label: 'TURN', fn: startTurn }, + { name: 'mysql', label: 'MySQL', fn: startMysql }, + { name: 'postgresql', label: 'PostgreSQL', fn: startPostgresql }, + { name: 'mongodb', label: 'MongoDB', fn: startMongodb }, + { name: 'redis', label: 'Redis', fn: startRedis }, + { name: 'graphite', label: 'Graphite', fn: startGraphite }, + { name: 'sftp', label: 'SFTP', fn: sftp.start }, + ]; - // always start addons on any infra change, regardless of minor or major update - if (existingInfra.version !== infra.version) { - debug(`startServices: ${existingInfra.version} -> ${infra.version}. starting all services`); - startFuncs.push( - mailServer.start, // start this first to reduce email downtime - startTurn, - startMysql, - startPostgresql, - startMongodb, - startRedis, - startGraphite, - sftp.start, - ); - } else { - assert.strictEqual(typeof existingInfra.images, 'object'); + const fullRebuild = existingInfra.version !== infra.version; + if (!fullRebuild && !existingInfra.images) throw new BoxError(BoxError.INTERNAL_ERROR, 'existing infra images is corrupt'); - if (infra.images.mail !== existingInfra.images.mail) startFuncs.push(mailServer.start); // start this first to reduce email downtime - if (infra.images.turn !== existingInfra.images.turn) startFuncs.push(startTurn); - if (infra.images.mysql !== existingInfra.images.mysql) startFuncs.push(startMysql); - if (infra.images.postgresql !== existingInfra.images.postgresql) startFuncs.push(startPostgresql); - if (infra.images.mongodb !== existingInfra.images.mongodb) startFuncs.push(startMongodb); - if (infra.images.redis !== existingInfra.images.redis) startFuncs.push(startRedis); - if (infra.images.graphite !== existingInfra.images.graphite) startFuncs.push(startGraphite); - if (infra.images.sftp !== existingInfra.images.sftp) startFuncs.push(sftp.start); + for (const {name, label, fn} of services) { + if (!fullRebuild && infra.images[name] === existingInfra.images[name]) continue; - debug('startServices: existing infra. incremental service create %j', startFuncs.map(function (f) { return f.name; })); - } - - for (const func of startFuncs) { - await func(existingInfra); + progressCallback({ message: `Starting ${label} service`}); + await fn(existingInfra); } // we always start db containers with unlimited memory. we then scale them down per configuration