0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-10 23:36:14 -05:00
ghost/core/server/data/migration/update.js
Katharina Irrgang 6e1bd2838e improvement: migrations (#7000)
closes #6972, #6574

- run each database version as top level transaction
- run migrations in correct order
2016-07-14 11:59:42 +01:00

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;