UNPKG

kibana-123

Version:

Kibana is an open source (Apache Licensed), browser based analytics and search dashboard for Elasticsearch. Kibana is a snap to setup and start using. Kibana strives to be easy to get started with, while also being flexible and powerful, just like Elastic

160 lines (129 loc) 3.86 kB
import cluster from 'cluster'; const { join, resolve } = require('path'); const { format: formatUrl } = require('url'); import Hapi from 'hapi'; const { debounce, compact, get, invoke, bindAll, once, sample, uniq } = require('lodash'); import Log from '../log'; import Worker from './worker'; import BasePathProxy from './base_path_proxy'; process.env.kbnWorkerType = 'managr'; module.exports = class ClusterManager { constructor(opts = {}, settings = {}) { this.log = new Log(opts.quiet, opts.silent); this.addedCount = 0; const serverArgv = []; const optimizerArgv = [ '--plugins.initialize=false', '--uiSettings.enabled=false', '--server.autoListen=false', ]; if (opts.basePath) { this.basePathProxy = new BasePathProxy(this, settings); optimizerArgv.push( `--server.basePath=${this.basePathProxy.basePath}` ); serverArgv.push( `--server.port=${this.basePathProxy.targetPort}`, `--server.basePath=${this.basePathProxy.basePath}` ); } this.workers = [ this.optimizer = new Worker({ type: 'optmzr', title: 'optimizer', log: this.log, argv: optimizerArgv, watch: false }), this.server = new Worker({ type: 'server', log: this.log, argv: serverArgv }) ]; // broker messages between workers this.workers.forEach((worker) => { worker.on('broadcast', (msg) => { this.workers.forEach((to) => { if (to !== worker && to.online) { to.fork.send(msg); } }); }); }); bindAll(this, 'onWatcherAdd', 'onWatcherError', 'onWatcherChange'); if (opts.watch) { this.setupWatching([ ...settings.plugins.paths, ...settings.plugins.scanDirs ]); } else this.startCluster(); } startCluster() { this.setupManualRestart(); invoke(this.workers, 'start'); if (this.basePathProxy) { this.basePathProxy.listen(); } } setupWatching(extraPaths) { const chokidar = require('chokidar'); const fromRoot = require('../../utils/from_root'); const watchPaths = [ fromRoot('src/core_plugins'), fromRoot('src/server'), fromRoot('src/ui'), fromRoot('src/utils'), fromRoot('config'), ...extraPaths ].map(path => resolve(path)); this.watcher = chokidar.watch(uniq(watchPaths), { cwd: fromRoot('.'), ignored: /[\\\/](\..*|node_modules|bower_components|public|__tests__)[\\\/]/ }); this.watcher.on('add', this.onWatcherAdd); this.watcher.on('error', this.onWatcherError); this.watcher.on('ready', once(() => { // start sending changes to workers this.watcher.removeListener('add', this.onWatcherAdd); this.watcher.on('all', this.onWatcherChange); this.log.good('watching for changes', `(${this.addedCount} files)`); this.startCluster(); })); } setupManualRestart() { const readline = require('readline'); const rl = readline.createInterface(process.stdin, process.stdout); let nls = 0; const clear = () => nls = 0; const clearSoon = debounce(clear, 2000); rl.setPrompt(''); rl.prompt(); rl.on('line', line => { nls = nls + 1; if (nls >= 2) { clearSoon.cancel(); clear(); this.server.start(); } else { clearSoon(); } rl.prompt(); }); rl.on('SIGINT', () => { rl.pause(); process.kill(process.pid, 'SIGINT'); }); } onWatcherAdd() { this.addedCount += 1; } onWatcherChange(e, path) { invoke(this.workers, 'onChange', path); } onWatcherError(err) { this.log.bad('failed to watch files!\n', err.stack); process.exit(1); // eslint-disable-line no-process-exit } };