mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-30 14:22:07 +03:00
d675278b0b
no issue - recurring jobs spin up worker threads which can be quite CPU intensive even when not performing much processing, this can be problematic in environments where there are many Ghost instances running - updated the email job scheduling to be skipped on bootup when there are no emails in the database and to be started when the first email is created as long as we're not in testing env - increase analytics job schedule from every 2 minutes to every 5 minutes to help spread the load further across instances
214 lines
7.3 KiB
JavaScript
214 lines
7.3 KiB
JavaScript
/**
|
|
* make sure overrides get's called first!
|
|
* - keeping the overrides import here works for installing Ghost as npm!
|
|
*
|
|
* the call order is the following:
|
|
* - root index requires core module
|
|
* - core index requires server
|
|
* - overrides is the first package to load
|
|
*/
|
|
require('./overrides');
|
|
|
|
const debug = require('ghost-ignition').debug('boot:init');
|
|
const Promise = require('bluebird');
|
|
const config = require('../shared/config');
|
|
const {events, i18n} = require('./lib/common');
|
|
const logging = require('../shared/logging');
|
|
const migrator = require('./data/db/migrator');
|
|
const urlUtils = require('./../shared/url-utils');
|
|
let parentApp;
|
|
|
|
// Frontend Components
|
|
const themeService = require('../frontend/services/themes');
|
|
const appService = require('../frontend/services/apps');
|
|
const frontendSettings = require('../frontend/services/settings');
|
|
|
|
function initialiseServices() {
|
|
// CASE: When Ghost is ready with bootstrapping (db migrations etc.), we can trigger the router creation.
|
|
// Reason is that the routers access the routes.yaml, which shouldn't and doesn't have to be validated to
|
|
// start Ghost in maintenance mode.
|
|
// Routing is a bridge between the frontend and API
|
|
const routing = require('../frontend/services/routing');
|
|
// We pass the themeService API version here, so that the frontend services are less tightly-coupled
|
|
routing.bootstrap.start(themeService.getApiVersion());
|
|
|
|
const settings = require('./services/settings');
|
|
const permissions = require('./services/permissions');
|
|
const xmlrpc = require('./services/xmlrpc');
|
|
const slack = require('./services/slack');
|
|
const {mega} = require('./services/mega');
|
|
const webhooks = require('./services/webhooks');
|
|
const scheduling = require('./adapters/scheduling');
|
|
|
|
debug('`initialiseServices` Start...');
|
|
const getRoutesHash = () => frontendSettings.getCurrentHash('routes');
|
|
|
|
return Promise.join(
|
|
// Initialize the permissions actions and objects
|
|
permissions.init(),
|
|
xmlrpc.listen(),
|
|
slack.listen(),
|
|
mega.listen(),
|
|
webhooks.listen(),
|
|
settings.syncRoutesHash(getRoutesHash),
|
|
appService.init(),
|
|
scheduling.init({
|
|
// NOTE: When changing API version need to consider how to migrate custom scheduling adapters
|
|
// that rely on URL to lookup persisted scheduled records (jobs, etc.). Ref: https://github.com/TryGhost/Ghost/pull/10726#issuecomment-489557162
|
|
apiUrl: urlUtils.urlFor('api', {version: 'v3', versionType: 'admin'}, true)
|
|
})
|
|
).then(function () {
|
|
debug('XMLRPC, Slack, MEGA, Webhooks, Scheduling, Permissions done');
|
|
|
|
// Initialise analytics events
|
|
if (config.get('segment:key')) {
|
|
require('./analytics-events').init();
|
|
}
|
|
}).then(function () {
|
|
debug('...`initialiseServices` End');
|
|
});
|
|
}
|
|
|
|
async function initializeRecurringJobs() {
|
|
// we don't want to kick off scheduled/recurring jobs that will interfere with tests
|
|
if (process.env.NODE_ENV.match(/^testing/)) {
|
|
return;
|
|
}
|
|
|
|
if (config.get('backgroundJobs:emailAnalytics')) {
|
|
const emailAnalyticsJobs = require('./services/email-analytics/jobs');
|
|
await emailAnalyticsJobs.scheduleRecurringJobs();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* - initialise models
|
|
* - initialise i18n
|
|
* - load all settings into settings cache (almost every component makes use of this cache)
|
|
* - load active theme
|
|
* - create our express apps (site, admin, api)
|
|
* - start the ghost server
|
|
* - enable maintenance mode if migrations are missing
|
|
*/
|
|
const minimalRequiredSetupToStartGhost = (dbState) => {
|
|
const settings = require('./services/settings');
|
|
const jobService = require('./services/jobs');
|
|
const models = require('./models');
|
|
const GhostServer = require('./ghost-server');
|
|
|
|
let ghostServer;
|
|
|
|
// Initialize Ghost core internationalization
|
|
i18n.init();
|
|
debug('Default i18n done for core');
|
|
|
|
models.init();
|
|
debug('Models done');
|
|
|
|
return settings.init()
|
|
.then(() => {
|
|
debug('Settings done');
|
|
|
|
return frontendSettings.init();
|
|
})
|
|
.then(() => {
|
|
debug('Frontend settings done');
|
|
return themeService.init();
|
|
})
|
|
.then(() => {
|
|
debug('Themes done');
|
|
|
|
parentApp = require('./web/parent/app')();
|
|
debug('Express Apps done');
|
|
|
|
return new GhostServer(parentApp);
|
|
})
|
|
.then((_ghostServer) => {
|
|
ghostServer = _ghostServer;
|
|
|
|
ghostServer.registerCleanupTask(async () => {
|
|
await jobService.shutdown();
|
|
});
|
|
|
|
// CASE: all good or db was just initialised
|
|
if (dbState === 1 || dbState === 2) {
|
|
events.emit('db.ready');
|
|
|
|
return initialiseServices()
|
|
.then(() => {
|
|
initializeRecurringJobs();
|
|
})
|
|
.then(() => {
|
|
return ghostServer;
|
|
});
|
|
}
|
|
|
|
// CASE: migrations required, put blog into maintenance mode
|
|
if (dbState === 4) {
|
|
logging.info('Blog is in maintenance mode.');
|
|
|
|
config.set('maintenance:enabled', true);
|
|
|
|
migrator.migrate()
|
|
.then(() => {
|
|
return settings.reinit().then(() => {
|
|
events.emit('db.ready');
|
|
return initialiseServices();
|
|
});
|
|
})
|
|
.then(() => {
|
|
config.set('maintenance:enabled', false);
|
|
logging.info('Blog is out of maintenance mode.');
|
|
return GhostServer.announceServerReadiness();
|
|
})
|
|
.then(() => {
|
|
initializeRecurringJobs();
|
|
})
|
|
.catch((err) => {
|
|
return GhostServer.announceServerReadiness(err)
|
|
.finally(() => {
|
|
logging.error(err);
|
|
setTimeout(() => {
|
|
process.exit(-1);
|
|
}, 100);
|
|
});
|
|
});
|
|
|
|
return ghostServer;
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Connect to database.
|
|
* Check db state.
|
|
*/
|
|
const isDatabaseInitialisationRequired = () => {
|
|
const db = require('./data/db/connection');
|
|
let dbState;
|
|
|
|
return migrator.getState()
|
|
.then((state) => {
|
|
dbState = state;
|
|
|
|
// CASE: db initialisation required, wait till finished
|
|
if (dbState === 2) {
|
|
return migrator.dbInit();
|
|
}
|
|
|
|
// CASE: is db incompatible? e.g. you can't connect a 0.11 database with Ghost 1.0 or 2.0
|
|
if (dbState === 3) {
|
|
return migrator.isDbCompatible(db)
|
|
.then(() => {
|
|
dbState = 2;
|
|
return migrator.dbInit();
|
|
});
|
|
}
|
|
})
|
|
.then(() => {
|
|
return minimalRequiredSetupToStartGhost(dbState);
|
|
});
|
|
};
|
|
|
|
module.exports = isDatabaseInitialisationRequired;
|