Server: fix migration scripts
authorChocobozzz <florian.bigard@gmail.com>
Sat, 18 Feb 2017 10:56:28 +0000 (11:56 +0100)
committerChocobozzz <florian.bigard@gmail.com>
Sat, 18 Feb 2017 11:13:33 +0000 (12:13 +0100)
server.js
server/initializers/constants.js
server/initializers/migrations/0005-email-pod.js
server/initializers/migrations/0010-email-user.js [new file with mode: 0644]
server/initializers/migrator.js
server/models/user.js

index 4a0de72bbfbc1a09de011b247796f74d886fb165..33d399786da00edd0f787ee8cba3b7819ed09ba9 100644 (file)
--- a/server.js
+++ b/server.js
@@ -20,7 +20,7 @@ const constants = require('./server/initializers/constants')
 const logger = require('./server/helpers/logger')
 // Initialize database and models
 const db = require('./server/initializers/database')
-db.init()
+db.init(onDatabaseInitDone)
 
 // ----------- Checker -----------
 const checker = require('./server/initializers/checker')
@@ -119,25 +119,27 @@ app.use(function (err, req, res, next) {
 
 // ----------- Run -----------
 
-const port = constants.CONFIG.LISTEN.PORT
-installer.installApplication(function (err) {
-  if (err) throw err
-
-  // Run the migration scripts if needed
+function onDatabaseInitDone () {
+  const port = constants.CONFIG.LISTEN.PORT
+    // Run the migration scripts if needed
   migrator.migrate(function (err) {
     if (err) throw err
 
-    // ----------- Make the server listening -----------
-    server.listen(port, function () {
-      // Activate the communication with friends
-      friends.activate()
+    installer.installApplication(function (err) {
+      if (err) throw err
+
+      // ----------- Make the server listening -----------
+      server.listen(port, function () {
+        // Activate the communication with friends
+        friends.activate()
 
-      logger.info('Server listening on port %d', port)
-      logger.info('Webserver: %s', constants.CONFIG.WEBSERVER.URL)
+        logger.info('Server listening on port %d', port)
+        logger.info('Webserver: %s', constants.CONFIG.WEBSERVER.URL)
 
-      app.emit('ready')
+        app.emit('ready')
+      })
     })
   })
-})
+}
 
 module.exports = app
index eb0509efe8eba617068e5e43635525a747ab7fb8..8215808931aa19fba67bf14e6b41b903145e464d 100644 (file)
@@ -5,6 +5,10 @@ const path = require('path')
 
 // ---------------------------------------------------------------------------
 
+const LAST_MIGRATION_VERSION = 10
+
+// ---------------------------------------------------------------------------
+
 // API version
 const API_VERSION = 'v1'
 
@@ -95,10 +99,6 @@ const FRIEND_SCORE = {
 
 // ---------------------------------------------------------------------------
 
-const LAST_MIGRATION_VERSION = 5
-
-// ---------------------------------------------------------------------------
-
 // Number of points we add/remove from a friend after a successful/bad request
 const PODS_SCORE = {
   MALUS: -10,
index d90b674a135a38997e63a0b07b9ab8711b63fa08..9bbb354bf1c7105dd6540463fa249fb821688e31 100644 (file)
@@ -1,18 +1,39 @@
-/*
-  This is just an example.
-*/
+'use strict'
 
-// utils = { transaction, queryInterface }
-exports.up = function (utils, callback) {
+const waterfall = require('async/waterfall')
+
+// utils = { transaction, queryInterface, sequelize, Sequelize }
+exports.up = function (utils, finalCallback) {
   const q = utils.queryInterface
   const Sequelize = utils.Sequelize
 
   const data = {
     type: Sequelize.STRING(400),
-    allowNull: false
+    allowNull: false,
+    defaultValue: ''
   }
 
-  q.addColumn('Pods', 'email', data, { transaction: utils.transaction }).asCallback(callback)
+  waterfall([
+
+    function addEmailColumn (callback) {
+      q.addColumn('Pods', 'email', data, { transaction: utils.transaction }).asCallback(function (err) {
+        return callback(err)
+      })
+    },
+
+    function updateWithFakeEmails (callback) {
+      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) {
+      data.defaultValue = null
+
+      q.changeColumn('Pods', 'email', data, { transaction: utils.transaction }).asCallback(callback)
+    }
+  ], finalCallback)
 }
 
 exports.down = function (options, callback) {
diff --git a/server/initializers/migrations/0010-email-user.js b/server/initializers/migrations/0010-email-user.js
new file mode 100644 (file)
index 0000000..1ab2713
--- /dev/null
@@ -0,0 +1,41 @@
+'use strict'
+
+const waterfall = require('async/waterfall')
+
+// utils = { transaction, queryInterface, sequelize, Sequelize }
+exports.up = function (utils, finalCallback) {
+  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) {
+      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) {
+      data.defaultValue = null
+
+      q.changeColumn('Users', 'email', data, { transaction: utils.transaction }).asCallback(callback)
+    }
+  ], finalCallback)
+}
+
+exports.down = function (options, callback) {
+  throw new Error('Not implemented.')
+}
index 233ee2bddf294e2be4a21c86125a31db13db44cf..8c67903add5cdc8d5fc10c03478827e37d84de0c 100644 (file)
@@ -1,5 +1,6 @@
 'use strict'
 
+const waterfall = require('async/waterfall')
 const eachSeries = require('async/eachSeries')
 const fs = require('fs')
 const path = require('path')
@@ -12,30 +13,52 @@ const migrator = {
   migrate: migrate
 }
 
-function migrate (callback) {
-  db.Application.loadMigrationVersion(function (err, actualVersion) {
-    if (err) return callback(err)
+function migrate (finalCallback) {
+  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)
+    },
 
-    // If there are a new migration scripts
-    if (actualVersion < constants.LAST_MIGRATION_VERSION) {
+    function abortMigrationIfNotNeeded (actualVersion, callback) {
+      // No need migrations
+      if (actualVersion >= constants.LAST_MIGRATION_VERSION) return finalCallback(null)
+
+      return callback(null, actualVersion)
+    },
+
+    function getMigrations (actualVersion, callback) {
+      // If there are a new migration scripts
       logger.info('Begin migrations.')
 
       getMigrationScripts(function (err, migrationScripts) {
-        if (err) return callback(err)
+        return callback(err, actualVersion, migrationScripts)
+      })
+    },
 
-        eachSeries(migrationScripts, function (entity, callbackEach) {
-          executeMigration(actualVersion, entity, callbackEach)
-        }, function (err) {
-          if (err) return callback(err)
+    function doMigrations (actualVersion, migrationScripts, callback) {
+      eachSeries(migrationScripts, function (entity, callbackEach) {
+        executeMigration(actualVersion, entity, callbackEach)
+      }, function (err) {
+        if (err) return callback(err)
 
-          logger.info('Migrations finished. New migration version schema: %s', constants.LAST_MIGRATION_VERSION)
-          return callback(null)
-        })
+        logger.info('Migrations finished. New migration version schema: %s', constants.LAST_MIGRATION_VERSION)
+        return callback(null)
       })
-    } else {
-      return callback(null)
     }
-  })
+  ], finalCallback)
 }
 
 // ---------------------------------------------------------------------------
@@ -81,6 +104,7 @@ function executeMigration (actualVersion, entity, callback) {
     const options = {
       transaction: t,
       queryInterface: db.sequelize.getQueryInterface(),
+      sequelize: db.sequelize,
       Sequelize: db.Sequelize
     }
     migrationScript.up(options, function (err) {
index 35a98dd6b430cc725d4bb64bebd155f2fa522ecc..24e710fa71c6ff1d36dac846dacb83c91ba3d092 100644 (file)
@@ -33,7 +33,7 @@ module.exports = function (sequelize, DataTypes) {
         }
       },
       email: {
-        type: DataTypes.STRING,
+        type: DataTypes.STRING(400),
         allowNull: false,
         validate: {
           isEmail: true