Skip to content

Commit

Permalink
Merge pull request #4611 from spalger/implement/devLiveOptimizer
Browse files Browse the repository at this point in the history
Implement dev live optimizer
  • Loading branch information
spalger committed Aug 11, 2015
2 parents aebcbf7 + a016f53 commit 153e195
Show file tree
Hide file tree
Showing 89 changed files with 1,682 additions and 1,291 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ target
esvm
.htpasswd
installedPlugins
webpackstats.json
config/kibana.dev.yml
2 changes: 1 addition & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require('babel/register');
require('babel/register')(require('./src/optimize/babelOptions'));

module.exports = function (grunt) {
// set the config once before calling load-grunt-config
Expand Down
Empty file added installedPlugins/.empty
Empty file.
14 changes: 12 additions & 2 deletions karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ module.exports = function (config) {

// list of files / patterns to load in the browser
files: [
'http://localhost:5601/bundles/commons.bundle.js',
'http://localhost:5601/bundles/tests.bundle.js',
'http://localhost:5601/bundles/tests.bundle.style.css'
'http://localhost:5601/bundles/commons.style.css',
'http://localhost:5601/bundles/tests.style.css'
],

proxies: {
Expand Down Expand Up @@ -57,6 +59,14 @@ module.exports = function (config) {

// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false
singleRun: false,

client: {
mocha: {
reporter: 'html', // change Karma's debug.html to the mocha web reporter
timeout: 10000,
slow: 5000
}
}
});
};
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,9 @@
"auto-preload-rjscommon-deps-loader": "^1.0.4",
"autoprefixer": "^5.2.0",
"autoprefixer-loader": "^2.0.0",
"babel": "^5.8.19",
"babel-core": "^5.8.19",
"babel": "^5.8.21",
"babel-core": "^5.8.21",
"babel-loader": "^5.3.2",
"babel-runtime": "^5.8.19",
"bluebird": "^2.9.27",
"boom": "^2.8.0",
"bootstrap": "^3.3.5",
Expand Down
12 changes: 12 additions & 0 deletions src/cli/Command.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,16 @@ Command.prototype.parseOptions = _.wrap(Command.prototype.parseOptions, function
return opts;
});

Command.prototype.action = _.wrap(Command.prototype.action, function (action, fn) {
return action.call(this, function (...args) {
var ret = fn.apply(this, args);
if (ret && typeof ret.then === 'function') {
ret.then(null, function (e) {
console.log('FATAL CLI ERROR', e.stack);
process.exit(1);
});
}
});
});

module.exports = Command;
94 changes: 94 additions & 0 deletions src/cli/cluster/ClusterManager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
let cluster = require('cluster');
let { join } = require('path');
let { compact, invoke, bindAll, once, get } = require('lodash');

let Log = require('../Log');
let Worker = require('./Worker');

module.exports = class ClusterManager {
constructor(opts) {
this.log = new Log(opts.quiet, opts.silent);
this.addedCount = 0;

this.workers = [
new Worker({
type: 'optmzr',
title: 'optimizer',
log: this.log,
argv: compact([
'--plugins.initialize=false',
'--server.autoListen=false'
]),
watch: false
}),

new Worker({
type: 'server',
log: this.log
})
];

// 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();
else this.startCluster();
}

startCluster() {
invoke(this.workers, 'start');
}

setupWatching() {
var chokidar = require('chokidar');
let utils = require('requirefrom')('src/utils');
let fromRoot = utils('fromRoot');

this.watcher = chokidar.watch([
'src/plugins',
'src/server',
'src/ui',
'src/utils',
'config',
'installedPlugins'
], {
cwd: fromRoot('.'),
ignored: /[\\\/](node_modules|bower_components|public)[\\\/]/,
});

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();
}));
}

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
}
};
27 changes: 16 additions & 11 deletions src/cli/watch/Worker.js → src/cli/cluster/Worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ module.exports = class Worker extends EventEmitter {
this.log = opts.log;
this.type = opts.type;
this.title = opts.title || opts.type;
this.filters = opts.filters;
this.watch = (opts.watch !== false);
this.online = false;
this.changes = [];

let argv = _.union(baseArgv, opts.argv || []);
Expand All @@ -31,7 +32,7 @@ module.exports = class Worker extends EventEmitter {
kbnWorkerArgv: JSON.stringify(argv)
};

_.bindAll(this, ['onExit', 'onMessage', 'shutdown', 'start']);
_.bindAll(this, ['onExit', 'onMessage', 'onOnline', 'onDisconnect', 'shutdown', 'start']);

this.start = _.debounce(this.start, 25);
cluster.on('exit', this.onExit);
Expand All @@ -53,15 +54,7 @@ module.exports = class Worker extends EventEmitter {
}

onChange(path) {
var valid = true;

if (this.filters) {
valid = _.any(this.filters, function (filter) {
return filter.test(path);
});
}

if (!valid) return;
if (!this.watch) return;
this.changes.push(path);
this.start();
}
Expand All @@ -70,6 +63,8 @@ module.exports = class Worker extends EventEmitter {
if (this.fork && !this.fork.isDead()) {
this.fork.kill();
this.fork.removeListener('message', this.onMessage);
this.fork.removeListener('online', this.onOnline);
this.fork.removeListener('disconnect', this.onDisconnect);
}
}

Expand All @@ -78,6 +73,14 @@ module.exports = class Worker extends EventEmitter {
this.emit('broadcast', msg[1]);
}

onOnline() {
this.online = true;
}

onDisconnect() {
this.online = false;
}

flushChangeBuffer() {
let files = _.unique(this.changes.splice(0));
let prefix = files.length > 1 ? '\n - ' : '';
Expand All @@ -100,5 +103,7 @@ module.exports = class Worker extends EventEmitter {

this.fork = cluster.fork(this.env);
this.fork.on('message', this.onMessage);
this.fork.on('online', this.onOnline);
this.fork.on('disconnect', this.onDisconnect);
}
};
4 changes: 2 additions & 2 deletions src/cli/plugin/pluginInstaller.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function install(settings, logger) {
try {
fs.statSync(settings.pluginPath);

logger.error(`Plugin ${settings.package} already exists. Please remove before installing a new version.`);
logger.error(`Plugin ${settings.package} already exists, please remove before installing a new version`);
process.exit(70); // eslint-disable-line no-process-exit
} catch (e) {
if (e.code !== 'ENOENT') throw e;
Expand All @@ -31,7 +31,7 @@ function install(settings, logger) {
})
.then(function (curious) {
fs.renameSync(settings.workingPath, settings.pluginPath);
logger.log('Plugin installation complete!');
logger.log('Plugin installation complete');
})
.catch(function (e) {
logger.error(`Plugin installation was unsuccessful due to error "${e.message}"`);
Expand Down
2 changes: 1 addition & 1 deletion src/cli/plugin/pluginRemover.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ function remove(settings, logger) {
try {
fs.statSync(settings.pluginPath);
} catch (e) {
logger.log(`Plugin ${settings.package} does not exist.`);
logger.log(`Plugin ${settings.package} does not exist`);
return;
}

Expand Down
2 changes: 1 addition & 1 deletion src/cli/plugin/progressReporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ module.exports = function (logger, request) {
function handleEnd() {
if (hasError) return;

logger.log('Download Complete.');
logger.log('Download Complete');
_resolve();
}

Expand Down
46 changes: 30 additions & 16 deletions src/cli/serve/serve.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ let { isWorker } = require('cluster');
let { resolve } = require('path');

let cwd = process.cwd();
let readYamlConfig = require('./readYamlConfig');
let src = require('requirefrom')('src');
let fromRoot = src('utils/fromRoot');
let KbnServer = src('server/KbnServer');

let pathCollector = function () {
let paths = [];
Expand Down Expand Up @@ -51,22 +49,29 @@ module.exports = function (program) {
)
.option('--plugins <path>', 'an alias for --plugin-dir', pluginDirCollector)
.option('--dev', 'Run the server with development mode defaults')
.option('--no-watch', 'Prevent watching, use with --dev to prevent server restarts')
.action(function (opts) {
if (opts.dev && opts.watch && !isWorker) {
// stop processing the action and handoff to watch cluster manager
return require('../watch/watch')(opts);
.option('--no-watch', 'Prevents automatic restarts of the server in --dev mode')
.action(async function (opts) {
if (opts.dev && !isWorker) {
// stop processing the action and handoff to cluster manager
let ClusterManager = require('../cluster/ClusterManager');
new ClusterManager(opts);
return;
}

let readYamlConfig = require('./readYamlConfig');
let KbnServer = src('server/KbnServer');

let settings = readYamlConfig(opts.config || fromRoot('config/kibana.yml'));
let set = _.partial(_.set, settings);
let get = _.partial(_.get, settings);

if (opts.dev) {
set('env', 'development');
set('optimize.watch', opts.watch);
try { _.merge(settings, readYamlConfig(fromRoot('config/kibana.dev.yml'))); }
catch (e) { null; }
}

let set = _.partial(_.set, settings);
let get = _.partial(_.get, settings);

if (opts.dev) set('env', 'development');
if (opts.elasticsearch) set('elasticsearch.url', opts.elasticsearch);
if (opts.port) set('server.port', opts.port);
if (opts.host) set('server.host', opts.host);
Expand All @@ -82,13 +87,22 @@ module.exports = function (program) {

set('plugins.paths', [].concat(opts.pluginPath || []));

let server = new KbnServer(_.merge(settings, this.getUnknownOptions()));
let kbnServer = {};

try {
kbnServer = new KbnServer(_.merge(settings, this.getUnknownOptions()));
await kbnServer.ready();
}
catch (err) {
let { server } = kbnServer;

server.ready().catch(function (err) {
console.error(err.stack);
if (server) server.log(['fatal'], err);
else console.error('FATAL', err);

kbnServer.close();
process.exit(1); // eslint-disable-line no-process-exit
});
}

return server;
return kbnServer;
});
};
Loading

0 comments on commit 153e195

Please sign in to comment.