From 6fcd19ba737f1f5614a56c6925adb882dea43b8d Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 5 Jul 2017 13:26:25 +0200 Subject: Move to promises Closes https://github.com/Chocobozzz/PeerTube/issues/74 --- server/initializers/checker.ts | 52 ++++---- server/initializers/database.ts | 99 ++++++++------- server/initializers/installer.ts | 75 ++++-------- server/initializers/migrations/0005-email-pod.ts | 38 +++--- server/initializers/migrations/0010-email-user.ts | 39 +++--- server/initializers/migrations/0015-video-views.ts | 13 +- server/initializers/migrations/0020-video-likes.ts | 13 +- .../initializers/migrations/0025-video-dislikes.ts | 13 +- .../initializers/migrations/0030-video-category.ts | 29 ++--- .../initializers/migrations/0035-video-licence.ts | 30 ++--- server/initializers/migrations/0040-video-nsfw.ts | 29 ++--- .../migrations/0045-user-display-nsfw.ts | 13 +- .../initializers/migrations/0050-video-language.ts | 13 +- server/initializers/migrator.ts | 133 ++++++++------------- 14 files changed, 262 insertions(+), 327 deletions(-) (limited to 'server/initializers') diff --git a/server/initializers/checker.ts b/server/initializers/checker.ts index 7007f2c0b..fb69e05fc 100644 --- a/server/initializers/checker.ts +++ b/server/initializers/checker.ts @@ -2,6 +2,7 @@ import * as config from 'config' import { database as db } from './database' import { CONFIG } from './constants' +import { promisify0 } from '../helpers/core-utils' // Some checks on configuration files function checkConfig () { @@ -35,41 +36,36 @@ function checkMissedConfig () { } // Check the available codecs -function checkFFmpeg (callback: (err: Error) => void) { +function checkFFmpeg () { const Ffmpeg = require('fluent-ffmpeg') - - Ffmpeg.getAvailableCodecs(function (err, codecs) { - if (err) return callback(err) - if (CONFIG.TRANSCODING.ENABLED === false) return callback(null) - - const canEncode = [ 'libx264' ] - canEncode.forEach(function (codec) { - if (codecs[codec] === undefined) { - return callback(new Error('Unknown codec ' + codec + ' in FFmpeg.')) - } - - if (codecs[codec].canEncode !== true) { - return callback(new Error('Unavailable encode codec ' + codec + ' in FFmpeg')) - } + const getAvailableCodecsPromise = promisify0(Ffmpeg.getAvailableCodecs) + + getAvailableCodecsPromise() + .then(codecs => { + if (CONFIG.TRANSCODING.ENABLED === false) return undefined + + const canEncode = [ 'libx264' ] + canEncode.forEach(function (codec) { + if (codecs[codec] === undefined) { + throw new Error('Unknown codec ' + codec + ' in FFmpeg.') + } + + if (codecs[codec].canEncode !== true) { + throw new Error('Unavailable encode codec ' + codec + ' in FFmpeg') + } + }) }) - - return callback(null) - }) } -function clientsExist (callback: (err: Error, clientsExist?: boolean) => void) { - db.OAuthClient.countTotal(function (err, totalClients) { - if (err) return callback(err) - - return callback(null, totalClients !== 0) +function clientsExist () { + return db.OAuthClient.countTotal().then(totalClients => { + return totalClients !== 0 }) } -function usersExist (callback: (err: Error, usersExist?: boolean) => void) { - db.User.countTotal(function (err, totalUsers) { - if (err) return callback(err) - - return callback(null, totalUsers !== 0) +function usersExist () { + return db.User.countTotal().then(totalUsers => { + return totalUsers !== 0 }) } diff --git a/server/initializers/database.ts b/server/initializers/database.ts index 705dec6da..6e3a8d009 100644 --- a/server/initializers/database.ts +++ b/server/initializers/database.ts @@ -1,12 +1,12 @@ -import * as fs from 'fs' import { join } from 'path' +import { flattenDepth } from 'lodash' import * as Sequelize from 'sequelize' -import { each } from 'async' +import * as Promise from 'bluebird' import { CONFIG } from './constants' // Do not use barrel, we need to load database first import { logger } from '../helpers/logger' -import { isTestInstance } from '../helpers/core-utils' +import { isTestInstance, readdirPromise } from '../helpers/core-utils' import { ApplicationModel, AuthorModel, @@ -33,7 +33,7 @@ const password = CONFIG.DATABASE.PASSWORD const database: { sequelize?: Sequelize.Sequelize, - init?: (silent: any, callback: any) => void, + init?: (silent: boolean) => Promise, Application?: ApplicationModel, Author?: AuthorModel, @@ -72,19 +72,17 @@ const sequelize = new Sequelize(dbname, username, password, { database.sequelize = sequelize -database.init = function (silent: boolean, callback: (err: Error) => void) { +database.init = function (silent: boolean) { const modelDirectory = join(__dirname, '..', 'models') - getModelFiles(modelDirectory, function (err, filePaths) { - if (err) throw err - - filePaths.forEach(function (filePath) { + return getModelFiles(modelDirectory).then(filePaths => { + filePaths.forEach(filePath => { const model = sequelize.import(filePath) database[model['name']] = model }) - Object.keys(database).forEach(function (modelName) { + Object.keys(database).forEach(modelName => { if ('associate' in database[modelName]) { database[modelName].associate(database) } @@ -92,7 +90,7 @@ database.init = function (silent: boolean, callback: (err: Error) => void) { if (!silent) logger.info('Database %s is ready.', dbname) - return callback(null) + return undefined }) } @@ -104,49 +102,50 @@ export { // --------------------------------------------------------------------------- -function getModelFiles (modelDirectory: string, callback: (err: Error, filePaths: string[]) => void) { - fs.readdir(modelDirectory, function (err, files) { - if (err) throw err - - const directories = files.filter(function (directory) { - // Find directories - if ( - directory.endsWith('.js.map') || - directory === 'index.js' || directory === 'index.ts' || - directory === 'utils.js' || directory === 'utils.ts' - ) return false +function getModelFiles (modelDirectory: string) { + return readdirPromise(modelDirectory) + .then(files => { + const directories: string[] = files.filter(function (directory) { + // Find directories + if ( + directory.endsWith('.js.map') || + directory === 'index.js' || directory === 'index.ts' || + directory === 'utils.js' || directory === 'utils.ts' + ) return false + + return true + }) - return true + return directories }) - - let modelFilePaths: string[] = [] - - // For each directory we read it and append model in the modelFilePaths array - each(directories, function (directory: string, eachCallback: ErrorCallback) { - const modelDirectoryPath = join(modelDirectory, directory) - - fs.readdir(modelDirectoryPath, function (err, files) { - if (err) return eachCallback(err) - - const filteredFiles = files.filter(file => { - if ( - file === 'index.js' || file === 'index.ts' || - file === 'utils.js' || file === 'utils.ts' || - file.endsWith('-interface.js') || file.endsWith('-interface.ts') || - file.endsWith('.js.map') - ) return false - - return true - }).map(file => { - return join(modelDirectoryPath, file) + .then(directories => { + const tasks = [] + + // For each directory we read it and append model in the modelFilePaths array + directories.forEach(directory => { + const modelDirectoryPath = join(modelDirectory, directory) + + const promise = readdirPromise(modelDirectoryPath).then(files => { + const filteredFiles = files.filter(file => { + if ( + file === 'index.js' || file === 'index.ts' || + file === 'utils.js' || file === 'utils.ts' || + file.endsWith('-interface.js') || file.endsWith('-interface.ts') || + file.endsWith('.js.map') + ) return false + + return true + }).map(file => join(modelDirectoryPath, file)) + + return filteredFiles }) - modelFilePaths = modelFilePaths.concat(filteredFiles) - - return eachCallback(null) + tasks.push(promise) }) - }, function (err: Error) { - return callback(err, modelFilePaths) + + return Promise.all(tasks) + }) + .then((filteredFiles: string[][]) => { + return flattenDepth(filteredFiles, 1) }) - }) } diff --git a/server/initializers/installer.ts b/server/initializers/installer.ts index f105c8292..1ec24c4ad 100644 --- a/server/initializers/installer.ts +++ b/server/initializers/installer.ts @@ -1,37 +1,19 @@ import { join } from 'path' import * as config from 'config' -import { each, series } from 'async' -import * as mkdirp from 'mkdirp' import * as passwordGenerator from 'password-generator' +import * as Promise from 'bluebird' import { database as db } from './database' import { USER_ROLES, CONFIG, LAST_MIGRATION_VERSION } from './constants' import { clientsExist, usersExist } from './checker' -import { logger, createCertsIfNotExist, root } from '../helpers' - -function installApplication (callback: (err: Error) => void) { - series([ - function createDatabase (callbackAsync) { - db.sequelize.sync().asCallback(callbackAsync) - // db.sequelize.sync({ force: true }).asCallback(callbackAsync) - }, - - function createDirectories (callbackAsync) { - createDirectoriesIfNotExist(callbackAsync) - }, - - function createCertificates (callbackAsync) { - createCertsIfNotExist(callbackAsync) - }, - - function createOAuthClient (callbackAsync) { - createOAuthClientIfNotExist(callbackAsync) - }, - - function createOAuthUser (callbackAsync) { - createOAuthAdminIfNotExist(callbackAsync) - } - ], callback) +import { logger, createCertsIfNotExist, root, mkdirpPromise } from '../helpers' + +function installApplication () { + return db.sequelize.sync() + .then(() => createDirectoriesIfNotExist()) + .then(() => createCertsIfNotExist()) + .then(() => createOAuthClientIfNotExist()) + .then(() => createOAuthAdminIfNotExist()) } // --------------------------------------------------------------------------- @@ -42,21 +24,22 @@ export { // --------------------------------------------------------------------------- -function createDirectoriesIfNotExist (callback: (err: Error) => void) { +function createDirectoriesIfNotExist () { const storages = config.get('storage') - each(Object.keys(storages), function (key, callbackEach) { + const tasks = [] + Object.keys(storages).forEach(key => { const dir = storages[key] - mkdirp(join(root(), dir), callbackEach) - }, callback) -} + tasks.push(mkdirpPromise(join(root(), dir))) + }) -function createOAuthClientIfNotExist (callback: (err: Error) => void) { - clientsExist(function (err, exist) { - if (err) return callback(err) + return Promise.all(tasks) +} +function createOAuthClientIfNotExist () { + return clientsExist().then(exist => { // Nothing to do, clients already exist - if (exist === true) return callback(null) + if (exist === true) return undefined logger.info('Creating a default OAuth Client.') @@ -69,23 +52,19 @@ function createOAuthClientIfNotExist (callback: (err: Error) => void) { redirectUris: null }) - client.save().asCallback(function (err, createdClient) { - if (err) return callback(err) - + return client.save().then(createdClient => { logger.info('Client id: ' + createdClient.clientId) logger.info('Client secret: ' + createdClient.clientSecret) - return callback(null) + return undefined }) }) } -function createOAuthAdminIfNotExist (callback: (err: Error) => void) { - usersExist(function (err, exist) { - if (err) return callback(err) - +function createOAuthAdminIfNotExist () { + return usersExist().then(exist => { // Nothing to do, users already exist - if (exist === true) return callback(null) + if (exist === true) return undefined logger.info('Creating the administrator.') @@ -116,14 +95,12 @@ function createOAuthAdminIfNotExist (callback: (err: Error) => void) { role } - db.User.create(userData, createOptions).asCallback(function (err, createdUser) { - if (err) return callback(err) - + return db.User.create(userData, createOptions).then(createdUser => { logger.info('Username: ' + username) logger.info('User password: ' + password) logger.info('Creating Application table.') - db.Application.create({ migrationVersion: LAST_MIGRATION_VERSION }).asCallback(callback) + return db.Application.create({ migrationVersion: LAST_MIGRATION_VERSION }) }) }) } diff --git a/server/initializers/migrations/0005-email-pod.ts b/server/initializers/migrations/0005-email-pod.ts index a9200c47f..ceefaad4a 100644 --- a/server/initializers/migrations/0005-email-pod.ts +++ b/server/initializers/migrations/0005-email-pod.ts @@ -1,9 +1,12 @@ -import { waterfall } from 'async' - -// utils = { transaction, queryInterface, sequelize, Sequelize } -function up (utils, finalCallback) { +import * as Sequelize from 'sequelize' +import * as Promise from 'bluebird' + +function up (utils: { + transaction: Sequelize.Transaction, + queryInterface: Sequelize.QueryInterface, + sequelize: Sequelize.Sequelize +}): Promise { const q = utils.queryInterface - const Sequelize = utils.Sequelize const data = { type: Sequelize.STRING(400), @@ -11,27 +14,16 @@ function up (utils, finalCallback) { defaultValue: '' } - waterfall([ - - function addEmailColumn (callback) { - q.addColumn('Pods', 'email', data, { transaction: utils.transaction }).asCallback(function (err) { - return callback(err) - }) - }, - - function updateWithFakeEmails (callback) { + return q.addColumn('Pods', 'email', data) + .then(() => { const query = 'UPDATE "Pods" SET "email" = \'dummy@example.com\'' - utils.sequelize.query(query, { transaction: utils.transaction }).asCallback(function (err) { - return callback(err) - }) - }, - - function nullOnDefault (callback) { + return utils.sequelize.query(query, { transaction: utils.transaction }) + }) + .then(() => { data.defaultValue = null - q.changeColumn('Pods', 'email', data, { transaction: utils.transaction }).asCallback(callback) - } - ], finalCallback) + return q.changeColumn('Pods', 'email', data) + }) } function down (options, callback) { diff --git a/server/initializers/migrations/0010-email-user.ts b/server/initializers/migrations/0010-email-user.ts index 4b5d29394..e8865acdb 100644 --- a/server/initializers/migrations/0010-email-user.ts +++ b/server/initializers/migrations/0010-email-user.ts @@ -1,37 +1,28 @@ -import { waterfall } from 'async' - -// utils = { transaction, queryInterface, sequelize, Sequelize } -function up (utils, finalCallback) { +import * as Sequelize from 'sequelize' +import * as Promise from 'bluebird' + +function up (utils: { + transaction: Sequelize.Transaction, + queryInterface: Sequelize.QueryInterface, + sequelize: Sequelize.Sequelize +}): Promise { const q = utils.queryInterface - const Sequelize = utils.Sequelize const data = { type: Sequelize.STRING(400), allowNull: false, defaultValue: '' } - - waterfall([ - - function addEmailColumn (callback) { - q.addColumn('Users', 'email', data, { transaction: utils.transaction }).asCallback(function (err) { - return callback(err) - }) - }, - - function updateWithFakeEmails (callback) { + return q.addColumn('Users', 'email', data) + .then(() => { const query = 'UPDATE "Users" SET "email" = CONCAT("username", \'@example.com\')' - utils.sequelize.query(query, { transaction: utils.transaction }).asCallback(function (err) { - return callback(err) - }) - }, - - function nullOnDefault (callback) { + return utils.sequelize.query(query, { transaction: utils.transaction }) + }) + .then(() => { data.defaultValue = null - q.changeColumn('Users', 'email', data, { transaction: utils.transaction }).asCallback(callback) - } - ], finalCallback) + return q.changeColumn('Users', 'email', data) + }) } function down (options, callback) { diff --git a/server/initializers/migrations/0015-video-views.ts b/server/initializers/migrations/0015-video-views.ts index e70869404..df274d817 100644 --- a/server/initializers/migrations/0015-video-views.ts +++ b/server/initializers/migrations/0015-video-views.ts @@ -1,7 +1,12 @@ -// utils = { transaction, queryInterface, sequelize, Sequelize } -function up (utils, finalCallback) { +import * as Sequelize from 'sequelize' +import * as Promise from 'bluebird' + +function up (utils: { + transaction: Sequelize.Transaction, + queryInterface: Sequelize.QueryInterface, + sequelize: Sequelize.Sequelize +}): Promise { const q = utils.queryInterface - const Sequelize = utils.Sequelize const data = { type: Sequelize.INTEGER, @@ -9,7 +14,7 @@ function up (utils, finalCallback) { defaultValue: 0 } - q.addColumn('Videos', 'views', data, { transaction: utils.transaction }).asCallback(finalCallback) + return q.addColumn('Videos', 'views', data) } function down (options, callback) { diff --git a/server/initializers/migrations/0020-video-likes.ts b/server/initializers/migrations/0020-video-likes.ts index e435d0657..3d7182d0a 100644 --- a/server/initializers/migrations/0020-video-likes.ts +++ b/server/initializers/migrations/0020-video-likes.ts @@ -1,7 +1,12 @@ -// utils = { transaction, queryInterface, sequelize, Sequelize } -function up (utils, finalCallback) { +import * as Sequelize from 'sequelize' +import * as Promise from 'bluebird' + +function up (utils: { + transaction: Sequelize.Transaction, + queryInterface: Sequelize.QueryInterface, + sequelize: Sequelize.Sequelize +}): Promise { const q = utils.queryInterface - const Sequelize = utils.Sequelize const data = { type: Sequelize.INTEGER, @@ -9,7 +14,7 @@ function up (utils, finalCallback) { defaultValue: 0 } - q.addColumn('Videos', 'likes', data, { transaction: utils.transaction }).asCallback(finalCallback) + return q.addColumn('Videos', 'likes', data) } function down (options, callback) { diff --git a/server/initializers/migrations/0025-video-dislikes.ts b/server/initializers/migrations/0025-video-dislikes.ts index 57e54e904..ed41095dc 100644 --- a/server/initializers/migrations/0025-video-dislikes.ts +++ b/server/initializers/migrations/0025-video-dislikes.ts @@ -1,7 +1,12 @@ -// utils = { transaction, queryInterface, sequelize, Sequelize } -function up (utils, finalCallback) { +import * as Sequelize from 'sequelize' +import * as Promise from 'bluebird' + +function up (utils: { + transaction: Sequelize.Transaction, + queryInterface: Sequelize.QueryInterface, + sequelize: Sequelize.Sequelize +}): Promise { const q = utils.queryInterface - const Sequelize = utils.Sequelize const data = { type: Sequelize.INTEGER, @@ -9,7 +14,7 @@ function up (utils, finalCallback) { defaultValue: 0 } - q.addColumn('Videos', 'dislikes', data, { transaction: utils.transaction }).asCallback(finalCallback) + return q.addColumn('Videos', 'dislikes', data) } function down (options, callback) { diff --git a/server/initializers/migrations/0030-video-category.ts b/server/initializers/migrations/0030-video-category.ts index 1073f449c..f5adee8f9 100644 --- a/server/initializers/migrations/0030-video-category.ts +++ b/server/initializers/migrations/0030-video-category.ts @@ -1,9 +1,12 @@ -import { waterfall } from 'async' - -// utils = { transaction, queryInterface, sequelize, Sequelize } -function up (utils, finalCallback) { +import * as Sequelize from 'sequelize' +import * as Promise from 'bluebird' + +function up (utils: { + transaction: Sequelize.Transaction, + queryInterface: Sequelize.QueryInterface, + sequelize: Sequelize.Sequelize +}): Promise { const q = utils.queryInterface - const Sequelize = utils.Sequelize const data = { type: Sequelize.INTEGER, @@ -11,20 +14,12 @@ function up (utils, finalCallback) { defaultValue: 0 } - waterfall([ - - function addCategoryColumn (callback) { - q.addColumn('Videos', 'category', data, { transaction: utils.transaction }).asCallback(function (err) { - return callback(err) - }) - }, - - function nullOnDefault (callback) { + return q.addColumn('Videos', 'category', data) + .then(() => { data.defaultValue = null - q.changeColumn('Videos', 'category', data, { transaction: utils.transaction }).asCallback(callback) - } - ], finalCallback) + return q.changeColumn('Videos', 'category', data) + }) } function down (options, callback) { diff --git a/server/initializers/migrations/0035-video-licence.ts b/server/initializers/migrations/0035-video-licence.ts index 9316b3c37..00c64d8e7 100644 --- a/server/initializers/migrations/0035-video-licence.ts +++ b/server/initializers/migrations/0035-video-licence.ts @@ -1,9 +1,12 @@ -import { waterfall } from 'async' - -// utils = { transaction, queryInterface, sequelize, Sequelize } -function up (utils, finalCallback) { +import * as Sequelize from 'sequelize' +import * as Promise from 'bluebird' + +function up (utils: { + transaction: Sequelize.Transaction, + queryInterface: Sequelize.QueryInterface, + sequelize: Sequelize.Sequelize +}): Promise { const q = utils.queryInterface - const Sequelize = utils.Sequelize const data = { type: Sequelize.INTEGER, @@ -11,20 +14,11 @@ function up (utils, finalCallback) { defaultValue: 0 } - waterfall([ - - function addLicenceColumn (callback) { - q.addColumn('Videos', 'licence', data, { transaction: utils.transaction }).asCallback(function (err) { - return callback(err) - }) - }, - - function nullOnDefault (callback) { + return q.addColumn('Videos', 'licence', data) + .then(() => { data.defaultValue = null - - q.changeColumn('Videos', 'licence', data, { transaction: utils.transaction }).asCallback(callback) - } - ], finalCallback) + return q.changeColumn('Videos', 'licence', data) + }) } function down (options, callback) { diff --git a/server/initializers/migrations/0040-video-nsfw.ts b/server/initializers/migrations/0040-video-nsfw.ts index c61f496f1..046876b61 100644 --- a/server/initializers/migrations/0040-video-nsfw.ts +++ b/server/initializers/migrations/0040-video-nsfw.ts @@ -1,9 +1,12 @@ -import { waterfall } from 'async' - -// utils = { transaction, queryInterface, sequelize, Sequelize } -function up (utils, finalCallback) { +import * as Sequelize from 'sequelize' +import * as Promise from 'bluebird' + +function up (utils: { + transaction: Sequelize.Transaction, + queryInterface: Sequelize.QueryInterface, + sequelize: Sequelize.Sequelize +}): Promise { const q = utils.queryInterface - const Sequelize = utils.Sequelize const data = { type: Sequelize.BOOLEAN, @@ -11,20 +14,12 @@ function up (utils, finalCallback) { defaultValue: false } - waterfall([ - - function addNSFWColumn (callback) { - q.addColumn('Videos', 'nsfw', data, { transaction: utils.transaction }).asCallback(function (err) { - return callback(err) - }) - }, - - function nullOnDefault (callback) { + return q.addColumn('Videos', 'nsfw', data) + .then(() => { data.defaultValue = null - q.changeColumn('Videos', 'nsfw', data, { transaction: utils.transaction }).asCallback(callback) - } - ], finalCallback) + return q.changeColumn('Videos', 'nsfw', data) + }) } function down (options, callback) { diff --git a/server/initializers/migrations/0045-user-display-nsfw.ts b/server/initializers/migrations/0045-user-display-nsfw.ts index 1ca317795..75bd3bbea 100644 --- a/server/initializers/migrations/0045-user-display-nsfw.ts +++ b/server/initializers/migrations/0045-user-display-nsfw.ts @@ -1,7 +1,12 @@ -// utils = { transaction, queryInterface, sequelize, Sequelize } -function up (utils, finalCallback) { +import * as Sequelize from 'sequelize' +import * as Promise from 'bluebird' + +function up (utils: { + transaction: Sequelize.Transaction, + queryInterface: Sequelize.QueryInterface, + sequelize: Sequelize.Sequelize +}): Promise { const q = utils.queryInterface - const Sequelize = utils.Sequelize const data = { type: Sequelize.BOOLEAN, @@ -9,7 +14,7 @@ function up (utils, finalCallback) { defaultValue: false } - q.addColumn('Users', 'displayNSFW', data, { transaction: utils.transaction }).asCallback(finalCallback) + return q.addColumn('Users', 'displayNSFW', data) } function down (options, callback) { diff --git a/server/initializers/migrations/0050-video-language.ts b/server/initializers/migrations/0050-video-language.ts index 95d0a473a..ed08f5866 100644 --- a/server/initializers/migrations/0050-video-language.ts +++ b/server/initializers/migrations/0050-video-language.ts @@ -1,7 +1,12 @@ -// utils = { transaction, queryInterface, sequelize, Sequelize } -function up (utils, finalCallback) { +import * as Sequelize from 'sequelize' +import * as Promise from 'bluebird' + +function up (utils: { + transaction: Sequelize.Transaction, + queryInterface: Sequelize.QueryInterface, + sequelize: Sequelize.Sequelize +}): Promise { const q = utils.queryInterface - const Sequelize = utils.Sequelize const data = { type: Sequelize.INTEGER, @@ -9,7 +14,7 @@ function up (utils, finalCallback) { defaultValue: null } - q.addColumn('Videos', 'language', data, { transaction: utils.transaction }).asCallback(finalCallback) + return q.addColumn('Videos', 'language', data) } function down (options, callback) { diff --git a/server/initializers/migrator.ts b/server/initializers/migrator.ts index d8faaebc6..d381551b5 100644 --- a/server/initializers/migrator.ts +++ b/server/initializers/migrator.ts @@ -1,70 +1,54 @@ -import { waterfall, eachSeries } from 'async' -import * as fs from 'fs' import * as path from 'path' -import * as Sequelize from 'sequelize' +import * as Promise from 'bluebird' import { database as db } from './database' import { LAST_MIGRATION_VERSION } from './constants' -import { logger } from '../helpers' - -function migrate (finalCallback: (err: Error) => void) { - waterfall([ - - function checkApplicationTableExists (callback) { - db.sequelize.getQueryInterface().showAllTables().asCallback(function (err, tables) { - if (err) return callback(err) - - // No tables, we don't need to migrate anything - // The installer will do that - if (tables.length === 0) return finalCallback(null) - - return callback(null) - }) - }, - - function loadMigrationVersion (callback) { - db.Application.loadMigrationVersion(callback) - }, - - function createMigrationRowIfNotExists (actualVersion, callback) { +import { logger, readdirPromise } from '../helpers' + +function migrate () { + const p = db.sequelize.getQueryInterface().showAllTables() + .then(tables => { + // No tables, we don't need to migrate anything + // The installer will do that + if (tables.length === 0) throw null + }) + .then(() => { + return db.Application.loadMigrationVersion() + }) + .then(actualVersion => { if (actualVersion === null) { - db.Application.create({ - migrationVersion: 0 - }, function (err) { - return callback(err, 0) - }) + return db.Application.create({ migrationVersion: 0 }).then(() => 0) } - return callback(null, actualVersion) - }, - - function abortMigrationIfNotNeeded (actualVersion, callback) { - // No need migrations - if (actualVersion >= LAST_MIGRATION_VERSION) return finalCallback(null) - - return callback(null, actualVersion) - }, + return actualVersion + }) + .then(actualVersion => { + // No need migrations, abort + if (actualVersion >= LAST_MIGRATION_VERSION) throw null - function getMigrations (actualVersion, callback) { + return actualVersion + }) + .then(actualVersion => { // If there are a new migration scripts logger.info('Begin migrations.') - getMigrationScripts(function (err, migrationScripts) { - return callback(err, actualVersion, migrationScripts) + return getMigrationScripts().then(migrationScripts => ({ actualVersion, migrationScripts })) + }) + .then(({ actualVersion, migrationScripts }) => { + return Promise.mapSeries(migrationScripts, entity => { + return executeMigration(actualVersion, entity) }) - }, + }) + .then(() => { + logger.info('Migrations finished. New migration version schema: %s', LAST_MIGRATION_VERSION) + }) + .catch(err => { + if (err === null) return undefined - function doMigrations (actualVersion, migrationScripts, callback) { - eachSeries(migrationScripts, function (entity: any, callbackEach) { - executeMigration(actualVersion, entity, callbackEach) - }, function (err) { - if (err) return callback(err) + throw err + }) - logger.info('Migrations finished. New migration version schema: %s', LAST_MIGRATION_VERSION) - return callback(null) - }) - } - ], finalCallback) + return p } // --------------------------------------------------------------------------- @@ -75,12 +59,12 @@ export { // --------------------------------------------------------------------------- -type GetMigrationScriptsCallback = (err: Error, filesToMigrate?: { version: string, script: string }[]) => void -function getMigrationScripts (callback: GetMigrationScriptsCallback) { - fs.readdir(path.join(__dirname, 'migrations'), function (err, files) { - if (err) return callback(err) - - const filesToMigrate = [] +function getMigrationScripts () { + return readdirPromise(path.join(__dirname, 'migrations')).then(files => { + const filesToMigrate: { + version: string, + script: string + }[] = [] files.forEach(function (file) { // Filename is something like 'version-blabla.js' @@ -91,15 +75,15 @@ function getMigrationScripts (callback: GetMigrationScriptsCallback) { }) }) - return callback(err, filesToMigrate) + return filesToMigrate }) } -function executeMigration (actualVersion: number, entity: { version: string, script: string }, callback: (err: Error) => void) { +function executeMigration (actualVersion: number, entity: { version: string, script: string }) { const versionScript = parseInt(entity.version, 10) // Do not execute old migration scripts - if (versionScript <= actualVersion) return callback(null) + if (versionScript <= actualVersion) return undefined // Load the migration module and run it const migrationScriptName = entity.script @@ -107,30 +91,17 @@ function executeMigration (actualVersion: number, entity: { version: string, scr const migrationScript = require(path.join(__dirname, 'migrations', migrationScriptName)) - db.sequelize.transaction().asCallback(function (err, t) { - if (err) return callback(err) - + return db.sequelize.transaction(t => { const options = { transaction: t, queryInterface: db.sequelize.getQueryInterface(), - sequelize: db.sequelize, - Sequelize: Sequelize + sequelize: db.sequelize } - migrationScript.up(options, function (err) { - if (err) { - t.rollback() - return callback(err) - } - - // Update the new migration version - db.Application.updateMigrationVersion(versionScript, t, function (err) { - if (err) { - t.rollback() - return callback(err) - } - t.commit().asCallback(callback) + migrationScript.up(options) + .then(() => { + // Update the new migration version + db.Application.updateMigrationVersion(versionScript, t) }) - }) }) } -- cgit v1.2.3