diff options
Diffstat (limited to 'server/initializers/migrator.ts')
-rw-r--r-- | server/initializers/migrator.ts | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/server/initializers/migrator.ts b/server/initializers/migrator.ts new file mode 100644 index 000000000..cfa3220e0 --- /dev/null +++ b/server/initializers/migrator.ts | |||
@@ -0,0 +1,134 @@ | |||
1 | import { waterfall, eachSeries } from 'async' | ||
2 | import fs = require('fs') | ||
3 | import path = require('path') | ||
4 | |||
5 | const db = require('./database') | ||
6 | import { LAST_MIGRATION_VERSION } from './constants' | ||
7 | import { logger } from '../helpers' | ||
8 | |||
9 | function migrate (finalCallback) { | ||
10 | waterfall([ | ||
11 | |||
12 | function checkApplicationTableExists (callback) { | ||
13 | db.sequelize.getQueryInterface().showAllTables().asCallback(function (err, tables) { | ||
14 | if (err) return callback(err) | ||
15 | |||
16 | // No tables, we don't need to migrate anything | ||
17 | // The installer will do that | ||
18 | if (tables.length === 0) return finalCallback(null) | ||
19 | |||
20 | return callback(null) | ||
21 | }) | ||
22 | }, | ||
23 | |||
24 | function loadMigrationVersion (callback) { | ||
25 | db.Application.loadMigrationVersion(callback) | ||
26 | }, | ||
27 | |||
28 | function createMigrationRowIfNotExists (actualVersion, callback) { | ||
29 | if (actualVersion === null) { | ||
30 | db.Application.create({ | ||
31 | migrationVersion: 0 | ||
32 | }, function (err) { | ||
33 | return callback(err, 0) | ||
34 | }) | ||
35 | } | ||
36 | |||
37 | return callback(null, actualVersion) | ||
38 | }, | ||
39 | |||
40 | function abortMigrationIfNotNeeded (actualVersion, callback) { | ||
41 | // No need migrations | ||
42 | if (actualVersion >= LAST_MIGRATION_VERSION) return finalCallback(null) | ||
43 | |||
44 | return callback(null, actualVersion) | ||
45 | }, | ||
46 | |||
47 | function getMigrations (actualVersion, callback) { | ||
48 | // If there are a new migration scripts | ||
49 | logger.info('Begin migrations.') | ||
50 | |||
51 | getMigrationScripts(function (err, migrationScripts) { | ||
52 | return callback(err, actualVersion, migrationScripts) | ||
53 | }) | ||
54 | }, | ||
55 | |||
56 | function doMigrations (actualVersion, migrationScripts, callback) { | ||
57 | eachSeries(migrationScripts, function (entity, callbackEach) { | ||
58 | executeMigration(actualVersion, entity, callbackEach) | ||
59 | }, function (err) { | ||
60 | if (err) return callback(err) | ||
61 | |||
62 | logger.info('Migrations finished. New migration version schema: %s', LAST_MIGRATION_VERSION) | ||
63 | return callback(null) | ||
64 | }) | ||
65 | } | ||
66 | ], finalCallback) | ||
67 | } | ||
68 | |||
69 | // --------------------------------------------------------------------------- | ||
70 | |||
71 | export { | ||
72 | migrate | ||
73 | } | ||
74 | |||
75 | // --------------------------------------------------------------------------- | ||
76 | |||
77 | function getMigrationScripts (callback) { | ||
78 | fs.readdir(path.join(__dirname, 'migrations'), function (err, files) { | ||
79 | if (err) return callback(err) | ||
80 | |||
81 | const filesToMigrate = [] | ||
82 | |||
83 | files.forEach(function (file) { | ||
84 | // Filename is something like 'version-blabla.js' | ||
85 | const version = file.split('-')[0] | ||
86 | filesToMigrate.push({ | ||
87 | version, | ||
88 | script: file | ||
89 | }) | ||
90 | }) | ||
91 | |||
92 | return callback(err, filesToMigrate) | ||
93 | }) | ||
94 | } | ||
95 | |||
96 | function executeMigration (actualVersion, entity, callback) { | ||
97 | const versionScript = parseInt(entity.version) | ||
98 | |||
99 | // Do not execute old migration scripts | ||
100 | if (versionScript <= actualVersion) return callback(null) | ||
101 | |||
102 | // Load the migration module and run it | ||
103 | const migrationScriptName = entity.script | ||
104 | logger.info('Executing %s migration script.', migrationScriptName) | ||
105 | |||
106 | const migrationScript = require(path.join(__dirname, 'migrations', migrationScriptName)) | ||
107 | |||
108 | db.sequelize.transaction().asCallback(function (err, t) { | ||
109 | if (err) return callback(err) | ||
110 | |||
111 | const options = { | ||
112 | transaction: t, | ||
113 | queryInterface: db.sequelize.getQueryInterface(), | ||
114 | sequelize: db.sequelize, | ||
115 | Sequelize: db.Sequelize | ||
116 | } | ||
117 | migrationScript.up(options, function (err) { | ||
118 | if (err) { | ||
119 | t.rollback() | ||
120 | return callback(err) | ||
121 | } | ||
122 | |||
123 | // Update the new migration version | ||
124 | db.Application.updateMigrationVersion(versionScript, t, function (err) { | ||
125 | if (err) { | ||
126 | t.rollback() | ||
127 | return callback(err) | ||
128 | } | ||
129 | |||
130 | t.commit().asCallback(callback) | ||
131 | }) | ||
132 | }) | ||
133 | }) | ||
134 | } | ||