process.title = 'Jetsam API Server' const redbird = require('redbird') const Koa = require('koa') const app = require('app') const http = require('http') const { config, env, fs, boot } = require('bootstrap') const debug = require('debug')('server:boot') const pkg = require('./package.json') const Sentry = require('@sentry/node') const Tracing = require('@sentry/tracing') let server = null let worker = null function bindSentry(app) { const sentryUtil = require('vendor/sentry') sentryUtil.configure() debug('Binding sentry to app level errors') app.on('error', (err, ctx) => { console.error(err) Sentry.withScope(function (scope) { scope.addEventProcessor(function (event) { return Sentry.Handlers.parseRequest(event, ctx.request) }) Sentry.captureException(err) }) }) } async function launch( port = 0, host = config('app.host.web', `http://localhost:${port}`), ) { const koa = new Koa() const appserver = await app(koa) if (config('sentry.enabled')) { bindSentry(koa) } const httpServer = http.createServer(appserver.callback()) httpServer.listen(port) debug(`Listening on ${host}`) server = httpServer maybeSpawnWorker() return httpServer } async function runProxy() { const port = config('app.port') const proxy = redbird({ port, bunyan: false }) const hosts = config('services.proxy.hosts') await launch() const address = server.address() if (!address) { throw new Error('Failed to start') } debug(`Binding hosts [${hosts.join(', ')}] to server port ${address.port}`) for (const host of hosts) { proxy.register(host, `http://127.0.0.1:${address.port}`) } } function maybeSpawnWorker() { if (config('queue.driver') === 'async') { debug('Spawning async worker') const bindQueue = require('core/utils/queue') const { queue } = require('services') bindQueue() worker = queue.listen() } } async function main() { await boot() if (config('services.proxy.enabled')) { return await runProxy() } else { return await launch(config('app.port')) } } main().catch(e => { console.error(e) process.exit(1) }) const cleanupsigs = ['SIGINT', 'SIGTERM', 'SIGUSR2'] cleanupsigs.forEach(signal => { process.on(signal, () => { if (worker) { worker() } if (server) { server.close() } Sentry.close(2000).then(() => { process.exit(0) }) }) })