src/Index.js
// Import the neccesary modules.
import cluster from 'cluster';
import domain from 'domain';
import Express from 'express';
import http from 'http';
import os from 'os';
import setupRoutes from './config/routes';
import doSetup from './config/setup';
import { createLogger } from './config/logger';
import {
createTemp,
resetLog
} from './utils';
import {
master,
port,
workers
} from './config/constants';
/**
* Class for starting the API.
*
* @example
* // Simply start the API by creating a new instance of the Index class.
* const index = new Index();
*
* @example
* // Or override the default configuration of the Index class.
* const index = new Index({
* pretty: true,
* verbose: false,
* debug: false
* });
*/
export default class Index {
/**
* Create an index object.
* @param {Object} config - Configuration for the API.
* @param {Boolean} [config.pretty=true] - Pretty output with Winston logging.
* @param {Boolean} [config.verbose=false] - Debug mode for no output.
*/
constructor({pretty = true, verbose = false} = {}) { // eslint-disable-line object-curly-spacing
// The express object.
const _app = new Express();
// Setup the global logger object.
createLogger(pretty, verbose);
// Setup the MongoDB configuration and ExpressJS configuration.
doSetup(_app, pretty, verbose);
// Setup the API routes.
setupRoutes(_app);
/**
* The http server object.
* @type {Object}
*/
Index._server = http.createServer(_app);
// Start the API.
Index._startAPI();
}
/**
* Function to start the API.
* @returns {void}
*/
static _startAPI() {
if (cluster.isMaster) { // Check is the cluster is the master
// Clear the log files from the temp directory.
resetLog();
// Setup the temporary directory
createTemp();
// Fork workers.
for (let i = 0; i < Math.min(os.cpus().length, workers); i++) // eslint-disable-line semi-spacing
cluster.fork();
// Check for errors with the workers.
cluster.on('exit', worker => {
logger.error(`Worker '${worker.process.pid}' died, spinning up another!`);
cluster.fork();
});
if (master) {
// WARNING: Domain module is pending deprication: https://nodejs.org/api/domain.html
const scope = domain.create();
scope.run(() => logger.info('API started'));
scope.on('error', logger.error);
}
} else {
Index._server.listen(port);
}
}
/**
* Function to stop the API from running.
* @returns {void}
*/
static closeAPI() {
Index._server.close(() => {
logger.info('Closed out remaining connections.');
process.exit();
});
}
}