diff options
author | Chocobozzz <florian.bigard@gmail.com> | 2017-09-12 14:17:46 +0200 |
---|---|---|
committer | Chocobozzz <florian.bigard@gmail.com> | 2017-09-12 14:17:46 +0200 |
commit | 91f6f169b1110eeae6ebf5c387f4204b0d07703c (patch) | |
tree | cba01c954c311b8b5296222994a64da58c17789e | |
parent | 6d33593a0829a7f041127d50d4c455456550a47f (diff) | |
download | PeerTube-91f6f169b1110eeae6ebf5c387f4204b0d07703c.tar.gz PeerTube-91f6f169b1110eeae6ebf5c387f4204b0d07703c.tar.zst PeerTube-91f6f169b1110eeae6ebf5c387f4204b0d07703c.zip |
Fix concurrency error when deleting a video
-rw-r--r-- | server/controllers/api/videos/index.ts | 36 | ||||
-rw-r--r-- | server/lib/friends.ts | 4 | ||||
-rw-r--r-- | server/models/video/video.ts | 6 |
3 files changed, 30 insertions, 16 deletions
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts index 7a9cd9d37..6fa84c801 100644 --- a/server/controllers/api/videos/index.ts +++ b/server/controllers/api/videos/index.ts | |||
@@ -45,6 +45,7 @@ import { VideoCreate, VideoUpdate } from '../../../../shared' | |||
45 | import { abuseVideoRouter } from './abuse' | 45 | import { abuseVideoRouter } from './abuse' |
46 | import { blacklistRouter } from './blacklist' | 46 | import { blacklistRouter } from './blacklist' |
47 | import { rateVideoRouter } from './rate' | 47 | import { rateVideoRouter } from './rate' |
48 | import { VideoInstance } from '../../../models/video/video-interface' | ||
48 | 49 | ||
49 | const videosRouter = express.Router() | 50 | const videosRouter = express.Router() |
50 | 51 | ||
@@ -106,7 +107,7 @@ videosRouter.get('/:id', | |||
106 | videosRouter.delete('/:id', | 107 | videosRouter.delete('/:id', |
107 | authenticate, | 108 | authenticate, |
108 | videosRemoveValidator, | 109 | videosRemoveValidator, |
109 | removeVideo | 110 | removeVideoRetryWrapper |
110 | ) | 111 | ) |
111 | 112 | ||
112 | videosRouter.get('/search/:value', | 113 | videosRouter.get('/search/:value', |
@@ -291,7 +292,6 @@ function updateVideoRetryWrapper (req: express.Request, res: express.Response, n | |||
291 | 292 | ||
292 | retryTransactionWrapper(updateVideo, options) | 293 | retryTransactionWrapper(updateVideo, options) |
293 | .then(() => { | 294 | .then(() => { |
294 | // TODO : include Location of the new video -> 201 | ||
295 | return res.type('json').status(204).end() | 295 | return res.type('json').status(204).end() |
296 | }) | 296 | }) |
297 | .catch(err => next(err)) | 297 | .catch(err => next(err)) |
@@ -396,18 +396,32 @@ function listVideos (req: express.Request, res: express.Response, next: express. | |||
396 | .catch(err => next(err)) | 396 | .catch(err => next(err)) |
397 | } | 397 | } |
398 | 398 | ||
399 | function removeVideo (req: express.Request, res: express.Response, next: express.NextFunction) { | 399 | function removeVideoRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) { |
400 | const videoInstance = res.locals.video | 400 | const options = { |
401 | arguments: [ req, res ], | ||
402 | errorMessage: 'Cannot remove the video with many retries.' | ||
403 | } | ||
401 | 404 | ||
402 | videoInstance.destroy() | 405 | retryTransactionWrapper(removeVideo, options) |
403 | .then(() => { | 406 | .then(() => { |
404 | logger.info('Video with name %s and uuid %s deleted.', videoInstance.name, videoInstance.uuid) | 407 | return res.type('json').status(204).end() |
405 | res.type('json').status(204).end() | ||
406 | }) | ||
407 | .catch(err => { | ||
408 | logger.error('Errors when removed the video.', err) | ||
409 | return next(err) | ||
410 | }) | 408 | }) |
409 | .catch(err => next(err)) | ||
410 | } | ||
411 | |||
412 | function removeVideo (req: express.Request, res: express.Response) { | ||
413 | const videoInstance: VideoInstance = res.locals.video | ||
414 | |||
415 | return db.sequelize.transaction(t => { | ||
416 | return videoInstance.destroy({ transaction: t }) | ||
417 | }) | ||
418 | .then(() => { | ||
419 | logger.info('Video with name %s and uuid %s deleted.', videoInstance.name, videoInstance.uuid) | ||
420 | }) | ||
421 | .catch(err => { | ||
422 | logger.error('Errors when removed the video.', err) | ||
423 | throw err | ||
424 | }) | ||
411 | } | 425 | } |
412 | 426 | ||
413 | function searchVideos (req: express.Request, res: express.Response, next: express.NextFunction) { | 427 | function searchVideos (req: express.Request, res: express.Response, next: express.NextFunction) { |
diff --git a/server/lib/friends.ts b/server/lib/friends.ts index 3f0ce3f33..ea9ddbe8d 100644 --- a/server/lib/friends.ts +++ b/server/lib/friends.ts | |||
@@ -80,12 +80,12 @@ function updateVideoToFriends (videoData: RemoteVideoUpdateData, transaction: Se | |||
80 | return createRequest(options) | 80 | return createRequest(options) |
81 | } | 81 | } |
82 | 82 | ||
83 | function removeVideoToFriends (videoParams: RemoteVideoRemoveData) { | 83 | function removeVideoToFriends (videoParams: RemoteVideoRemoveData, transaction: Sequelize.Transaction) { |
84 | const options = { | 84 | const options = { |
85 | type: ENDPOINT_ACTIONS.REMOVE, | 85 | type: ENDPOINT_ACTIONS.REMOVE, |
86 | endpoint: REQUEST_ENDPOINTS.VIDEOS, | 86 | endpoint: REQUEST_ENDPOINTS.VIDEOS, |
87 | data: videoParams, | 87 | data: videoParams, |
88 | transaction: null | 88 | transaction |
89 | } | 89 | } |
90 | return createRequest(options) | 90 | return createRequest(options) |
91 | } | 91 | } |
diff --git a/server/models/video/video.ts b/server/models/video/video.ts index 1134525f0..e011c3b4d 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts | |||
@@ -300,7 +300,7 @@ function associate (models) { | |||
300 | }) | 300 | }) |
301 | } | 301 | } |
302 | 302 | ||
303 | function afterDestroy (video: VideoInstance) { | 303 | function afterDestroy (video: VideoInstance, options: { transaction: Sequelize.Transaction }) { |
304 | const tasks = [] | 304 | const tasks = [] |
305 | 305 | ||
306 | tasks.push( | 306 | tasks.push( |
@@ -314,10 +314,10 @@ function afterDestroy (video: VideoInstance) { | |||
314 | 314 | ||
315 | tasks.push( | 315 | tasks.push( |
316 | video.removePreview(), | 316 | video.removePreview(), |
317 | removeVideoToFriends(removeVideoToFriendsParams) | 317 | removeVideoToFriends(removeVideoToFriendsParams, options.transaction) |
318 | ) | 318 | ) |
319 | 319 | ||
320 | // TODO: check files is populated | 320 | // Remove physical files and torrents |
321 | video.VideoFiles.forEach(file => { | 321 | video.VideoFiles.forEach(file => { |
322 | video.removeFile(file), | 322 | video.removeFile(file), |
323 | video.removeTorrent(file) | 323 | video.removeTorrent(file) |