'use strict' import config from '../scripts/load-config.js' import Logger from '../scripts/logger.js' import cluster from 'cluster' import path from 'path' const cpuCount = require('os').cpus().length const workers = [] // Initialize the logger Logger.initialize() const args = { dev: process.env.NODE_ENV !== 'production', port: config.server.port } function spawnWorkers () { const workerCount = config.server.workers === 0 ? cpuCount : config.server.workers console.log('Spinning up %d worker process%s', workerCount, (workerCount !== 1 ? 'es' : '')) for (let i = 0; i < workerCount; i++) { spawnWorker() } } async function initialize () { try { const knex = require('knex')(require('../knexfile')) console.log('Initializing database...') await knex.migrate.latest() console.log('Database initialized') await knex.destroy() } catch (err) { console.error('Database error:', err) } spawnWorkers() if (args.dev) { watchFileTree() } } function watchFileTree () { if (process.argv.indexOf('-w') === -1) return console.log('[WatchTask] Starting watcher') const watch = require('watch') watch.watchTree(__dirname, (f, curr, prev) => { if (typeof f === 'object' && prev === null && curr === null) { console.log('[WatchTask] Watching %d files', Object.keys(f).length) return } console.log('[WatchTask] %s changed, restarting workers', f) if (workers.length) { for (const i in workers) { workers[i].send('stop') } } spawnWorkers() }) } function spawnWorker (oldWorker) { const w = cluster.fork() w.process.stdout.on('data', (data) => { console.log('[%s]', w.process.pid, data.toString().trim()) }) w.process.stderr.on('data', (data) => { console.error('[%s]', w.process.pid, data.toString().trim()) }) w.on('message', (message) => { if (message !== 'started') return workers.push(w) if (oldWorker) oldWorker.send('stop') }) args.id = w.process.pid w.send(args) return w } console.log('Initializing') cluster.setupMaster({ stdio: ['ignore', 'pipe', 'pipe', 'ipc'], exec: path.join(__dirname, './worker.js') }) cluster.on('exit', (worker, code, signal) => { const extra = ((code || '') + ' ' + (signal || '')).trim() console.error('Worker process %d exited %s', worker.process.pid, (extra ? '(' + extra + ')' : '')) const index = workers.indexOf(worker) if (index !== -1) workers.splice(index, 1) if (code === 0) return setTimeout(spawnWorker, 10 * 1000) }) initialize() process.stdin.resume() process.on('SIGUSR2', () => { console.log('Received SIGUSR2. Restarting workers.') if (workers.length) { for (const i in workers) { workers[i].send('stop') } } spawnWorkers() })