mirror of
https://github.com/strapi/strapi.git
synced 2025-09-01 12:53:03 +00:00
Merge pull request #27 from wistityhq/improvement/rebuild
Improve the rebuild process
This commit is contained in:
commit
a556094c2e
@ -170,6 +170,21 @@ module.exports = function (strapi) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
cb();
|
cb();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reload the hook
|
||||||
|
*/
|
||||||
|
|
||||||
|
reload: function () {
|
||||||
|
hook.initialize(function (err) {
|
||||||
|
if (err) {
|
||||||
|
strapi.log.error('Failed to reinitialize the API hook.');
|
||||||
|
strapi.stop();
|
||||||
|
} else {
|
||||||
|
strapi.emit('hook:_api:reloaded');
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -111,6 +111,13 @@ module.exports = function (strapi) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure the ORM config are equals to the databases file
|
||||||
|
// (aiming to not have issue with adapters when rebuilding the dictionary).
|
||||||
|
// It's kind of messy, for now, but it works fine. If someone has a better
|
||||||
|
// solution we'd be glad to accept a Pull Request.
|
||||||
|
const ormConfig = JSON.parse(fs.readFileSync(path.resolve(strapi.config.appPath, strapi.config.paths.config, 'environments', strapi.config.environment, 'databases.json')));
|
||||||
|
strapi.config.orm = ormConfig.orm;
|
||||||
|
|
||||||
// Save different environments inside an array because we need it in the Strapi Studio.
|
// Save different environments inside an array because we need it in the Strapi Studio.
|
||||||
strapi.config.environments = fs.readdirSync(path.resolve(strapi.config.appPath, strapi.config.paths.config, 'environments'));
|
strapi.config.environments = fs.readdirSync(path.resolve(strapi.config.appPath, strapi.config.paths.config, 'environments'));
|
||||||
|
|
||||||
@ -121,9 +128,24 @@ module.exports = function (strapi) {
|
|||||||
strapi.controllers = {};
|
strapi.controllers = {};
|
||||||
strapi.models = {};
|
strapi.models = {};
|
||||||
strapi.policies = {};
|
strapi.policies = {};
|
||||||
});
|
|
||||||
|
|
||||||
cb();
|
cb();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reload the hook
|
||||||
|
*/
|
||||||
|
|
||||||
|
reload: function () {
|
||||||
|
hook.initialize(function (err) {
|
||||||
|
if (err) {
|
||||||
|
strapi.log.error('Failed to reinitialize the config hook.');
|
||||||
|
strapi.stop();
|
||||||
|
} else {
|
||||||
|
strapi.emit('hook:_config:reloaded');
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
* Module dependencies
|
* Module dependencies
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Node.js core.
|
||||||
|
const cluster = require('cluster');
|
||||||
|
|
||||||
// Public node modules.
|
// Public node modules.
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
|
||||||
@ -36,6 +39,7 @@ module.exports = function (strapi) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
initialize: function (cb) {
|
initialize: function (cb) {
|
||||||
|
if ((cluster.isWorker && strapi.config.reload.workers > 0) || (cluster.isMaster && strapi.config.reload.workers < 1)) {
|
||||||
let route;
|
let route;
|
||||||
let controller;
|
let controller;
|
||||||
let action;
|
let action;
|
||||||
@ -139,8 +143,26 @@ module.exports = function (strapi) {
|
|||||||
this.app.emit('error', err, this);
|
this.app.emit('error', err, this);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
cb();
|
cb();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reload the hook
|
||||||
|
*/
|
||||||
|
|
||||||
|
reload: function () {
|
||||||
|
delete strapi.router;
|
||||||
|
|
||||||
|
hook.initialize(function (err) {
|
||||||
|
if (err) {
|
||||||
|
strapi.log.error('Failed to reinitialize the router.');
|
||||||
|
strapi.stop();
|
||||||
|
} else {
|
||||||
|
strapi.emit('hook:router:reloaded');
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -83,8 +83,11 @@ module.exports = function (strapi) {
|
|||||||
|
|
||||||
socket.on('connect', function () {
|
socket.on('connect', function () {
|
||||||
firstConnectionAttempt = false;
|
firstConnectionAttempt = false;
|
||||||
|
|
||||||
|
strapi.once('bootstrap:done', function () {
|
||||||
_self.connectWithStudio(socket);
|
_self.connectWithStudio(socket);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
socket.on('error', function (err) {
|
socket.on('error', function (err) {
|
||||||
strapi.log.warn(err);
|
strapi.log.warn(err);
|
||||||
@ -334,9 +337,11 @@ module.exports = function (strapi) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
rebuild: function (data, cb) {
|
rebuild: function (data, cb) {
|
||||||
strapi.restart();
|
process.nextTick(function () {
|
||||||
|
strapi.restart(function () {
|
||||||
cb(null, true);
|
cb(null, true);
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5,11 +5,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Node.js core.
|
// Node.js core.
|
||||||
|
const cluster = require('cluster');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const spawn = require('child_process').spawnSync;
|
const spawn = require('child_process').spawnSync;
|
||||||
|
|
||||||
// Public node modules.
|
// Public node modules.
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
const async = require('async');
|
||||||
const Waterline = require('waterline');
|
const Waterline = require('waterline');
|
||||||
const WaterlineGraphQL = require('waterline-graphql');
|
const WaterlineGraphQL = require('waterline-graphql');
|
||||||
|
|
||||||
@ -58,8 +60,9 @@ module.exports = function (strapi) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
initialize: function (cb) {
|
initialize: function (cb) {
|
||||||
if (_.isPlainObject(strapi.config.orm) && !_.isEmpty(strapi.config.orm)) {
|
if (_.isPlainObject(strapi.config.orm) && !_.isEmpty(strapi.config.orm) && ((cluster.isWorker && strapi.config.reload.workers > 0) || (cluster.isMaster && strapi.config.reload.workers < 1))) {
|
||||||
strapi.adapters = {};
|
strapi.adapters = {};
|
||||||
|
strapi.collections = [];
|
||||||
|
|
||||||
// Expose a new instance of Waterline.
|
// Expose a new instance of Waterline.
|
||||||
if (!strapi.orm) {
|
if (!strapi.orm) {
|
||||||
@ -147,7 +150,11 @@ module.exports = function (strapi) {
|
|||||||
|
|
||||||
// Finally, load the collection in the Waterline instance.
|
// Finally, load the collection in the Waterline instance.
|
||||||
try {
|
try {
|
||||||
strapi.orm.loadCollection(Waterline.Collection.extend(definition));
|
const collection = strapi.orm.loadCollection(Waterline.Collection.extend(definition));
|
||||||
|
|
||||||
|
if (_.isFunction(collection)) {
|
||||||
|
strapi.collections.push(collection);
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
strapi.log.error('Impossible to register the `' + model + '` model.');
|
strapi.log.error('Impossible to register the `' + model + '` model.');
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
@ -158,8 +165,8 @@ module.exports = function (strapi) {
|
|||||||
// globally expose models.
|
// globally expose models.
|
||||||
strapi.orm.initialize({
|
strapi.orm.initialize({
|
||||||
adapters: strapi.adapters,
|
adapters: strapi.adapters,
|
||||||
models: strapi.models,
|
|
||||||
connections: strapi.config.orm.connections,
|
connections: strapi.config.orm.connections,
|
||||||
|
collections: strapi.collections,
|
||||||
defaults: {
|
defaults: {
|
||||||
connection: strapi.config.orm.defaultConnection
|
connection: strapi.config.orm.defaultConnection
|
||||||
}
|
}
|
||||||
@ -170,7 +177,6 @@ module.exports = function (strapi) {
|
|||||||
global[globalName] = strapi.orm.collections[model];
|
global[globalName] = strapi.orm.collections[model];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
// Parse each models and look for associations.
|
// Parse each models and look for associations.
|
||||||
_.forEach(strapi.orm.collections, function (definition, model) {
|
_.forEach(strapi.orm.collections, function (definition, model) {
|
||||||
@ -193,11 +199,51 @@ module.exports = function (strapi) {
|
|||||||
usefulFunctions: true
|
usefulFunctions: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
strapi.log.warn('Waterline ORM disabled!');
|
|
||||||
}
|
|
||||||
|
|
||||||
cb();
|
cb();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
cb();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reload the hook
|
||||||
|
*/
|
||||||
|
|
||||||
|
reload: function () {
|
||||||
|
hook.teardown(function () {
|
||||||
|
delete strapi.orm;
|
||||||
|
|
||||||
|
hook.initialize(function (err) {
|
||||||
|
if (err) {
|
||||||
|
strapi.log.error('Failed to reinitialize the ORM hook.');
|
||||||
|
strapi.stop();
|
||||||
|
} else {
|
||||||
|
strapi.emit('hook:waterline:reloaded');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Teardown adapters
|
||||||
|
*/
|
||||||
|
|
||||||
|
teardown: function (cb) {
|
||||||
|
cb = cb || function (err) {
|
||||||
|
if (err) {
|
||||||
|
strapi.log.error('Failed to teardown ORM adapters.');
|
||||||
|
strapi.stop();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
async.forEach(Object.keys(strapi.adapters || {}), function (name, next) {
|
||||||
|
if (strapi.adapters[name].teardown) {
|
||||||
|
strapi.adapters[name].teardown(null, next);
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}, cb);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -59,14 +59,28 @@ module.exports = function initialize(cb) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Only run the application bootstrap if
|
|
||||||
// we are in a master cluster.
|
|
||||||
if (cluster.isMaster) {
|
if (cluster.isMaster) {
|
||||||
|
_.forEach(cluster.workers, function (worker) {
|
||||||
|
worker.on('message', function () {
|
||||||
|
self.emit('bootstrap:done');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only run the application bootstrap on master cluster if we don't have any workers.
|
||||||
|
// Else, run the bootstrap logic on the workers.
|
||||||
|
if ((cluster.isWorker && strapi.config.reload.workers > 0) || (cluster.isMaster && strapi.config.reload.workers < 1)) {
|
||||||
self.runBootstrap(function afterBootstrap(err) {
|
self.runBootstrap(function afterBootstrap(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
self.log.error('Bootstrap encountered an error.');
|
self.log.error('Bootstrap encountered an error.');
|
||||||
return cb(self.log.error(err));
|
return cb(self.log.error(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cluster.isWorker) {
|
||||||
|
process.send('message');
|
||||||
|
} else {
|
||||||
|
self.emit('bootstrap:done');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ module.exports = function (strapi) {
|
|||||||
|
|
||||||
// Prepare all other hooks.
|
// Prepare all other hooks.
|
||||||
prepare: function prepareHooks(cb) {
|
prepare: function prepareHooks(cb) {
|
||||||
async.each(_.without(_.keys(hooks), '_config', '_api'), function (id, cb) {
|
async.each(_.without(_.keys(hooks), '_config', '_api', 'studio'), function (id, cb) {
|
||||||
prepareHook(id);
|
prepareHook(id);
|
||||||
process.nextTick(cb);
|
process.nextTick(cb);
|
||||||
}, cb);
|
}, cb);
|
||||||
@ -131,7 +131,7 @@ module.exports = function (strapi) {
|
|||||||
|
|
||||||
// Apply the default config for all other hooks.
|
// Apply the default config for all other hooks.
|
||||||
defaults: function defaultConfigHooks(cb) {
|
defaults: function defaultConfigHooks(cb) {
|
||||||
async.each(_.without(_.keys(hooks), '_config', '_api'), function (id, cb) {
|
async.each(_.without(_.keys(hooks), '_config', '_api', 'studio'), function (id, cb) {
|
||||||
const hook = hooks[id];
|
const hook = hooks[id];
|
||||||
applyDefaults(hook);
|
applyDefaults(hook);
|
||||||
process.nextTick(cb);
|
process.nextTick(cb);
|
||||||
@ -140,9 +140,19 @@ module.exports = function (strapi) {
|
|||||||
|
|
||||||
// Load all other hooks.
|
// Load all other hooks.
|
||||||
load: function loadOtherHooks(cb) {
|
load: function loadOtherHooks(cb) {
|
||||||
async.each(_.without(_.keys(hooks), '_config', '_api'), function (id, cb) {
|
async.each(_.without(_.keys(hooks), '_config', '_api', 'studio'), function (id, cb) {
|
||||||
loadHook(id, cb);
|
loadHook(id, cb);
|
||||||
}, cb);
|
}, cb);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Load the studio hook.
|
||||||
|
studio: function loadStudioHook(cb) {
|
||||||
|
if (!hooks.studio) {
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
prepareHook('studio');
|
||||||
|
applyDefaults(hooks.studio);
|
||||||
|
loadHook('studio', cb);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -9,14 +9,88 @@ const cluster = require('cluster');
|
|||||||
|
|
||||||
// Public node modules.
|
// Public node modules.
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
const async = require('async');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Programmatically restart the server
|
* Programmatically restart the server
|
||||||
* (useful for the Studio)
|
* (useful for the Studio)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = function (cb) {
|
||||||
_.forEach(cluster.worker, function () {
|
const self = this;
|
||||||
|
|
||||||
|
console.log();
|
||||||
|
|
||||||
|
// Update the Strapi status (might be used
|
||||||
|
// by the core or some hooks).
|
||||||
|
self.reloading = true;
|
||||||
|
|
||||||
|
// Async module loader to rebuild a
|
||||||
|
// dictionary of the application.
|
||||||
|
async.auto({
|
||||||
|
|
||||||
|
// Rebuild the dictionaries.
|
||||||
|
dictionaries: function (cb) {
|
||||||
|
self.on('hook:_config:reloaded', function () {
|
||||||
|
self.on('hook:_api:reloaded', function () {
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
|
||||||
|
self.hooks._api.reload();
|
||||||
|
});
|
||||||
|
|
||||||
|
self.hooks._config.reload();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Callback.
|
||||||
|
function (err) {
|
||||||
|
|
||||||
|
// Just in case there is an error.
|
||||||
|
if (err) {
|
||||||
|
self.log.error('Impossible to reload the server');
|
||||||
|
self.log.error('Please restart the server manually');
|
||||||
|
self.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tell the application the framework is reloading
|
||||||
|
// (might be used by some hooks).
|
||||||
|
self.reloading = true;
|
||||||
|
|
||||||
|
// Teardown Waterline adapters and
|
||||||
|
// reload the Waterline ORM.
|
||||||
|
self.after('hook:waterline:reloaded', function () {
|
||||||
|
self.after('hook:router:reloaded', function () {
|
||||||
|
process.nextTick(function () {
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update `strapi` status.
|
||||||
|
self.reloaded = true;
|
||||||
|
self.reloading = false;
|
||||||
|
|
||||||
|
// Finally inform the developer everything seems ok.
|
||||||
|
if (cluster.isMaster && _.isPlainObject(strapi.config.reload) && !_.isEmpty(strapi.config.reload) && strapi.config.reload.workers < 1) {
|
||||||
|
self.log.info('Application\'s dictionnary updated');
|
||||||
|
self.log.warn('You still need to restart your server to fully enjoy changes...');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kill every worker processes.
|
||||||
|
_.forEach(cluster.workers, function () {
|
||||||
process.kill(process.pid, 'SIGHUP');
|
process.kill(process.pid, 'SIGHUP');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (cluster.isMaster && _.isPlainObject(strapi.config.reload) && !_.isEmpty(strapi.config.reload) && strapi.config.reload.workers > 0) {
|
||||||
|
self.log.info('Application restarted');
|
||||||
|
console.log();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Reloading the router.
|
||||||
|
self.hooks.router.reload();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Reloading the ORM.
|
||||||
|
self.hooks.waterline.reload();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
@ -129,6 +129,7 @@
|
|||||||
"no-else-return": 0,
|
"no-else-return": 0,
|
||||||
"no-extra-parens": 0,
|
"no-extra-parens": 0,
|
||||||
"no-implicit-coercion": 0,
|
"no-implicit-coercion": 0,
|
||||||
|
"no-inner-declarations": 0,
|
||||||
"no-invalid-this": 0,
|
"no-invalid-this": 0,
|
||||||
"no-negated-condition": 0,
|
"no-negated-condition": 0,
|
||||||
"no-throw-literal": 0,
|
"no-throw-literal": 0,
|
||||||
|
@ -9,6 +9,7 @@ describe('app.toJSON()', function () {
|
|||||||
|
|
||||||
obj.should.eql({
|
obj.should.eql({
|
||||||
subdomainOffset: 2,
|
subdomainOffset: 2,
|
||||||
|
proxy: false,
|
||||||
env: 'test'
|
env: 'test'
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -40,15 +40,6 @@ describe('ctx.type=', function () {
|
|||||||
ctx.response.header['content-type'].should.equal('text/html; charset=foo');
|
ctx.response.header['content-type'].should.equal('text/html; charset=foo');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('with an unknown extension', function () {
|
|
||||||
it('should default to application/octet-stream', function () {
|
|
||||||
const ctx = context();
|
|
||||||
ctx.type = 'asdf';
|
|
||||||
ctx.type.should.equal('application/octet-stream');
|
|
||||||
ctx.response.header['content-type'].should.equal('application/octet-stream');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('ctx.type', function () {
|
describe('ctx.type', function () {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user