From b00d9fee6d7f0214718bd954889f27763716dc80 Mon Sep 17 00:00:00 2001 From: Hannah Wolfe Date: Fri, 17 Feb 2017 16:44:34 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20=E2=8F=B1=20Cleanup=20/=20optimi?= =?UTF-8?q?se=20the=20server.init()=20function=20(#7985)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit refs #2182 * 🔥 Remove unused options from server init - this is left over from old code and is now unused * 🎨 Move knex-migrator check to db health - Move complex check function into own module - Call module from server/index.js - This just improves the readability of server/index.js * 🔥 Remove old comments - These comments all make no sense now! * 🎨 ⏱ Move model init out of promise chain - Model.init() does not return a promise - Therefore, we can move it to the top of the init function, outside of the promise change - This should be a minor optimisation, and again improves readability /clarity of what's happening * ✨ ⁉️ Move DBHash init / first run to Settings model - this structure is left over from when we had code we executed on the first run of Ghost - the implementation used the API to initialise one setting before populateDefaults is called - this had lots of dependencies - the whole model, API, and permissions structure had to be initialised for it to work - the new implementation is simpler, it captures the dbHash getting initialised during populateDefaults() - it also adds an event, so we can do first-run code later if we really want to (or maybe apps can?!) - perhaps this is hiding behaviour, and there's a nicer way to do it, but populateDefaults seems like a sane place to populate a default setting 😁 * ⏱ Optimise require order so config is first - the first require to config will cause the files to be read etc - this ensures that it happens early, and isn't confusingly timed as part of loading a different module * 🎨 Simplify settings model changes --- core/server/data/db/health.js | 40 ++++++++++++++++ core/server/index.js | 85 ++++------------------------------ core/server/models/settings.js | 20 +++++--- 3 files changed, 64 insertions(+), 81 deletions(-) create mode 100644 core/server/data/db/health.js diff --git a/core/server/data/db/health.js b/core/server/data/db/health.js new file mode 100644 index 0000000000..951a3d7519 --- /dev/null +++ b/core/server/data/db/health.js @@ -0,0 +1,40 @@ +var KnexMigrator = require('knex-migrator'), + config = require('../../config'), + errors = require('../../errors'), + models = require('../../models'); + +module.exports.check = function healthCheck() { + var knexMigrator = new KnexMigrator({ + knexMigratorFilePath: config.get('paths:appRoot') + }); + + return knexMigrator.isDatabaseOK() + .catch(function (outerErr) { + if (outerErr.code === 'DB_NOT_INITIALISED') { + throw outerErr; + } + + // CASE: migration table does not exist, figure out if database is compatible + return models.Settings.findOne({key: 'databaseVersion', context: {internal: true}}) + .then(function (response) { + // CASE: no db version key, database is compatible + if (!response) { + throw outerErr; + } + + throw new errors.DatabaseVersionError({ + message: 'Your database version is not compatible with Ghost 1.0.0 Alpha (master branch)', + context: 'Want to keep your DB? Use Ghost < 1.0.0 or the "stable" branch. Otherwise please delete your DB and restart Ghost.', + help: 'More information on the Ghost 1.0.0 Alpha at https://support.ghost.org/v1-0-alpha' + }); + }) + .catch(function (err) { + // CASE: settings table does not exist + if (err.errno === 1 || err.errno === 1146) { + throw outerErr; + } + + throw err; + }); + }); +}; diff --git a/core/server/index.js b/core/server/index.js index 18d4ffb757..aa17f91a93 100644 --- a/core/server/index.js +++ b/core/server/index.js @@ -14,122 +14,57 @@ require('./overrides'); // Module dependencies var debug = require('debug')('ghost:boot:init'), - uuid = require('uuid'), - Promise = require('bluebird'), - KnexMigrator = require('knex-migrator'), +// Config should be first require, as it triggers the initial load of the config files config = require('./config'), + Promise = require('bluebird'), logging = require('./logging'), - errors = require('./errors'), i18n = require('./i18n'), api = require('./api'), models = require('./models'), permissions = require('./permissions'), apps = require('./apps'), auth = require('./auth'), + dbHealth = require('./data/db/health'), xmlrpc = require('./data/xml/xmlrpc'), slack = require('./data/slack'), GhostServer = require('./ghost-server'), scheduling = require('./scheduling'), readDirectory = require('./utils/read-directory'), - utils = require('./utils'), - knexMigrator = new KnexMigrator({ - knexMigratorFilePath: config.get('paths:appRoot') - }), - dbHash; - -function initDbHashAndFirstRun() { - return api.settings.read({key: 'dbHash', context: {internal: true}}).then(function (response) { - var hash = response.settings[0].value, - initHash; - - dbHash = hash; - - if (dbHash === null) { - initHash = uuid.v4(); - return api.settings.edit({settings: [{key: 'dbHash', value: initHash}]}, {context: {internal: true}}) - .then(function (response) { - dbHash = response.settings[0].value; - return dbHash; - // Use `then` here to do 'first run' actions - }); - } - - return dbHash; - }); -} + utils = require('./utils'); // ## Initialise Ghost -// Sets up the express server instances, runs init on a bunch of stuff, configures views, helpers, routes and more -// Finally it returns an instance of GhostServer -function init(options) { +function init() { debug('Init Start...'); - options = options || {}; var ghostServer, parentApp; - // ### Initialisation - // The server and its dependencies require a populated config - // It returns a promise that is resolved when the application - // has finished starting up. - // Initialize Internationalization i18n.init(); debug('I18n done'); + models.init(); + debug('models done'); return readDirectory(config.getContentPath('apps')).then(function loadThemes(result) { config.set('paths:availableApps', result); return api.themes.loadThemes(); }).then(function () { debug('Themes & apps done'); - - models.init(); - }).then(function () { - return knexMigrator.isDatabaseOK() - .catch(function (outerErr) { - if (outerErr.code === 'DB_NOT_INITIALISED') { - throw outerErr; - } - - // CASE: migration table does not exist, figure out if database is compatible - return models.Settings.findOne({key: 'databaseVersion', context: {internal: true}}) - .then(function (response) { - // CASE: no db version key, database is compatible - if (!response) { - throw outerErr; - } - - throw new errors.DatabaseVersionError({ - message: 'Your database version is not compatible with Ghost 1.0.0 Alpha (master branch)', - context: 'Want to keep your DB? Use Ghost < 1.0.0 or the "stable" branch. Otherwise please delete your DB and restart Ghost.', - help: 'More information on the Ghost 1.0.0 Alpha at https://support.ghost.org/v1-0-alpha' - }); - }) - .catch(function (err) { - // CASE: settings table does not exist - if (err.errno === 1 || err.errno === 1146) { - throw outerErr; - } - - throw err; - }); - }); + return dbHealth.check(); }).then(function () { + debug('DB health check done'); // Populate any missing default settings return models.Settings.populateDefaults(); }).then(function () { debug('Models & database done'); - + // Refresh the API settings cache return api.settings.updateSettingsCache(); }).then(function () { debug('Update settings cache done'); // Initialize the permissions actions and objects - // NOTE: Must be done before initDbHashAndFirstRun calls return permissions.init(); }).then(function () { debug('Permissions done'); return Promise.join( - // Check for or initialise a dbHash. - initDbHashAndFirstRun(), // Initialize apps apps.init(), // Initialize xmrpc ping diff --git a/core/server/models/settings.js b/core/server/models/settings.js index c53d8d41fc..d84dd2ed74 100644 --- a/core/server/models/settings.js +++ b/core/server/models/settings.js @@ -1,12 +1,14 @@ var Settings, - ghostBookshelf = require('./base'), - _ = require('lodash'), - errors = require('../errors'), Promise = require('bluebird'), - validation = require('../data/validation'), + _ = require('lodash'), + uuid = require('uuid'), + ghostBookshelf = require('./base'), + errors = require('../errors'), events = require('../events'), - internalContext = {context: {internal: true}}, i18n = require('../i18n'), + validation = require('../data/validation'), + + internalContext = {context: {internal: true}}, defaultSettings; @@ -15,12 +17,18 @@ var Settings, // instead of iterating those categories every time function parseDefaultSettings() { var defaultSettingsInCategories = require('../data/schema/').defaultSettings, - defaultSettingsFlattened = {}; + defaultSettingsFlattened = {}, + dynamicDefault = { + dbHash: uuid.v4() + }; _.each(defaultSettingsInCategories, function each(settings, categoryName) { _.each(settings, function each(setting, settingName) { setting.type = categoryName; setting.key = settingName; + if (dynamicDefault[setting.key]) { + setting.defaultValue = dynamicDefault[setting.key]; + } defaultSettingsFlattened[settingName] = setting; });