aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChocobozzz <florian.bigard@gmail.com>2016-12-30 11:27:42 +0100
committerChocobozzz <florian.bigard@gmail.com>2016-12-30 11:27:42 +0100
commit3d118fb501f576a298f6bb059167e4c7f4dd8dcc (patch)
treef2c8e74e1ca9a9d39b86412a6444a95343d2833e
parent7b1f49de22c40ae121ddb3c399b2540ba56fd414 (diff)
downloadPeerTube-3d118fb501f576a298f6bb059167e4c7f4dd8dcc.tar.gz
PeerTube-3d118fb501f576a298f6bb059167e4c7f4dd8dcc.tar.zst
PeerTube-3d118fb501f576a298f6bb059167e4c7f4dd8dcc.zip
Server: propagate video update to other pods
-rw-r--r--server/controllers/api/remote.js108
-rw-r--r--server/controllers/api/videos.js2
-rw-r--r--server/helpers/custom-validators/videos.js15
-rw-r--r--server/models/video.js6
-rw-r--r--server/tests/api/multiple-pods.js55
5 files changed, 152 insertions, 34 deletions
diff --git a/server/controllers/api/remote.js b/server/controllers/api/remote.js
index 929ade555..254ae56d5 100644
--- a/server/controllers/api/remote.js
+++ b/server/controllers/api/remote.js
@@ -35,12 +35,21 @@ function remoteVideos (req, res, next) {
35 eachSeries(requests, function (request, callbackEach) { 35 eachSeries(requests, function (request, callbackEach) {
36 const videoData = request.data 36 const videoData = request.data
37 37
38 if (request.type === 'add') { 38 switch (request.type) {
39 addRemoteVideo(videoData, fromPod, callbackEach) 39 case 'add':
40 } else if (request.type === 'remove') { 40 addRemoteVideo(videoData, fromPod, callbackEach)
41 removeRemoteVideo(videoData, fromPod, callbackEach) 41 break
42 } else { 42
43 logger.error('Unkown remote request type %s.', request.type) 43 case 'update':
44 updateRemoteVideo(videoData, fromPod, callbackEach)
45 break
46
47 case 'remove':
48 removeRemoteVideo(videoData, fromPod, callbackEach)
49 break
50
51 default:
52 logger.error('Unkown remote request type %s.', request.type)
44 } 53 }
45 }, function (err) { 54 }, function (err) {
46 if (err) logger.error('Error managing remote videos.', { error: err }) 55 if (err) logger.error('Error managing remote videos.', { error: err })
@@ -143,24 +152,85 @@ function addRemoteVideo (videoToCreateData, fromPod, finalCallback) {
143 }) 152 })
144} 153}
145 154
146function removeRemoteVideo (videoToRemoveData, fromPod, callback) { 155function updateRemoteVideo (videoAttributesToUpdate, fromPod, finalCallback) {
147 // TODO: use bulkDestroy? 156 logger.debug('Updating remote video "%s".', videoAttributesToUpdate.name)
148 157
149 // We need the list because we have to remove some other stuffs (thumbnail etc) 158 waterfall([
150 db.Video.listByHostAndRemoteId(fromPod.host, videoToRemoveData.remoteId, function (err, videosList) { 159
151 if (err) { 160 function startTransaction (callback) {
152 logger.error('Cannot list videos from host and remote id.', { error: err.message }) 161 db.sequelize.transaction().asCallback(function (err, t) {
153 return callback(err) 162 return callback(err, t)
163 })
164 },
165
166 function findVideo (t, callback) {
167 db.Video.loadByHostAndRemoteId(fromPod.host, videoAttributesToUpdate.remoteId, function (err, videoInstance) {
168 if (err || !videoInstance) {
169 logger.error('Cannot load video from host and remote id.', { error: err.message })
170 return callback(err)
171 }
172
173 return callback(null, t, videoInstance)
174 })
175 },
176
177 function findOrCreateTags (t, videoInstance, callback) {
178 const tags = videoAttributesToUpdate.tags
179
180 db.Tag.findOrCreateTags(tags, t, function (err, tagInstances) {
181 return callback(err, t, videoInstance, tagInstances)
182 })
183 },
184
185 function updateVideoIntoDB (t, videoInstance, tagInstances, callback) {
186 const options = { transaction: t }
187
188 videoInstance.set('name', videoAttributesToUpdate.name)
189 videoInstance.set('description', videoAttributesToUpdate.description)
190 videoInstance.set('infoHash', videoAttributesToUpdate.infoHash)
191 videoInstance.set('duration', videoAttributesToUpdate.duration)
192 videoInstance.set('createdAt', videoAttributesToUpdate.createdAt)
193 videoInstance.set('extname', videoAttributesToUpdate.extname)
194
195 videoInstance.save(options).asCallback(function (err) {
196 return callback(err, t, videoInstance, tagInstances)
197 })
198 },
199
200 function associateTagsToVideo (t, videoInstance, tagInstances, callback) {
201 const options = { transaction: t }
202
203 videoInstance.setTags(tagInstances, options).asCallback(function (err) {
204 return callback(err, t)
205 })
154 } 206 }
155 207
156 if (videosList.length === 0) { 208 ], function (err, t) {
157 logger.error('No remote video was found for this pod.', { remoteId: videoToRemoveData.remoteId, podHost: fromPod.host }) 209 if (err) {
210 logger.error('Cannot update the remote video.')
211
212 // Abort transaction?
213 if (t) t.rollback()
214
215 return finalCallback(err)
158 } 216 }
159 217
160 each(videosList, function (video, callbackEach) { 218 // Commit transaction
161 logger.debug('Removing remote video %s.', video.remoteId) 219 t.commit()
220
221 return finalCallback()
222 })
223}
224
225function removeRemoteVideo (videoToRemoveData, fromPod, callback) {
226 // We need the instance because we have to remove some other stuffs (thumbnail etc)
227 db.Video.loadByHostAndRemoteId(fromPod.host, videoToRemoveData.remoteId, function (err, video) {
228 if (err || !video) {
229 logger.error('Cannot load video from host and remote id.', { error: err.message })
230 return callback(err)
231 }
162 232
163 video.destroy().asCallback(callbackEach) 233 logger.debug('Removing remote video %s.', video.remoteId)
164 }, callback) 234 video.destroy().asCallback(callback)
165 }) 235 })
166} 236}
diff --git a/server/controllers/api/videos.js b/server/controllers/api/videos.js
index 1b306d1cf..e5c52a87b 100644
--- a/server/controllers/api/videos.js
+++ b/server/controllers/api/videos.js
@@ -229,8 +229,6 @@ function updateVideo (req, res, next) {
229 229
230 // Add tags association 230 // Add tags association
231 videoInstance.save(options).asCallback(function (err) { 231 videoInstance.save(options).asCallback(function (err) {
232 if (err) return callback(err)
233
234 return callback(err, t, tagInstances) 232 return callback(err, t, tagInstances)
235 }) 233 })
236 }, 234 },
diff --git a/server/helpers/custom-validators/videos.js b/server/helpers/custom-validators/videos.js
index 4aaa6aaa9..b76eec1b5 100644
--- a/server/helpers/custom-validators/videos.js
+++ b/server/helpers/custom-validators/videos.js
@@ -38,6 +38,17 @@ function isEachRemoteVideosValid (requests) {
38 isVideoExtnameValid(video.extname) 38 isVideoExtnameValid(video.extname)
39 ) || 39 ) ||
40 ( 40 (
41 isRequestTypeUpdateValid(request.type) &&
42 isVideoDateValid(video.createdAt) &&
43 isVideoDescriptionValid(video.description) &&
44 isVideoDurationValid(video.duration) &&
45 isVideoInfoHashValid(video.infoHash) &&
46 isVideoNameValid(video.name) &&
47 isVideoTagsValid(video.tags) &&
48 isVideoRemoteIdValid(video.remoteId) &&
49 isVideoExtnameValid(video.extname)
50 ) ||
51 (
41 isRequestTypeRemoveValid(request.type) && 52 isRequestTypeRemoveValid(request.type) &&
42 isVideoNameValid(video.name) && 53 isVideoNameValid(video.name) &&
43 isVideoRemoteIdValid(video.remoteId) 54 isVideoRemoteIdValid(video.remoteId)
@@ -104,6 +115,10 @@ function isRequestTypeAddValid (value) {
104 return value === 'add' 115 return value === 'add'
105} 116}
106 117
118function isRequestTypeUpdateValid (value) {
119 return value === 'update'
120}
121
107function isRequestTypeRemoveValid (value) { 122function isRequestTypeRemoveValid (value) {
108 return value === 'remove' 123 return value === 'remove'
109} 124}
diff --git a/server/models/video.js b/server/models/video.js
index 14fbe2f71..f51d08f06 100644
--- a/server/models/video.js
+++ b/server/models/video.js
@@ -111,10 +111,10 @@ module.exports = function (sequelize, DataTypes) {
111 getDurationFromFile, 111 getDurationFromFile,
112 list, 112 list,
113 listForApi, 113 listForApi,
114 listByHostAndRemoteId,
115 listOwnedAndPopulateAuthorAndTags, 114 listOwnedAndPopulateAuthorAndTags,
116 listOwnedByAuthor, 115 listOwnedByAuthor,
117 load, 116 load,
117 loadByHostAndRemoteId,
118 loadAndPopulateAuthor, 118 loadAndPopulateAuthor,
119 loadAndPopulateAuthorAndPodAndTags, 119 loadAndPopulateAuthorAndPodAndTags,
120 searchAndPopulateAuthorAndPodAndTags 120 searchAndPopulateAuthorAndPodAndTags
@@ -428,7 +428,7 @@ function listForApi (start, count, sort, callback) {
428 }) 428 })
429} 429}
430 430
431function listByHostAndRemoteId (fromHost, remoteId, callback) { 431function loadByHostAndRemoteId (fromHost, remoteId, callback) {
432 const query = { 432 const query = {
433 where: { 433 where: {
434 remoteId: remoteId 434 remoteId: remoteId
@@ -449,7 +449,7 @@ function listByHostAndRemoteId (fromHost, remoteId, callback) {
449 ] 449 ]
450 } 450 }
451 451
452 return this.findAll(query).asCallback(callback) 452 return this.findOne(query).asCallback(callback)
453} 453}
454 454
455function listOwnedAndPopulateAuthorAndTags (callback) { 455function listOwnedAndPopulateAuthorAndTags (callback) {
diff --git a/server/tests/api/multiple-pods.js b/server/tests/api/multiple-pods.js
index f0fe59c5f..672187068 100644
--- a/server/tests/api/multiple-pods.js
+++ b/server/tests/api/multiple-pods.js
@@ -299,8 +299,8 @@ describe('Test multiple pods', function () {
299 if (err) throw err 299 if (err) throw err
300 300
301 const video = res.body.data[0] 301 const video = res.body.data[0]
302 toRemove.push(res.body.data[2].id) 302 toRemove.push(res.body.data[2])
303 toRemove.push(res.body.data[3].id) 303 toRemove.push(res.body.data[3])
304 304
305 webtorrent.add(video.magnetUri, function (torrent) { 305 webtorrent.add(video.magnetUri, function (torrent) {
306 expect(torrent.files).to.exist 306 expect(torrent.files).to.exist
@@ -368,16 +368,51 @@ describe('Test multiple pods', function () {
368 }) 368 })
369 }) 369 })
370 }) 370 })
371 })
372
373 describe('Should manipulate these videos', function () {
374 it('Should update the video 3 by asking pod 3', function (done) {
375 this.timeout(15000)
376
377 const name = 'my super video updated'
378 const description = 'my super description updated'
379 const tags = [ 'tagup1', 'tagup2' ]
380
381 videosUtils.updateVideo(servers[2].url, servers[2].accessToken, toRemove[0].id, name, description, tags, function (err) {
382 if (err) throw err
383
384 setTimeout(done, 11000)
385 })
386 })
387
388 it('Should have the video 3 updated on each pod', function (done) {
389 each(servers, function (server, callback) {
390 videosUtils.getVideosList(server.url, function (err, res) {
391 if (err) throw err
392
393 const videos = res.body.data
394 const videoUpdated = videos.find(function (video) {
395 return video.name === 'my super video updated'
396 })
397
398 expect(!!videoUpdated).to.be.true
399 expect(videoUpdated.description).to.equal('my super description updated')
400 expect(videoUpdated.tags).to.deep.equal([ 'tagup1', 'tagup2' ])
401
402 callback()
403 })
404 }, done)
405 })
371 406
372 it('Should remove the file 3 and 3-2 by asking pod 3', function (done) { 407 it('Should remove the videos 3 and 3-2 by asking pod 3', function (done) {
373 this.timeout(15000) 408 this.timeout(15000)
374 409
375 series([ 410 series([
376 function (next) { 411 function (next) {
377 videosUtils.removeVideo(servers[2].url, servers[2].accessToken, toRemove[0], next) 412 videosUtils.removeVideo(servers[2].url, servers[2].accessToken, toRemove[0].id, next)
378 }, 413 },
379 function (next) { 414 function (next) {
380 videosUtils.removeVideo(servers[2].url, servers[2].accessToken, toRemove[1], next) 415 videosUtils.removeVideo(servers[2].url, servers[2].accessToken, toRemove[1].id, next)
381 }], 416 }],
382 function (err) { 417 function (err) {
383 if (err) throw err 418 if (err) throw err
@@ -394,11 +429,11 @@ describe('Test multiple pods', function () {
394 const videos = res.body.data 429 const videos = res.body.data
395 expect(videos).to.be.an('array') 430 expect(videos).to.be.an('array')
396 expect(videos.length).to.equal(2) 431 expect(videos.length).to.equal(2)
397 expect(videos[0].id).not.to.equal(videos[1].id) 432 expect(videos[0].name).not.to.equal(videos[1].name)
398 expect(videos[0].id).not.to.equal(toRemove[0]) 433 expect(videos[0].name).not.to.equal(toRemove[0].name)
399 expect(videos[1].id).not.to.equal(toRemove[0]) 434 expect(videos[1].name).not.to.equal(toRemove[0].name)
400 expect(videos[0].id).not.to.equal(toRemove[1]) 435 expect(videos[0].name).not.to.equal(toRemove[1].name)
401 expect(videos[1].id).not.to.equal(toRemove[1]) 436 expect(videos[1].name).not.to.equal(toRemove[1].name)
402 437
403 callback() 438 callback()
404 }) 439 })