0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-01-06 22:40:14 -05:00

Finalised new boot process

- This commit removes the old boot process and any files that are no longer needed as a result
- Remove the duplicate event for triggering inactive themes to load
- Tidied up a few other bits
This commit is contained in:
Hannah Wolfe 2021-02-16 11:42:51 +00:00
parent 9e93ed7ef0
commit 481e2425af
12 changed files with 16 additions and 403 deletions

View file

@ -208,7 +208,6 @@ async function bootGhost() {
debug('End: Load sentry');
debug('Begin: load server + minimal app');
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
// Get minimal application in maintenance mode
const rootApp = require('./app');
@ -241,7 +240,7 @@ async function bootGhost() {
mountGhost(rootApp, ghostApp);
// Announce Server Readiness
logging.info('Ghost boot', (Date.now() - startTime) / 1000 + 's');
logging.info('Ghost booted', (Date.now() - startTime) / 1000 + 's');
debug('boot announcing readiness');
GhostServer.announceServerReadiness();

View file

@ -23,11 +23,8 @@ module.exports = {
debug('init themes', activeThemeName);
// Register a listener for server-start to load all themes
events.on('server.start', function readAllThemesOnServerStart() {
themeLoader.loadAllThemes();
});
events.on('themes.ready', function readAllThemesOnServerStart() {
// Register a listener for when the server says we can start to load all themes
events.on('themes.ready', function readAllThemesOnReady() {
themeLoader.loadAllThemes();
});

View file

@ -1,26 +0,0 @@
// ## Server Loader
// Passes options through the boot process to get a server instance back
const server = require('./server');
const errors = require('@tryghost/errors');
const GhostServer = require('./server/ghost-server');
// Set the default environment to be `development`
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
function makeGhost(options) {
options = options || {};
return server(options)
.catch((err) => {
if (!errors.utils.isIgnitionError(err)) {
err = new errors.GhostError({message: err.message, err: err});
}
return GhostServer.announceServerReadiness(err)
.finally(() => {
throw err;
});
});
}
module.exports = makeGhost;

View file

@ -1,74 +0,0 @@
const KnexMigrator = require('knex-migrator');
const config = require('../../../shared/config');
const errors = require('@tryghost/errors');
const knexMigrator = new KnexMigrator({
knexMigratorFilePath: config.get('paths:appRoot')
});
module.exports.getState = () => {
let state;
let err;
return knexMigrator.isDatabaseOK()
.then(() => {
state = 1;
return state;
})
.catch((_err) => {
err = _err;
// CASE: database was never created
if (err.code === 'DB_NOT_INITIALISED') {
state = 2;
return state;
}
// CASE: you have created the database on your own, you have an existing none compatible db?
if (err.code === 'MIGRATION_TABLE_IS_MISSING') {
state = 3;
return state;
}
// CASE: database needs migrations
if (err.code === 'DB_NEEDS_MIGRATION') {
state = 4;
return state;
}
// CASE: database connection errors, unknown cases
throw err;
});
};
module.exports.dbInit = () => {
return knexMigrator.init();
};
module.exports.migrate = () => {
return knexMigrator.migrate();
};
module.exports.isDbCompatible = (connection) => {
return connection.raw('SELECT `key` FROM settings WHERE `key`="databaseVersion";')
.then((response) => {
if (!response || !response[0].length) {
return;
}
throw new errors.DatabaseVersionError({
message: 'Your database version is not compatible with Ghost 2.0.',
help: 'Want to keep your DB? Use Ghost < 1.0.0 or the "0.11" branch.' +
'\n\n\n' +
'Want to migrate Ghost 0.11 to 2.0? Please visit https://ghost.org/docs/update/'
});
})
.catch((err) => {
// CASE settings table doesn't exists
if (err.errno === 1146 || err.errno === 1) {
return;
}
throw err;
});
};

View file

@ -199,15 +199,6 @@ class GhostServer {
}
}
/**
* @param {Object} externalApp - express app instance
* @return {Promise} Resolves once Ghost has switched HTTP Servers
*/
async swapHttpApp(externalApp) {
await this._stopServer();
await this.start(externalApp);
}
/**
* ### Hammertime
* To be called after `stop`

View file

@ -1,203 +0,0 @@
/**
* 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');
// Frontend Components
const themeService = require('../frontend/services/themes');
const appService = require('../frontend/services/apps');
const frontendSettings = require('../frontend/services/settings');
async 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');
await Promise.all([
// 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)
})
]);
debug('XMLRPC, Slack, MEGA, Webhooks, Scheduling, Permissions done');
// Initialise analytics events
if (config.get('segment:key')) {
require('./analytics-events').init();
}
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();
}
}
const initExpressApps = async () => {
await frontendSettings.init();
debug('Frontend settings done');
await themeService.init();
debug('Themes done');
const parentApp = require('./web/parent/app')();
debug('Express Apps done');
return parentApp;
};
/**
* - initialise models
* - initialise i18n
* - start the ghost server
* - load all settings into settings cache (almost every component makes use of this cache)
* - enable maintenance mode if migrations are missing
* - load active theme
* - create our express apps (site, admin, api)
*/
const minimalRequiredSetupToStartGhost = async (dbState) => {
const settings = require('./services/settings');
const jobService = require('./services/jobs');
const models = require('./models');
const GhostServer = require('./ghost-server');
// Initialize Ghost core internationalization
i18n.init();
debug('Default i18n done for core');
models.init();
debug('Models done');
const ghostServer = new GhostServer();
ghostServer.registerCleanupTask(async () => {
await jobService.shutdown();
});
// CASE: all good or db was just initialised
if (dbState === 1 || dbState === 2) {
await settings.init();
debug('Settings done');
const parentApp = await initExpressApps();
ghostServer.rootApp = parentApp;
events.emit('db.ready');
await initialiseServices();
}
// CASE: migrations required, put blog into maintenance mode
if (dbState === 4) {
config.set('maintenance:enabled', true);
logging.info('Blog is in maintenance mode.');
ghostServer.rootApp = require('./web/maintenance');
try {
migrator.migrate()
.then(async () => {
await settings.init();
debug('Settings done');
const parentApp = await initExpressApps();
ghostServer.swapHttpApp(parentApp);
events.emit('db.ready');
await initialiseServices();
config.set('maintenance:enabled', false);
logging.info('Blog is out of maintenance mode.');
await GhostServer.announceServerReadiness();
});
} catch (err) {
try {
await GhostServer.announceServerReadiness(err);
} finally {
logging.error(err);
setTimeout(() => {
process.exit(1);
}, 100);
}
}
}
initializeRecurringJobs();
return ghostServer;
};
/**
* Connect to database.
* Check db state.
*/
const isDatabaseInitialisationRequired = async () => {
const db = require('./data/db/connection');
let dbState = await migrator.getState();
// CASE: db initialisation required, wait till finished
if (dbState === 2) {
await 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) {
await migrator.isDbCompatible(db);
dbState = 2;
await migrator.dbInit();
}
return minimalRequiredSetupToStartGhost(dbState);
};
module.exports = isDatabaseInitialisationRequired;

View file

@ -1,6 +0,0 @@
const MaintenanceApp = require('@tryghost/maintenance');
const express = require('../../../shared/express');
module.exports = new MaintenanceApp({
express
}).app;

View file

@ -1,14 +1,19 @@
const argv = process.argv;
/**
* Internal CLI Placeholder
*
* If we want to add alternative commands, flags, or modify environment vars, it should all go here.
* Important: This file should not contain any requires, unless we decide to add pretty-cli/commander type tools
*
**/
const mode = argv[2] || 'new';
// Don't allow NODE_ENV to be null
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
const argv = process.argv;
const mode = argv[2];
// Switch between boot modes
switch (mode) {
case 'old':
case '3':
// Old boot sequence
require('./startup');
break;
default:
// New boot sequence
require('./core/boot')();

View file

@ -56,7 +56,6 @@
"@tryghost/kg-markdown-html-renderer": "4.0.0-rc.2",
"@tryghost/kg-mobiledoc-html-renderer": "4.0.0-rc.1",
"@tryghost/magic-link": "0.6.6",
"@tryghost/maintenance": "0.1.0",
"@tryghost/members-api": "1.0.0-rc.3",
"@tryghost/members-csv": "0.4.4",
"@tryghost/members-ssr": "0.8.10",

View file

@ -1,44 +0,0 @@
// # Ghost Startup
// Orchestrates the startup of Ghost when run from command line.
const startTime = Date.now();
const debug = require('ghost-ignition').debug('boot:index');
// Sentry must be initialised early on
const sentry = require('./core/shared/sentry');
debug('First requires...');
const ghost = require('./core');
debug('Required ghost');
const express = require('./core/shared/express');
const logging = require('./core/shared/logging');
const urlService = require('./core/frontend/services/url');
logging.info('Boot Mode: 3.0');
// This is what listen gets called on, it needs to be a full Express App
const ghostApp = express('ghost');
// Use the request handler at the top level
// @TODO: decide if this should be here or in parent App - should it come after request id mw?
ghostApp.use(sentry.requestHandler);
debug('Initialising Ghost');
ghost().then(function (ghostServer) {
// Mount our Ghost instance on our desired subdirectory path if it exists.
ghostApp.use(urlService.utils.getSubdir(), ghostServer.rootApp);
debug('Starting Ghost');
// Let Ghost handle starting our server instance.
return ghostServer.start(ghostApp)
.then(function afterStart() {
logging.info('Ghost boot', (Date.now() - startTime) / 1000 + 's');
});
}).catch(function (err) {
logging.error(err);
setTimeout(() => {
process.exit(-1);
}, 100);
});

View file

@ -14,13 +14,10 @@ const knexMigrator = new KnexMigrator();
// Ghost Internals
const config = require('../../core/shared/config');
const boot = require('../../core/boot');
const express = require('../../core/shared/express');
const ghost = require('../../core/server');
const GhostServer = require('../../core/server/ghost-server');
const {events} = require('../../core/server/lib/common');
const db = require('../../core/server/data/db');
const models = require('../../core/server/models');
const urlUtils = require('../../core/shared/url-utils');
const urlService = require('../../core/frontend/services/url');
const settingsService = require('../../core/server/services/settings');
const frontendSettingsService = require('../../core/frontend/services/settings');
@ -216,21 +213,6 @@ const restartModeGhostStart = async () => {
events.emit('server.start');
};
// Old Boot Method
// const bootGhost = async (options) => {
// // Require Ghost
// ghostServer = await ghost();
// // Mount Ghost & Start Server
// if (options.subdir) {
// let parentApp = express('test parent');
// parentApp.use(urlUtils.getSubdir(), ghostServer.rootApp);
// await ghostServer.start(parentApp);
// } else {
// await ghostServer.start();
// }
// };
const bootGhost = async () => {
ghostServer = await boot();
};

View file

@ -557,13 +557,6 @@
jsonwebtoken "^8.5.1"
lodash "^4.17.15"
"@tryghost/maintenance@0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@tryghost/maintenance/-/maintenance-0.1.0.tgz#cb2c4dff2c1292ca7a07b88f3a658832e33b3259"
integrity sha512-f91Wngx4UbzGuSlCN6TI9EAvS1nofIYY653+3OO3fx/2A9ehbzMRWraUH3GY05xKRc8CnW+msGkRrPgiMIa/Kw==
dependencies:
ghost-ignition "^4.4.3"
"@tryghost/members-api@1.0.0-rc.3":
version "1.0.0-rc.3"
resolved "https://registry.yarnpkg.com/@tryghost/members-api/-/members-api-1.0.0-rc.3.tgz#24dd56700f3da322a6a299a97b8632a1cae7db65"
@ -4141,7 +4134,7 @@ ghost-ignition@4.2.4:
prettyjson "1.2.1"
uuid "8.3.1"
ghost-ignition@4.4.3, ghost-ignition@^4.4.3:
ghost-ignition@4.4.3:
version "4.4.3"
resolved "https://registry.yarnpkg.com/ghost-ignition/-/ghost-ignition-4.4.3.tgz#c837ab11e1f3a1cfd22cc24df6b506a9afc1bc25"
integrity sha512-eViE/ae+AGV/YmVbTq2W5TBWVu724EUJ0pjtSwa4q6o1+fXxMIqoELJaxMX+Gc9PBK0nI3J+E0JI8GdrEiqndg==