function remoteVideos (req, res, next) {
const requests = req.body.data
- const fromHost = req.body.signature.host
+ const fromPod = res.locals.secure.pod
// We need to process in the same order to keep consistency
// TODO: optimization
eachSeries(requests, function (request, callbackEach) {
const videoData = request.data
- if (request.type === 'add') {
- addRemoteVideo(videoData, fromHost, callbackEach)
- } else if (request.type === 'remove') {
- removeRemoteVideo(videoData, fromHost, callbackEach)
- } else {
- logger.error('Unkown remote request type %s.', request.type)
+ switch (request.type) {
+ case 'add':
+ addRemoteVideo(videoData, fromPod, callbackEach)
+ break
+
+ case 'update':
+ updateRemoteVideo(videoData, fromPod, callbackEach)
+ break
+
+ case 'remove':
+ removeRemoteVideo(videoData, fromPod, callbackEach)
+ break
+
+ default:
+ logger.error('Unkown remote request type %s.', request.type)
}
}, function (err) {
if (err) logger.error('Error managing remote videos.', { error: err })
return res.type('json').status(204).end()
}
-function addRemoteVideo (videoToCreateData, fromHost, callback) {
+function addRemoteVideo (videoToCreateData, fromPod, finalCallback) {
logger.debug('Adding remote video "%s".', videoToCreateData.name)
waterfall([
- function findOrCreatePod (callback) {
- fromHost
+ function startTransaction (callback) {
+ db.sequelize.transaction().asCallback(function (err, t) {
+ return callback(err, t)
+ })
+ },
- const query = {
- where: {
- host: fromHost
- },
- defaults: {
- host: fromHost
- }
- }
+ function findOrCreateAuthor (t, callback) {
+ const name = videoToCreateData.author
+ const podId = fromPod.id
+ // This author is from another pod so we do not associate a user
+ const userId = null
- db.Pod.findOrCreate(query).asCallback(function (err, result) {
- // [ instance, wasCreated ]
- return callback(err, result[0])
+ db.Author.findOrCreateAuthor(name, podId, userId, t, function (err, authorInstance) {
+ return callback(err, t, authorInstance)
})
},
- function findOrCreateAuthor (pod, callback) {
- const username = videoToCreateData.author
-
- const query = {
- where: {
- name: username,
- podId: pod.id
- },
- defaults: {
- name: username,
- podId: pod.id
- }
- }
+ function findOrCreateTags (t, author, callback) {
+ const tags = videoToCreateData.tags
- db.Author.findOrCreate(query).asCallback(function (err, result) {
- // [ instance, wasCreated ]
- return callback(err, result[0])
+ db.Tag.findOrCreateTags(tags, t, function (err, tagInstances) {
+ return callback(err, t, author, tagInstances)
})
},
- function createVideoObject (author, callback) {
+ function createVideoObject (t, author, tagInstances, callback) {
const videoData = {
name: videoToCreateData.name,
remoteId: videoToCreateData.remoteId,
description: videoToCreateData.description,
authorId: author.id,
duration: videoToCreateData.duration,
- tags: videoToCreateData.tags
+ createdAt: videoToCreateData.createdAt,
+ updatedAt: videoToCreateData.updatedAt
}
const video = db.Video.build(videoData)
- return callback(null, video)
+ return callback(null, t, tagInstances, video)
},
- function generateThumbnail (video, callback) {
- db.Video.generateThumbnailFromBase64(video, videoToCreateData.thumbnailBase64, function (err) {
+ function generateThumbnail (t, tagInstances, video, callback) {
+ db.Video.generateThumbnailFromData(video, videoToCreateData.thumbnailData, function (err) {
if (err) {
- logger.error('Cannot generate thumbnail from base 64 data.', { error: err })
+ logger.error('Cannot generate thumbnail from data.', { error: err })
return callback(err)
}
- video.save().asCallback(callback)
+ return callback(err, t, tagInstances, video)
+ })
+ },
+
+ function insertVideoIntoDB (t, tagInstances, video, callback) {
+ const options = {
+ transaction: t
+ }
+
+ video.save(options).asCallback(function (err, videoCreated) {
+ return callback(err, t, tagInstances, videoCreated)
})
},
- function insertIntoDB (video, callback) {
- video.save().asCallback(callback)
+ function associateTagsToVideo (t, tagInstances, video, callback) {
+ const options = { transaction: t }
+
+ video.setTags(tagInstances, options).asCallback(function (err) {
+ return callback(err, t)
+ })
+ }
+
+ ], function (err, t) {
+ if (err) {
+ logger.error('Cannot insert the remote video.')
+
+ // Abort transaction?
+ if (t) t.rollback()
+
+ return finalCallback(err)
}
- ], callback)
+ // Commit transaction
+ t.commit()
+
+ return finalCallback()
+ })
}
-function removeRemoteVideo (videoToRemoveData, fromHost, callback) {
- // TODO: use bulkDestroy?
+function updateRemoteVideo (videoAttributesToUpdate, fromPod, finalCallback) {
+ logger.debug('Updating remote video "%s".', videoAttributesToUpdate.name)
- // We need the list because we have to remove some other stuffs (thumbnail etc)
- db.Video.listByHostAndRemoteId(fromHost, videoToRemoveData.remoteId, function (err, videosList) {
- if (err) {
- logger.error('Cannot list videos from host and remote id.', { error: err.message })
- return callback(err)
+ waterfall([
+
+ function startTransaction (callback) {
+ db.sequelize.transaction().asCallback(function (err, t) {
+ return callback(err, t)
+ })
+ },
+
+ function findVideo (t, callback) {
+ db.Video.loadByHostAndRemoteId(fromPod.host, videoAttributesToUpdate.remoteId, function (err, videoInstance) {
+ if (err || !videoInstance) {
+ logger.error('Cannot load video from host and remote id.', { error: err.message })
+ return callback(err)
+ }
+
+ return callback(null, t, videoInstance)
+ })
+ },
+
+ function findOrCreateTags (t, videoInstance, callback) {
+ const tags = videoAttributesToUpdate.tags
+
+ db.Tag.findOrCreateTags(tags, t, function (err, tagInstances) {
+ return callback(err, t, videoInstance, tagInstances)
+ })
+ },
+
+ function updateVideoIntoDB (t, videoInstance, tagInstances, callback) {
+ const options = { transaction: t }
+
+ videoInstance.set('name', videoAttributesToUpdate.name)
+ videoInstance.set('description', videoAttributesToUpdate.description)
+ videoInstance.set('infoHash', videoAttributesToUpdate.infoHash)
+ videoInstance.set('duration', videoAttributesToUpdate.duration)
+ videoInstance.set('createdAt', videoAttributesToUpdate.createdAt)
+ videoInstance.set('updatedAt', videoAttributesToUpdate.updatedAt)
+ videoInstance.set('extname', videoAttributesToUpdate.extname)
+
+ videoInstance.save(options).asCallback(function (err) {
+ return callback(err, t, videoInstance, tagInstances)
+ })
+ },
+
+ function associateTagsToVideo (t, videoInstance, tagInstances, callback) {
+ const options = { transaction: t }
+
+ videoInstance.setTags(tagInstances, options).asCallback(function (err) {
+ return callback(err, t)
+ })
}
- if (videosList.length === 0) {
- logger.error('No remote video was found for this pod.', { remoteId: videoToRemoveData.remoteId, podHost: fromHost })
+ ], function (err, t) {
+ if (err) {
+ logger.error('Cannot update the remote video.')
+
+ // Abort transaction?
+ if (t) t.rollback()
+
+ return finalCallback(err)
}
- each(videosList, function (video, callbackEach) {
- logger.debug('Removing remote video %s.', video.remoteId)
+ // Commit transaction
+ t.commit()
+
+ return finalCallback()
+ })
+}
+
+function removeRemoteVideo (videoToRemoveData, fromPod, callback) {
+ // We need the instance because we have to remove some other stuffs (thumbnail etc)
+ db.Video.loadByHostAndRemoteId(fromPod.host, videoToRemoveData.remoteId, function (err, video) {
+ if (err || !video) {
+ logger.error('Cannot load video from host and remote id.', { error: err.message })
+ return callback(err)
+ }
- video.destroy().asCallback(callbackEach)
- }, callback)
+ logger.debug('Removing remote video %s.', video.remoteId)
+ video.destroy().asCallback(callback)
})
}