diff options
author | Chocobozzz <florian.bigard@gmail.com> | 2016-12-25 09:44:57 +0100 |
---|---|---|
committer | Chocobozzz <florian.bigard@gmail.com> | 2016-12-25 09:44:57 +0100 |
commit | b769007f733769d3afe2d29a3eb23e2e7693f301 (patch) | |
tree | 3816d542e907f298d08338129e0f6b9ca0df8fbb /server | |
parent | dd6019932efd6ae3b790bf024bc0cd74162e4517 (diff) | |
download | PeerTube-b769007f733769d3afe2d29a3eb23e2e7693f301.tar.gz PeerTube-b769007f733769d3afe2d29a3eb23e2e7693f301.tar.zst PeerTube-b769007f733769d3afe2d29a3eb23e2e7693f301.zip |
Update migrations code
Diffstat (limited to 'server')
-rw-r--r-- | server/initializers/checker.js | 2 | ||||
-rw-r--r-- | server/initializers/constants.js | 43 | ||||
-rw-r--r-- | server/initializers/database.js | 65 | ||||
-rw-r--r-- | server/initializers/installer.js | 5 | ||||
-rw-r--r-- | server/initializers/migrations/0005-create-application.js | 17 | ||||
-rw-r--r-- | server/initializers/migrations/0005-example.js | 14 | ||||
-rw-r--r-- | server/initializers/migrations/0010-users-password.js | 22 | ||||
-rw-r--r-- | server/initializers/migrations/0015-admin-role.js | 16 | ||||
-rw-r--r-- | server/initializers/migrations/0020-requests-endpoint.js | 15 | ||||
-rw-r--r-- | server/initializers/migrations/0025-video-filenames.js | 57 | ||||
-rw-r--r-- | server/initializers/migrations/0030-video-magnet.js | 32 | ||||
-rw-r--r-- | server/initializers/migrations/0035-url-to-host.js | 30 | ||||
-rw-r--r-- | server/initializers/migrations/0040-video-remote-id.js | 59 | ||||
-rw-r--r-- | server/initializers/migrator.js | 88 | ||||
-rw-r--r-- | server/models/application.js | 26 | ||||
-rw-r--r-- | server/models/video.js | 7 | ||||
-rw-r--r-- | server/tests/utils/servers.js | 2 |
17 files changed, 155 insertions, 345 deletions
diff --git a/server/initializers/checker.js b/server/initializers/checker.js index 7b402de82..2753604dc 100644 --- a/server/initializers/checker.js +++ b/server/initializers/checker.js | |||
@@ -27,7 +27,7 @@ function checkConfig () { | |||
27 | function checkMissedConfig () { | 27 | function checkMissedConfig () { |
28 | const required = [ 'listen.port', | 28 | const required = [ 'listen.port', |
29 | 'webserver.https', 'webserver.hostname', 'webserver.port', | 29 | 'webserver.https', 'webserver.hostname', 'webserver.port', |
30 | 'database.hostname', 'database.port', 'database.suffix', | 30 | 'database.hostname', 'database.port', 'database.suffix', 'database.username', 'database.password', |
31 | 'storage.certs', 'storage.videos', 'storage.logs', 'storage.thumbnails', 'storage.previews' | 31 | 'storage.certs', 'storage.videos', 'storage.logs', 'storage.thumbnails', 'storage.previews' |
32 | ] | 32 | ] |
33 | const miss = [] | 33 | const miss = [] |
diff --git a/server/initializers/constants.js b/server/initializers/constants.js index 1ad0c82a0..6f39b65da 100644 --- a/server/initializers/constants.js +++ b/server/initializers/constants.js | |||
@@ -37,7 +37,9 @@ const CONFIG = { | |||
37 | DATABASE: { | 37 | DATABASE: { |
38 | DBNAME: 'peertube' + config.get('database.suffix'), | 38 | DBNAME: 'peertube' + config.get('database.suffix'), |
39 | HOSTNAME: config.get('database.hostname'), | 39 | HOSTNAME: config.get('database.hostname'), |
40 | PORT: config.get('database.port') | 40 | PORT: config.get('database.port'), |
41 | USERNAME: config.get('database.username'), | ||
42 | PASSWORD: config.get('database.password') | ||
41 | }, | 43 | }, |
42 | STORAGE: { | 44 | STORAGE: { |
43 | CERT_DIR: path.join(__dirname, '..', '..', config.get('storage.certs')), | 45 | CERT_DIR: path.join(__dirname, '..', '..', config.get('storage.certs')), |
@@ -87,41 +89,7 @@ const FRIEND_SCORE = { | |||
87 | 89 | ||
88 | // --------------------------------------------------------------------------- | 90 | // --------------------------------------------------------------------------- |
89 | 91 | ||
90 | const MIGRATION_SCRIPTS = [ | 92 | const LAST_MIGRATION_VERSION = 0 |
91 | { | ||
92 | script: '0005-create-application', | ||
93 | version: 5 | ||
94 | }, | ||
95 | { | ||
96 | script: '0010-users-password', | ||
97 | version: 10 | ||
98 | }, | ||
99 | { | ||
100 | script: '0015-admin-role', | ||
101 | version: 15 | ||
102 | }, | ||
103 | { | ||
104 | script: '0020-requests-endpoint', | ||
105 | version: 20 | ||
106 | }, | ||
107 | { | ||
108 | script: '0025-video-filenames', | ||
109 | version: 25 | ||
110 | }, | ||
111 | { | ||
112 | script: '0030-video-magnet', | ||
113 | version: 30 | ||
114 | }, | ||
115 | { | ||
116 | script: '0035-url-to-host', | ||
117 | version: 35 | ||
118 | }, | ||
119 | { | ||
120 | script: '0040-video-remote-id', | ||
121 | version: 40 | ||
122 | } | ||
123 | ] | ||
124 | const LAST_SQL_SCHEMA_VERSION = (maxBy(MIGRATION_SCRIPTS, 'version'))['version'] | ||
125 | 93 | ||
126 | // --------------------------------------------------------------------------- | 94 | // --------------------------------------------------------------------------- |
127 | 95 | ||
@@ -197,8 +165,7 @@ module.exports = { | |||
197 | CONFIG, | 165 | CONFIG, |
198 | CONSTRAINTS_FIELDS, | 166 | CONSTRAINTS_FIELDS, |
199 | FRIEND_SCORE, | 167 | FRIEND_SCORE, |
200 | LAST_SQL_SCHEMA_VERSION, | 168 | LAST_MIGRATION_VERSION, |
201 | MIGRATION_SCRIPTS, | ||
202 | OAUTH_LIFETIME, | 169 | OAUTH_LIFETIME, |
203 | PAGINATION_COUNT_DEFAULT, | 170 | PAGINATION_COUNT_DEFAULT, |
204 | PODS_SCORE, | 171 | PODS_SCORE, |
diff --git a/server/initializers/database.js b/server/initializers/database.js index 9642231b9..f8f68adeb 100644 --- a/server/initializers/database.js +++ b/server/initializers/database.js | |||
@@ -10,7 +10,11 @@ const utils = require('../helpers/utils') | |||
10 | 10 | ||
11 | const database = {} | 11 | const database = {} |
12 | 12 | ||
13 | const sequelize = new Sequelize(constants.CONFIG.DATABASE.DBNAME, 'peertube', 'peertube', { | 13 | const dbname = constants.CONFIG.DATABASE.DBNAME |
14 | const username = constants.CONFIG.DATABASE.USERNAME | ||
15 | const password = constants.CONFIG.DATABASE.PASSWORD | ||
16 | |||
17 | const sequelize = new Sequelize(dbname, username, password, { | ||
14 | dialect: 'postgres', | 18 | dialect: 'postgres', |
15 | host: constants.CONFIG.DATABASE.HOSTNAME, | 19 | host: constants.CONFIG.DATABASE.HOSTNAME, |
16 | port: constants.CONFIG.DATABASE.PORT, | 20 | port: constants.CONFIG.DATABASE.PORT, |
@@ -26,33 +30,48 @@ const sequelize = new Sequelize(constants.CONFIG.DATABASE.DBNAME, 'peertube', 'p | |||
26 | } | 30 | } |
27 | }) | 31 | }) |
28 | 32 | ||
29 | const modelDirectory = path.join(__dirname, '..', 'models') | 33 | database.sequelize = sequelize |
30 | fs.readdir(modelDirectory, function (err, files) { | 34 | database.Sequelize = Sequelize |
31 | if (err) throw err | 35 | database.init = init |
32 | 36 | ||
33 | files.filter(function (file) { | 37 | // --------------------------------------------------------------------------- |
34 | if (file === 'utils.js') return false | ||
35 | 38 | ||
36 | return true | 39 | module.exports = database |
37 | }) | ||
38 | .forEach(function (file) { | ||
39 | const model = sequelize.import(path.join(modelDirectory, file)) | ||
40 | 40 | ||
41 | database[model.name] = model | 41 | // --------------------------------------------------------------------------- |
42 | }) | ||
43 | 42 | ||
44 | Object.keys(database).forEach(function (modelName) { | 43 | function init (silent, callback) { |
45 | if ('associate' in database[modelName]) { | 44 | if (!callback) { |
46 | database[modelName].associate(database) | 45 | callback = silent |
47 | } | 46 | silent = false |
48 | }) | 47 | } |
49 | 48 | ||
50 | logger.info('Database is ready.') | 49 | if (!callback) callback = function () {} |
51 | }) | ||
52 | 50 | ||
53 | database.sequelize = sequelize | 51 | const modelDirectory = path.join(__dirname, '..', 'models') |
54 | database.Sequelize = Sequelize | 52 | fs.readdir(modelDirectory, function (err, files) { |
53 | if (err) throw err | ||
55 | 54 | ||
56 | // --------------------------------------------------------------------------- | 55 | files.filter(function (file) { |
56 | // For all models but not utils.js | ||
57 | if (file === 'utils.js') return false | ||
57 | 58 | ||
58 | module.exports = database | 59 | return true |
60 | }) | ||
61 | .forEach(function (file) { | ||
62 | const model = sequelize.import(path.join(modelDirectory, file)) | ||
63 | |||
64 | database[model.name] = model | ||
65 | }) | ||
66 | |||
67 | Object.keys(database).forEach(function (modelName) { | ||
68 | if ('associate' in database[modelName]) { | ||
69 | database[modelName].associate(database) | ||
70 | } | ||
71 | }) | ||
72 | |||
73 | if (!silent) logger.info('Database is ready.') | ||
74 | |||
75 | return callback(null) | ||
76 | }) | ||
77 | } | ||
diff --git a/server/initializers/installer.js b/server/initializers/installer.js index 4823bc8c8..d5382364e 100644 --- a/server/initializers/installer.js +++ b/server/initializers/installer.js | |||
@@ -121,9 +121,8 @@ function createOAuthAdminIfNotExist (callback) { | |||
121 | logger.info('Username: ' + username) | 121 | logger.info('Username: ' + username) |
122 | logger.info('User password: ' + password) | 122 | logger.info('User password: ' + password) |
123 | 123 | ||
124 | logger.info('Creating Application collection.') | 124 | logger.info('Creating Application table.') |
125 | const application = db.Application.build({ sqlSchemaVersion: constants.LAST_SQL_SCHEMA_VERSION }) | 125 | db.Application.create({ migrationVersion: constants.LAST_MIGRATION_VERSION }).asCallback(callback) |
126 | application.save().asCallback(callback) | ||
127 | }) | 126 | }) |
128 | }) | 127 | }) |
129 | } | 128 | } |
diff --git a/server/initializers/migrations/0005-create-application.js b/server/initializers/migrations/0005-create-application.js deleted file mode 100644 index e99dec019..000000000 --- a/server/initializers/migrations/0005-create-application.js +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | /* | ||
2 | Create the application collection in MongoDB. | ||
3 | Used to store the actual MongoDB scheme version. | ||
4 | */ | ||
5 | |||
6 | const mongoose = require('mongoose') | ||
7 | |||
8 | const Application = mongoose.model('Application') | ||
9 | |||
10 | exports.up = function (callback) { | ||
11 | const application = new Application() | ||
12 | application.save(callback) | ||
13 | } | ||
14 | |||
15 | exports.down = function (callback) { | ||
16 | throw new Error('Not implemented.') | ||
17 | } | ||
diff --git a/server/initializers/migrations/0005-example.js b/server/initializers/migrations/0005-example.js new file mode 100644 index 000000000..481c2c4dd --- /dev/null +++ b/server/initializers/migrations/0005-example.js | |||
@@ -0,0 +1,14 @@ | |||
1 | /* | ||
2 | This is just an example. | ||
3 | */ | ||
4 | |||
5 | const db = require('../database') | ||
6 | |||
7 | // options contains the transaction | ||
8 | exports.up = function (options, callback) { | ||
9 | // db.Application.create({ migrationVersion: 42 }, { transaction: options.transaction }).asCallback(callback) | ||
10 | } | ||
11 | |||
12 | exports.down = function (options, callback) { | ||
13 | throw new Error('Not implemented.') | ||
14 | } | ||
diff --git a/server/initializers/migrations/0010-users-password.js b/server/initializers/migrations/0010-users-password.js deleted file mode 100644 index a0616a269..000000000 --- a/server/initializers/migrations/0010-users-password.js +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | /* | ||
2 | Convert plain user password to encrypted user password. | ||
3 | */ | ||
4 | |||
5 | const eachSeries = require('async/eachSeries') | ||
6 | const mongoose = require('mongoose') | ||
7 | |||
8 | const User = mongoose.model('User') | ||
9 | |||
10 | exports.up = function (callback) { | ||
11 | User.list(function (err, users) { | ||
12 | if (err) return callback(err) | ||
13 | |||
14 | eachSeries(users, function (user, callbackEach) { | ||
15 | user.save(callbackEach) | ||
16 | }, callback) | ||
17 | }) | ||
18 | } | ||
19 | |||
20 | exports.down = function (callback) { | ||
21 | throw new Error('Not implemented.') | ||
22 | } | ||
diff --git a/server/initializers/migrations/0015-admin-role.js b/server/initializers/migrations/0015-admin-role.js deleted file mode 100644 index af06dca9e..000000000 --- a/server/initializers/migrations/0015-admin-role.js +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | /* | ||
2 | Set the admin role to the root user. | ||
3 | */ | ||
4 | |||
5 | const constants = require('../constants') | ||
6 | const mongoose = require('mongoose') | ||
7 | |||
8 | const User = mongoose.model('User') | ||
9 | |||
10 | exports.up = function (callback) { | ||
11 | User.update({ username: 'root' }, { role: constants.USER_ROLES.ADMIN }, callback) | ||
12 | } | ||
13 | |||
14 | exports.down = function (callback) { | ||
15 | throw new Error('Not implemented.') | ||
16 | } | ||
diff --git a/server/initializers/migrations/0020-requests-endpoint.js b/server/initializers/migrations/0020-requests-endpoint.js deleted file mode 100644 index 55feec571..000000000 --- a/server/initializers/migrations/0020-requests-endpoint.js +++ /dev/null | |||
@@ -1,15 +0,0 @@ | |||
1 | /* | ||
2 | Set the endpoint videos for requests. | ||
3 | */ | ||
4 | |||
5 | const mongoose = require('mongoose') | ||
6 | |||
7 | const Request = mongoose.model('Request') | ||
8 | |||
9 | exports.up = function (callback) { | ||
10 | Request.update({ }, { endpoint: 'videos' }, callback) | ||
11 | } | ||
12 | |||
13 | exports.down = function (callback) { | ||
14 | throw new Error('Not implemented.') | ||
15 | } | ||
diff --git a/server/initializers/migrations/0025-video-filenames.js b/server/initializers/migrations/0025-video-filenames.js deleted file mode 100644 index df21494d7..000000000 --- a/server/initializers/migrations/0025-video-filenames.js +++ /dev/null | |||
@@ -1,57 +0,0 @@ | |||
1 | /* | ||
2 | Rename thumbnails and video filenames to _id.extension | ||
3 | */ | ||
4 | |||
5 | const each = require('async/each') | ||
6 | const fs = require('fs') | ||
7 | const path = require('path') | ||
8 | const mongoose = require('mongoose') | ||
9 | |||
10 | const constants = require('../constants') | ||
11 | const logger = require('../../helpers/logger') | ||
12 | |||
13 | const Video = mongoose.model('Video') | ||
14 | |||
15 | exports.up = function (callback) { | ||
16 | // Use of lean because the new Video scheme does not have filename field | ||
17 | Video.find({ filename: { $ne: null } }).lean().exec(function (err, videos) { | ||
18 | if (err) throw err | ||
19 | |||
20 | each(videos, function (video, callbackEach) { | ||
21 | const torrentName = video.filename + '.torrent' | ||
22 | const thumbnailName = video.thumbnail | ||
23 | const thumbnailExtension = path.extname(thumbnailName) | ||
24 | const videoName = video.filename | ||
25 | const videoExtension = path.extname(videoName) | ||
26 | |||
27 | const newTorrentName = video._id + '.torrent' | ||
28 | const newThumbnailName = video._id + thumbnailExtension | ||
29 | const newVideoName = video._id + videoExtension | ||
30 | |||
31 | const torrentsDir = constants.CONFIG.STORAGE.TORRENTS_DIR | ||
32 | const thumbnailsDir = constants.CONFIG.STORAGE.THUMBNAILS_DIR | ||
33 | const videosDir = constants.CONFIG.STORAGE.VIDEOS_DIR | ||
34 | |||
35 | logger.info('Renaming %s to %s.', torrentsDir + torrentName, torrentsDir + newTorrentName) | ||
36 | fs.renameSync(torrentsDir + torrentName, torrentsDir + newTorrentName) | ||
37 | |||
38 | logger.info('Renaming %s to %s.', thumbnailsDir + thumbnailName, thumbnailsDir + newThumbnailName) | ||
39 | fs.renameSync(thumbnailsDir + thumbnailName, thumbnailsDir + newThumbnailName) | ||
40 | |||
41 | logger.info('Renaming %s to %s.', videosDir + videoName, videosDir + newVideoName) | ||
42 | fs.renameSync(videosDir + videoName, videosDir + newVideoName) | ||
43 | |||
44 | Video.load(video._id, function (err, videoObj) { | ||
45 | if (err) return callbackEach(err) | ||
46 | |||
47 | videoObj.extname = videoExtension | ||
48 | videoObj.remoteId = null | ||
49 | videoObj.save(callbackEach) | ||
50 | }) | ||
51 | }, callback) | ||
52 | }) | ||
53 | } | ||
54 | |||
55 | exports.down = function (callback) { | ||
56 | throw new Error('Not implemented.') | ||
57 | } | ||
diff --git a/server/initializers/migrations/0030-video-magnet.js b/server/initializers/migrations/0030-video-magnet.js deleted file mode 100644 index b9119d61c..000000000 --- a/server/initializers/migrations/0030-video-magnet.js +++ /dev/null | |||
@@ -1,32 +0,0 @@ | |||
1 | /* | ||
2 | Change video magnet structures | ||
3 | */ | ||
4 | |||
5 | const each = require('async/each') | ||
6 | const magnet = require('magnet-uri') | ||
7 | const mongoose = require('mongoose') | ||
8 | |||
9 | const Video = mongoose.model('Video') | ||
10 | |||
11 | exports.up = function (callback) { | ||
12 | // Use of lean because the new Video scheme does not have magnetUri field | ||
13 | Video.find({ }).lean().exec(function (err, videos) { | ||
14 | if (err) throw err | ||
15 | |||
16 | each(videos, function (video, callbackEach) { | ||
17 | const parsed = magnet.decode(video.magnetUri) | ||
18 | const infoHash = parsed.infoHash | ||
19 | |||
20 | Video.load(video._id, function (err, videoObj) { | ||
21 | if (err) return callbackEach(err) | ||
22 | |||
23 | videoObj.magnet.infoHash = infoHash | ||
24 | videoObj.save(callbackEach) | ||
25 | }) | ||
26 | }, callback) | ||
27 | }) | ||
28 | } | ||
29 | |||
30 | exports.down = function (callback) { | ||
31 | throw new Error('Not implemented.') | ||
32 | } | ||
diff --git a/server/initializers/migrations/0035-url-to-host.js b/server/initializers/migrations/0035-url-to-host.js deleted file mode 100644 index 6243304d5..000000000 --- a/server/initializers/migrations/0035-url-to-host.js +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | /* | ||
2 | Change video magnet structures | ||
3 | */ | ||
4 | |||
5 | const each = require('async/each') | ||
6 | const mongoose = require('mongoose') | ||
7 | |||
8 | const Video = mongoose.model('Video') | ||
9 | |||
10 | exports.up = function (callback) { | ||
11 | // Use of lean because the new Video scheme does not have podUrl field | ||
12 | Video.find({ }).lean().exec(function (err, videos) { | ||
13 | if (err) throw err | ||
14 | |||
15 | each(videos, function (video, callbackEach) { | ||
16 | Video.load(video._id, function (err, videoObj) { | ||
17 | if (err) return callbackEach(err) | ||
18 | |||
19 | const host = video.podUrl.split('://')[1] | ||
20 | |||
21 | videoObj.podHost = host | ||
22 | videoObj.save(callbackEach) | ||
23 | }) | ||
24 | }, callback) | ||
25 | }) | ||
26 | } | ||
27 | |||
28 | exports.down = function (callback) { | ||
29 | throw new Error('Not implemented.') | ||
30 | } | ||
diff --git a/server/initializers/migrations/0040-video-remote-id.js b/server/initializers/migrations/0040-video-remote-id.js deleted file mode 100644 index 46a14a689..000000000 --- a/server/initializers/migrations/0040-video-remote-id.js +++ /dev/null | |||
@@ -1,59 +0,0 @@ | |||
1 | /* | ||
2 | Use remote id as identifier | ||
3 | */ | ||
4 | |||
5 | const map = require('lodash/map') | ||
6 | const mongoose = require('mongoose') | ||
7 | const readline = require('readline') | ||
8 | |||
9 | const rl = readline.createInterface({ | ||
10 | input: process.stdin, | ||
11 | output: process.stdout | ||
12 | }) | ||
13 | |||
14 | const logger = require('../../helpers/logger') | ||
15 | const friends = require('../../lib/friends') | ||
16 | |||
17 | const Pod = mongoose.model('Pod') | ||
18 | const Video = mongoose.model('Video') | ||
19 | |||
20 | exports.up = function (callback) { | ||
21 | Pod.find({}).lean().exec(function (err, pods) { | ||
22 | if (err) return callback(err) | ||
23 | |||
24 | // We need to quit friends first | ||
25 | if (pods.length === 0) { | ||
26 | return setVideosRemoteId(callback) | ||
27 | } | ||
28 | |||
29 | const timeout = setTimeout(function () { | ||
30 | throw new Error('You need to enter a value!') | ||
31 | }, 10000) | ||
32 | |||
33 | rl.question('I am sorry but I need to quit friends for upgrading. Do you want to continue? (yes/*)', function (answer) { | ||
34 | if (answer !== 'yes') throw new Error('I cannot continue.') | ||
35 | |||
36 | clearTimeout(timeout) | ||
37 | rl.close() | ||
38 | |||
39 | const urls = map(pods, 'url') | ||
40 | logger.info('Saying goodbye to: ' + urls.join(', ')) | ||
41 | |||
42 | setVideosRemoteId(function () { | ||
43 | friends.quitFriends(callback) | ||
44 | }) | ||
45 | }) | ||
46 | }) | ||
47 | } | ||
48 | |||
49 | exports.down = function (callback) { | ||
50 | throw new Error('Not implemented.') | ||
51 | } | ||
52 | |||
53 | function setVideosRemoteId (callback) { | ||
54 | Video.update({ filename: { $ne: null } }, { remoteId: null }, function (err) { | ||
55 | if (err) throw err | ||
56 | |||
57 | Video.update({ filename: null }, { remoteId: mongoose.Types.ObjectId() }, callback) | ||
58 | }) | ||
59 | } | ||
diff --git a/server/initializers/migrator.js b/server/initializers/migrator.js index 9e5350e60..eaecb4936 100644 --- a/server/initializers/migrator.js +++ b/server/initializers/migrator.js | |||
@@ -1,6 +1,7 @@ | |||
1 | 'use strict' | 1 | 'use strict' |
2 | 2 | ||
3 | const eachSeries = require('async/eachSeries') | 3 | const eachSeries = require('async/eachSeries') |
4 | const fs = require('fs') | ||
4 | const path = require('path') | 5 | const path = require('path') |
5 | 6 | ||
6 | const constants = require('./constants') | 7 | const constants = require('./constants') |
@@ -12,35 +13,24 @@ const migrator = { | |||
12 | } | 13 | } |
13 | 14 | ||
14 | function migrate (callback) { | 15 | function migrate (callback) { |
15 | db.Application.loadSqlSchemaVersion(function (err, actualVersion) { | 16 | db.Application.loadMigrationVersion(function (err, actualVersion) { |
16 | if (err) return callback(err) | 17 | if (err) return callback(err) |
17 | 18 | ||
18 | // If there are a new mongo schemas | 19 | // If there are a new migration scripts |
19 | if (!actualVersion || actualVersion < constants.LAST_SQL_SCHEMA_VERSION) { | 20 | if (actualVersion < constants.LAST_MIGRATION_VERSION) { |
20 | logger.info('Begin migrations.') | 21 | logger.info('Begin migrations.') |
21 | 22 | ||
22 | eachSeries(constants.MONGO_MIGRATION_SCRIPTS, function (entity, callbackEach) { | 23 | getMigrationScripts(function (err, migrationScripts) { |
23 | const versionScript = entity.version | 24 | if (err) return callback(err) |
24 | |||
25 | // Do not execute old migration scripts | ||
26 | if (versionScript <= actualVersion) return callbackEach(null) | ||
27 | |||
28 | // Load the migration module and run it | ||
29 | const migrationScriptName = entity.script | ||
30 | logger.info('Executing %s migration script.', migrationScriptName) | ||
31 | 25 | ||
32 | const migrationScript = require(path.join(__dirname, 'migrations', migrationScriptName)) | 26 | eachSeries(migrationScripts, function (entity, callbackEach) { |
33 | migrationScript.up(function (err) { | 27 | executeMigration(actualVersion, entity, callbackEach) |
34 | if (err) return callbackEach(err) | 28 | }, function (err) { |
29 | if (err) return callback(err) | ||
35 | 30 | ||
36 | // Update the new mongo version schema | 31 | logger.info('Migrations finished. New migration version schema: %s', constants.LAST_MIGRATION_VERSION) |
37 | db.Application.updateSqlSchemaVersion(versionScript, callbackEach) | 32 | return callback(null) |
38 | }) | 33 | }) |
39 | }, function (err) { | ||
40 | if (err) return callback(err) | ||
41 | |||
42 | logger.info('Migrations finished. New SQL version schema: %s', constants.LAST_SQL_SCHEMA_VERSION) | ||
43 | return callback(null) | ||
44 | }) | 34 | }) |
45 | } else { | 35 | } else { |
46 | return callback(null) | 36 | return callback(null) |
@@ -52,3 +42,57 @@ function migrate (callback) { | |||
52 | 42 | ||
53 | module.exports = migrator | 43 | module.exports = migrator |
54 | 44 | ||
45 | // --------------------------------------------------------------------------- | ||
46 | |||
47 | function getMigrationScripts (callback) { | ||
48 | fs.readdir(path.join(__dirname, 'migrations'), function (err, files) { | ||
49 | if (err) return callback(err) | ||
50 | |||
51 | const filesToMigrate = [] | ||
52 | |||
53 | files.forEach(function (file) { | ||
54 | // Filename is something like 'version-blabla.js' | ||
55 | const version = file.split('-')[0] | ||
56 | filesToMigrate.push({ | ||
57 | version, | ||
58 | script: file | ||
59 | }) | ||
60 | }) | ||
61 | |||
62 | return callback(err, filesToMigrate) | ||
63 | }) | ||
64 | } | ||
65 | |||
66 | function executeMigration (actualVersion, entity, callback) { | ||
67 | const versionScript = entity.version | ||
68 | |||
69 | // Do not execute old migration scripts | ||
70 | if (versionScript <= actualVersion) return callback(null) | ||
71 | |||
72 | // Load the migration module and run it | ||
73 | const migrationScriptName = entity.script | ||
74 | logger.info('Executing %s migration script.', migrationScriptName) | ||
75 | |||
76 | const migrationScript = require(path.join(__dirname, 'migrations', migrationScriptName)) | ||
77 | |||
78 | db.sequelize.transaction().asCallback(function (err, t) { | ||
79 | if (err) return callback(err) | ||
80 | |||
81 | migrationScript.up({ transaction: t }, function (err) { | ||
82 | if (err) { | ||
83 | t.rollback() | ||
84 | return callback(err) | ||
85 | } | ||
86 | |||
87 | // Update the new migration version | ||
88 | db.Application.updateMigrationVersion(versionScript, t, function (err) { | ||
89 | if (err) { | ||
90 | t.rollback() | ||
91 | return callback(err) | ||
92 | } | ||
93 | |||
94 | t.commit() | ||
95 | }) | ||
96 | }) | ||
97 | }) | ||
98 | } | ||
diff --git a/server/models/application.js b/server/models/application.js index ec1d7b122..4114ed76d 100644 --- a/server/models/application.js +++ b/server/models/application.js | |||
@@ -1,15 +1,15 @@ | |||
1 | module.exports = function (sequelize, DataTypes) { | 1 | module.exports = function (sequelize, DataTypes) { |
2 | const Application = sequelize.define('Application', | 2 | const Application = sequelize.define('Application', |
3 | { | 3 | { |
4 | sqlSchemaVersion: { | 4 | migrationVersion: { |
5 | type: DataTypes.INTEGER, | 5 | type: DataTypes.INTEGER, |
6 | defaultValue: 0 | 6 | defaultValue: 0 |
7 | } | 7 | } |
8 | }, | 8 | }, |
9 | { | 9 | { |
10 | classMethods: { | 10 | classMethods: { |
11 | loadSqlSchemaVersion, | 11 | loadMigrationVersion, |
12 | updateSqlSchemaVersion | 12 | updateMigrationVersion |
13 | } | 13 | } |
14 | } | 14 | } |
15 | ) | 15 | ) |
@@ -19,18 +19,28 @@ module.exports = function (sequelize, DataTypes) { | |||
19 | 19 | ||
20 | // --------------------------------------------------------------------------- | 20 | // --------------------------------------------------------------------------- |
21 | 21 | ||
22 | function loadSqlSchemaVersion (callback) { | 22 | function loadMigrationVersion (callback) { |
23 | const query = { | 23 | const query = { |
24 | attributes: [ 'sqlSchemaVersion' ] | 24 | attributes: [ 'migrationVersion' ] |
25 | } | 25 | } |
26 | 26 | ||
27 | return this.findOne(query).asCallback(function (err, data) { | 27 | return this.findOne(query).asCallback(function (err, data) { |
28 | const version = data ? data.sqlSchemaVersion : 0 | 28 | const version = data ? data.migrationVersion : 0 |
29 | 29 | ||
30 | return callback(err, version) | 30 | return callback(err, version) |
31 | }) | 31 | }) |
32 | } | 32 | } |
33 | 33 | ||
34 | function updateSqlSchemaVersion (newVersion, callback) { | 34 | function updateMigrationVersion (newVersion, transaction, callback) { |
35 | return this.update({ sqlSchemaVersion: newVersion }).asCallback(callback) | 35 | const options = { |
36 | where: {} | ||
37 | } | ||
38 | |||
39 | if (!callback) { | ||
40 | transaction = callback | ||
41 | } else { | ||
42 | options.transaction = transaction | ||
43 | } | ||
44 | |||
45 | return this.update({ migrationVersion: newVersion }, options).asCallback(callback) | ||
36 | } | 46 | } |
diff --git a/server/models/video.js b/server/models/video.js index 0023a24e1..af05a861f 100644 --- a/server/models/video.js +++ b/server/models/video.js | |||
@@ -16,7 +16,7 @@ const modelUtils = require('./utils') | |||
16 | // --------------------------------------------------------------------------- | 16 | // --------------------------------------------------------------------------- |
17 | 17 | ||
18 | module.exports = function (sequelize, DataTypes) { | 18 | module.exports = function (sequelize, DataTypes) { |
19 | // TODO: add indexes on searchable columns | 19 | // TODO: add indexes on searchable columns |
20 | const Video = sequelize.define('Video', | 20 | const Video = sequelize.define('Video', |
21 | { | 21 | { |
22 | id: { | 22 | id: { |
@@ -50,6 +50,7 @@ module.exports = function (sequelize, DataTypes) { | |||
50 | 50 | ||
51 | generateThumbnailFromBase64, | 51 | generateThumbnailFromBase64, |
52 | getDurationFromFile, | 52 | getDurationFromFile, |
53 | list, | ||
53 | listForApi, | 54 | listForApi, |
54 | listByHostAndRemoteId, | 55 | listByHostAndRemoteId, |
55 | listOwnedAndPopulateAuthorAndTags, | 56 | listOwnedAndPopulateAuthorAndTags, |
@@ -310,6 +311,10 @@ function getDurationFromFile (videoPath, callback) { | |||
310 | }) | 311 | }) |
311 | } | 312 | } |
312 | 313 | ||
314 | function list (callback) { | ||
315 | return this.find().asCallback() | ||
316 | } | ||
317 | |||
313 | function listForApi (start, count, sort, callback) { | 318 | function listForApi (start, count, sort, callback) { |
314 | const query = { | 319 | const query = { |
315 | offset: start, | 320 | offset: start, |
diff --git a/server/tests/utils/servers.js b/server/tests/utils/servers.js index 4e55f8f5c..e7c756499 100644 --- a/server/tests/utils/servers.js +++ b/server/tests/utils/servers.js | |||
@@ -103,7 +103,7 @@ function runServer (number, callback) { | |||
103 | if (serverRunString[key] === false) dontContinue = true | 103 | if (serverRunString[key] === false) dontContinue = true |
104 | } | 104 | } |
105 | 105 | ||
106 | // If no, there is maybe one thing not already initialized (mongodb...) | 106 | // If no, there is maybe one thing not already initialized (client/user credentials generation...) |
107 | if (dontContinue === true) return | 107 | if (dontContinue === true) return |
108 | 108 | ||
109 | server.app.stdout.removeListener('data', onStdout) | 109 | server.app.stdout.removeListener('data', onStdout) |