diff --git a/lib/cli.js b/lib/cli.js index 3b2d1490..1bb25afc 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -435,6 +435,23 @@ program }) }) +program + .command('migrate') + .description('migrates the database to the latest version') + .action(function() { + var log = logger.createLogger('cli:migrate') + , db = require('./db') + + db.setup() + .then(function() { + process.exit(0) + }) + .catch(function(err) { + log.fatal('Migration had an error:', err.stack) + process.exit(1) + }) + }) + program .command('local [serial..]') .description('start everything locally') @@ -485,114 +502,124 @@ program .option('-d, --disable-watch' , 'disable watching resources') .action(function() { - var log = logger.createLogger('cli') + var log = logger.createLogger('cli:local') , options = cliutil.lastArg(arguments) + , db = require('./db') - var procs = [ - // app triproxy - procutil.fork(__filename, [ - 'triproxy', 'app001' - , '--bind-pub', options.bindAppPub - , '--bind-dealer', options.bindAppDealer - , '--bind-pull', options.bindAppPull - ]) + // Each forked process waits for signals to stop, and we run over the + // default limit of 10. So, it's not a leak, but a refactor wouldn't hurt. + process.setMaxListeners(20) - // device triproxy - , procutil.fork(__filename, [ - 'triproxy', 'dev001' - , '--bind-pub', options.bindDevPub - , '--bind-dealer', options.bindDevDealer - , '--bind-pull', options.bindDevPull - ]) + function run() { + var procs = [ + // app triproxy + procutil.fork(__filename, [ + 'triproxy', 'app001' + , '--bind-pub', options.bindAppPub + , '--bind-dealer', options.bindAppDealer + , '--bind-pull', options.bindAppPull + ]) - // processor one - , procutil.fork(__filename, [ - 'processor', 'proc001' - , '--connect-app-dealer', options.bindAppDealer - , '--connect-dev-dealer', options.bindDevDealer - ]) + // device triproxy + , procutil.fork(__filename, [ + 'triproxy', 'dev001' + , '--bind-pub', options.bindDevPub + , '--bind-dealer', options.bindDevDealer + , '--bind-pull', options.bindDevPull + ]) - // processor two - , procutil.fork(__filename, [ - 'processor', 'proc002' - , '--connect-app-dealer', options.bindAppDealer - , '--connect-dev-dealer', options.bindDevDealer - ]) + // processor one + , procutil.fork(__filename, [ + 'processor', 'proc001' + , '--connect-app-dealer', options.bindAppDealer + , '--connect-dev-dealer', options.bindDevDealer + ]) - // reaper one - , procutil.fork(__filename, [ - 'reaper', 'reaper001' - , '--connect-push', options.bindDevPull - ]) + // processor two + , procutil.fork(__filename, [ + 'processor', 'proc002' + , '--connect-app-dealer', options.bindAppDealer + , '--connect-dev-dealer', options.bindDevDealer + ]) - // provider - , procutil.fork(__filename, [ - 'provider' - , '--name', options.provider - , '--connect-sub', options.bindDevPub - , '--connect-push', options.bindDevPull - ].concat(cliutil.allUnknownArgs(arguments))) + // reaper one + , procutil.fork(__filename, [ + 'reaper', 'reaper001' + , '--connect-push', options.bindDevPull + ]) - // auth-mock - , procutil.fork(__filename, [ - 'auth-mock' - , '--port', options.authPort - , '--secret', options.authSecret - , '--app-url', util.format('http://localhost:%d/', options.appPort) - ]) + // provider + , procutil.fork(__filename, [ + 'provider' + , '--name', options.provider + , '--connect-sub', options.bindDevPub + , '--connect-push', options.bindDevPull + ].concat(cliutil.allUnknownArgs(arguments))) - // app - , procutil.fork(__filename, [ - 'app' - , '--port', options.appPort - , '--secret', options.authSecret - , '--auth-url', util.format('http://localhost:%d/', options.authPort) - , '--storage-url' - , util.format('http://localhost:%d/', options.storagePort) - , '--connect-sub', options.bindAppPub - , '--connect-push', options.bindAppPull - ].concat((function() { - var extra = [] - if (options.disableWatch) { - extra.push('--disable-watch') - } - return extra - })())) + // auth-mock + , procutil.fork(__filename, [ + 'auth-mock' + , '--port', options.authPort + , '--secret', options.authSecret + , '--app-url', util.format('http://localhost:%d/', options.appPort) + ]) - // storage - , procutil.fork(__filename, [ - 'storage-temp' - , '--port', options.storagePort - ]) - ] + // app + , procutil.fork(__filename, [ + 'app' + , '--port', options.appPort + , '--secret', options.authSecret + , '--auth-url', util.format('http://localhost:%d/', options.authPort) + , '--storage-url' + , util.format('http://localhost:%d/', options.storagePort) + , '--connect-sub', options.bindAppPub + , '--connect-push', options.bindAppPull + ].concat((function() { + var extra = [] + if (options.disableWatch) { + extra.push('--disable-watch') + } + return extra + })())) - function shutdown() { - log.info('Shutting down all child processes') - procs.forEach(function(proc) { - proc.cancel() + // storage + , procutil.fork(__filename, [ + 'storage-temp' + , '--port', options.storagePort + ]) + ] + + function shutdown() { + log.info('Shutting down all child processes') + procs.forEach(function(proc) { + proc.cancel() + }) + return Promise.settle(procs) + } + + process.on('SIGINT', function() { + log.info('Received SIGINT, waiting for processes to terminate') }) - return Promise.settle(procs) + + process.on('SIGTERM', function() { + log.info('Received SIGTERM, waiting for processes to terminate') + }) + + return Promise.all(procs) + .then(function() { + process.exit(0) + }) + .catch(function(err) { + log.fatal('Child process had an error', err.stack) + return shutdown() + .then(function() { + process.exit(1) + }) + }) } - process.on('SIGINT', function() { - log.info('Received SIGINT, waiting for processes to terminate') - }) - - process.on('SIGTERM', function() { - log.info('Received SIGTERM, waiting for processes to terminate') - }) - - Promise.all(procs) - .then(function() { - process.exit(0) - }) - .catch(function(err) { - log.fatal('Child process had an error', err.stack) - return shutdown() - .then(function() { - process.exit(1) - }) - }) + procutil.fork(__filename, ['migrate']) + .then(run) }) program.parse(process.argv) diff --git a/lib/db/index.js b/lib/db/index.js index a2889a8b..b24bca66 100644 --- a/lib/db/index.js +++ b/lib/db/index.js @@ -1,6 +1,7 @@ var setup = require('./setup') var rutil = require('../util/rutil') var logger = require('../util/logger') +var lifecycle = require('../util/lifecycle') function connect() { var log = logger.createLogger('db') @@ -11,11 +12,10 @@ function connect() { , authKey: process.env.RDB_AUTHKEY }) .then(function(conn) { - conn.on('error', function(err) { + return conn.on('error', function(err) { log.fatal('Connection error', err.stack) - process.exit(1) + lifecycle.fatal() }) - return setup(conn) }) .catch(function(err) { log.fatal('Unable to connect to the database: "%s"', err.message) @@ -46,3 +46,10 @@ db.run = function(q, options) { return rutil.run(conn, q, options) }) } + +// Sets up the database +db.setup = function() { + return db.connect().then(function(conn) { + return setup(conn) + }) +}