mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
closes #6972, #6574 - run each database version as top level transaction - run migrations in correct order
103 lines
3.5 KiB
JavaScript
103 lines
3.5 KiB
JavaScript
// # Update Database
|
|
// Handles migrating a database between two different database versions
|
|
var Promise = require('bluebird'),
|
|
backup = require('./backup'),
|
|
fixtures = require('./fixtures'),
|
|
models = require('../../models'),
|
|
db = require('../../data/db'),
|
|
sequence = require('../../utils/sequence'),
|
|
versioning = require('../schema').versioning,
|
|
|
|
updateDatabaseSchema,
|
|
migrateToDatabaseVersion,
|
|
update;
|
|
|
|
/**
|
|
* update database schema for one single version
|
|
*/
|
|
updateDatabaseSchema = function (tasks, logger, modelOptions) {
|
|
if (!tasks.length) {
|
|
return Promise.resolve();
|
|
}
|
|
|
|
return sequence(tasks, modelOptions, logger);
|
|
};
|
|
|
|
/**
|
|
* update each database version as one transaction
|
|
* if a version fails, rollback
|
|
* if a version fails, stop updating more versions
|
|
*/
|
|
migrateToDatabaseVersion = function migrateToDatabaseVersion(version, logger, modelOptions) {
|
|
return new Promise(function (resolve, reject) {
|
|
db.knex.transaction(function (transaction) {
|
|
var migrationTasks = versioning.getUpdateDatabaseTasks(version, logger),
|
|
fixturesTasks = versioning.getUpdateFixturesTasks(version, logger);
|
|
|
|
logger.info('###########');
|
|
logger.info('Updating database to ' + version);
|
|
logger.info('###########\n');
|
|
|
|
modelOptions.transacting = transaction;
|
|
|
|
updateDatabaseSchema(migrationTasks, logger, modelOptions)
|
|
.then(function () {
|
|
return fixtures.update(fixturesTasks, logger, modelOptions);
|
|
})
|
|
.then(function () {
|
|
return versioning.setDatabaseVersion(transaction, version);
|
|
})
|
|
.then(function () {
|
|
return models.Settings.populateDefaults(modelOptions);
|
|
})
|
|
.then(function () {
|
|
transaction.commit();
|
|
resolve();
|
|
})
|
|
.catch(function (err) {
|
|
logger.warn('rolling back because of: ' + err.stack);
|
|
|
|
transaction.rollback();
|
|
});
|
|
}).catch(function () {
|
|
reject();
|
|
});
|
|
});
|
|
};
|
|
|
|
/**
|
|
* ## Update
|
|
* Does a backup, then updates the database and fixtures
|
|
*
|
|
* @param {String} fromVersion
|
|
* @param {String} toVersion
|
|
* @param {{info: logger.info, warn: logger.warn}} logger
|
|
* @returns {Promise<*>}
|
|
*/
|
|
update = function update(fromVersion, toVersion, logger, modelOptions) {
|
|
modelOptions = modelOptions || {};
|
|
// Is the current version lower than the version we can migrate from?
|
|
// E.g. is this blog's DB older than 003?
|
|
if (fromVersion < versioning.canMigrateFromVersion) {
|
|
return versioning.showCannotMigrateError();
|
|
}
|
|
|
|
fromVersion = process.env.FORCE_MIGRATION ? versioning.canMigrateFromVersion : fromVersion;
|
|
|
|
// Figure out which versions we're updating through.
|
|
// This shouldn't include the from/current version (which we're already on)
|
|
var versionsToUpdate = versioning.getMigrationVersions(fromVersion, toVersion).slice(1);
|
|
|
|
return backup(logger)
|
|
.then(function () {
|
|
return Promise.mapSeries(versionsToUpdate, function (versionToUpdate) {
|
|
return migrateToDatabaseVersion(versionToUpdate, logger, modelOptions);
|
|
});
|
|
})
|
|
.catch(function () {
|
|
// we don't want that your blog can't start
|
|
Promise.resolve();
|
|
});
|
|
};
|
|
|
|
module.exports = update;
|