aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/controllers/api
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2018-06-13 14:27:40 +0200
committerChocobozzz <me@florianbigard.com>2018-06-13 14:27:40 +0200
commit90d4bb8125e80c8060416d4d135ddeaf0a622ede (patch)
treeb3b7181329a08ecc930b54fe7b48095c4155393c /server/controllers/api
parent3cd0734fd9b0ff21aaef02317a874e8f1c06e027 (diff)
downloadPeerTube-90d4bb8125e80c8060416d4d135ddeaf0a622ede.tar.gz
PeerTube-90d4bb8125e80c8060416d4d135ddeaf0a622ede.tar.zst
PeerTube-90d4bb8125e80c8060416d4d135ddeaf0a622ede.zip
Refractor retry transaction function
Diffstat (limited to 'server/controllers/api')
-rw-r--r--server/controllers/api/users.ts52
-rw-r--r--server/controllers/api/video-channel.ts55
-rw-r--r--server/controllers/api/videos/abuse.ts25
-rw-r--r--server/controllers/api/videos/comment.ts68
-rw-r--r--server/controllers/api/videos/index.ts62
-rw-r--r--server/controllers/api/videos/rate.ts18
6 files changed, 84 insertions, 196 deletions
diff --git a/server/controllers/api/users.ts b/server/controllers/api/users.ts
index 2b40c44d9..0aeb77964 100644
--- a/server/controllers/api/users.ts
+++ b/server/controllers/api/users.ts
@@ -4,7 +4,6 @@ import { extname, join } from 'path'
4import * as uuidv4 from 'uuid/v4' 4import * as uuidv4 from 'uuid/v4'
5import * as RateLimit from 'express-rate-limit' 5import * as RateLimit from 'express-rate-limit'
6import { UserCreate, UserRight, UserRole, UserUpdate, UserUpdateMe, UserVideoRate as FormattedUserVideoRate } from '../../../shared' 6import { UserCreate, UserRight, UserRole, UserUpdate, UserUpdateMe, UserVideoRate as FormattedUserVideoRate } from '../../../shared'
7import { retryTransactionWrapper } from '../../helpers/database-utils'
8import { processImage } from '../../helpers/image-utils' 7import { processImage } from '../../helpers/image-utils'
9import { logger } from '../../helpers/logger' 8import { logger } from '../../helpers/logger'
10import { getFormattedObjects } from '../../helpers/utils' 9import { getFormattedObjects } from '../../helpers/utils'
@@ -16,6 +15,7 @@ import { Redis } from '../../lib/redis'
16import { createUserAccountAndChannel } from '../../lib/user' 15import { createUserAccountAndChannel } from '../../lib/user'
17import { 16import {
18 asyncMiddleware, 17 asyncMiddleware,
18 asyncRetryTransactionMiddleware,
19 authenticate, 19 authenticate,
20 ensureUserHasRight, 20 ensureUserHasRight,
21 ensureUserRegistrationAllowed, 21 ensureUserRegistrationAllowed,
@@ -102,14 +102,14 @@ usersRouter.post('/',
102 authenticate, 102 authenticate,
103 ensureUserHasRight(UserRight.MANAGE_USERS), 103 ensureUserHasRight(UserRight.MANAGE_USERS),
104 asyncMiddleware(usersAddValidator), 104 asyncMiddleware(usersAddValidator),
105 asyncMiddleware(createUserRetryWrapper) 105 asyncRetryTransactionMiddleware(createUser)
106) 106)
107 107
108usersRouter.post('/register', 108usersRouter.post('/register',
109 asyncMiddleware(ensureUserRegistrationAllowed), 109 asyncMiddleware(ensureUserRegistrationAllowed),
110 ensureUserRegistrationAllowedForIP, 110 ensureUserRegistrationAllowedForIP,
111 asyncMiddleware(usersRegisterValidator), 111 asyncMiddleware(usersRegisterValidator),
112 asyncMiddleware(registerUserRetryWrapper) 112 asyncRetryTransactionMiddleware(registerUser)
113) 113)
114 114
115usersRouter.put('/me', 115usersRouter.put('/me',
@@ -178,26 +178,7 @@ async function getUserVideos (req: express.Request, res: express.Response, next:
178 return res.json(getFormattedObjects(resultList.data, resultList.total, { additionalAttributes })) 178 return res.json(getFormattedObjects(resultList.data, resultList.total, { additionalAttributes }))
179} 179}
180 180
181async function createUserRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) { 181async function createUser (req: express.Request, res: express.Response) {
182 const options = {
183 arguments: [ req ],
184 errorMessage: 'Cannot insert the user with many retries.'
185 }
186
187 const { user, account } = await retryTransactionWrapper(createUser, options)
188
189 return res.json({
190 user: {
191 id: user.id,
192 account: {
193 id: account.id,
194 uuid: account.Actor.uuid
195 }
196 }
197 }).end()
198}
199
200async function createUser (req: express.Request) {
201 const body: UserCreate = req.body 182 const body: UserCreate = req.body
202 const userToCreate = new UserModel({ 183 const userToCreate = new UserModel({
203 username: body.username, 184 username: body.username,
@@ -213,21 +194,18 @@ async function createUser (req: express.Request) {
213 194
214 logger.info('User %s with its channel and account created.', body.username) 195 logger.info('User %s with its channel and account created.', body.username)
215 196
216 return { user, account } 197 return res.json({
217} 198 user: {
218 199 id: user.id,
219async function registerUserRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) { 200 account: {
220 const options = { 201 id: account.id,
221 arguments: [ req ], 202 uuid: account.Actor.uuid
222 errorMessage: 'Cannot insert the user with many retries.' 203 }
223 } 204 }
224 205 }).end()
225 await retryTransactionWrapper(registerUser, options)
226
227 return res.type('json').status(204).end()
228} 206}
229 207
230async function registerUser (req: express.Request) { 208async function registerUser (req: express.Request, res: express.Response) {
231 const body: UserCreate = req.body 209 const body: UserCreate = req.body
232 210
233 const user = new UserModel({ 211 const user = new UserModel({
@@ -243,6 +221,8 @@ async function registerUser (req: express.Request) {
243 await createUserAccountAndChannel(user) 221 await createUserAccountAndChannel(user)
244 222
245 logger.info('User %s with its channel and account registered.', body.username) 223 logger.info('User %s with its channel and account registered.', body.username)
224
225 return res.type('json').status(204).end()
246} 226}
247 227
248async function getUserInformation (req: express.Request, res: express.Response, next: express.NextFunction) { 228async function getUserInformation (req: express.Request, res: express.Response, next: express.NextFunction) {
diff --git a/server/controllers/api/video-channel.ts b/server/controllers/api/video-channel.ts
index 263eb2a8a..61e72125f 100644
--- a/server/controllers/api/video-channel.ts
+++ b/server/controllers/api/video-channel.ts
@@ -2,6 +2,7 @@ import * as express from 'express'
2import { getFormattedObjects, resetSequelizeInstance } from '../../helpers/utils' 2import { getFormattedObjects, resetSequelizeInstance } from '../../helpers/utils'
3import { 3import {
4 asyncMiddleware, 4 asyncMiddleware,
5 asyncRetryTransactionMiddleware,
5 authenticate, 6 authenticate,
6 optionalAuthenticate, 7 optionalAuthenticate,
7 paginationValidator, 8 paginationValidator,
@@ -20,7 +21,6 @@ import { VideoChannelCreate, VideoChannelUpdate } from '../../../shared'
20import { createVideoChannel } from '../../lib/video-channel' 21import { createVideoChannel } from '../../lib/video-channel'
21import { isNSFWHidden } from '../../helpers/express-utils' 22import { isNSFWHidden } from '../../helpers/express-utils'
22import { setAsyncActorKeys } from '../../lib/activitypub' 23import { setAsyncActorKeys } from '../../lib/activitypub'
23import { retryTransactionWrapper } from '../../helpers/database-utils'
24import { AccountModel } from '../../models/account/account' 24import { AccountModel } from '../../models/account/account'
25import { sequelizeTypescript } from '../../initializers' 25import { sequelizeTypescript } from '../../initializers'
26import { logger } from '../../helpers/logger' 26import { logger } from '../../helpers/logger'
@@ -39,19 +39,19 @@ videoChannelRouter.get('/',
39videoChannelRouter.post('/', 39videoChannelRouter.post('/',
40 authenticate, 40 authenticate,
41 videoChannelsAddValidator, 41 videoChannelsAddValidator,
42 asyncMiddleware(addVideoChannelRetryWrapper) 42 asyncRetryTransactionMiddleware(addVideoChannel)
43) 43)
44 44
45videoChannelRouter.put('/:id', 45videoChannelRouter.put('/:id',
46 authenticate, 46 authenticate,
47 asyncMiddleware(videoChannelsUpdateValidator), 47 asyncMiddleware(videoChannelsUpdateValidator),
48 updateVideoChannelRetryWrapper 48 asyncRetryTransactionMiddleware(updateVideoChannel)
49) 49)
50 50
51videoChannelRouter.delete('/:id', 51videoChannelRouter.delete('/:id',
52 authenticate, 52 authenticate,
53 asyncMiddleware(videoChannelsRemoveValidator), 53 asyncMiddleware(videoChannelsRemoveValidator),
54 asyncMiddleware(removeVideoChannelRetryWrapper) 54 asyncRetryTransactionMiddleware(removeVideoChannel)
55) 55)
56 56
57videoChannelRouter.get('/:id', 57videoChannelRouter.get('/:id',
@@ -83,23 +83,6 @@ async function listVideoChannels (req: express.Request, res: express.Response, n
83 return res.json(getFormattedObjects(resultList.data, resultList.total)) 83 return res.json(getFormattedObjects(resultList.data, resultList.total))
84} 84}
85 85
86// Wrapper to video channel add that retry the async function if there is a database error
87// We need this because we run the transaction in SERIALIZABLE isolation that can fail
88async function addVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
89 const options = {
90 arguments: [ req, res ],
91 errorMessage: 'Cannot insert the video video channel with many retries.'
92 }
93
94 const videoChannel = await retryTransactionWrapper(addVideoChannel, options)
95 return res.json({
96 videoChannel: {
97 id: videoChannel.id,
98 uuid: videoChannel.Actor.uuid
99 }
100 }).end()
101}
102
103async function addVideoChannel (req: express.Request, res: express.Response) { 86async function addVideoChannel (req: express.Request, res: express.Response) {
104 const videoChannelInfo: VideoChannelCreate = req.body 87 const videoChannelInfo: VideoChannelCreate = req.body
105 const account: AccountModel = res.locals.oauth.token.User.Account 88 const account: AccountModel = res.locals.oauth.token.User.Account
@@ -113,18 +96,12 @@ async function addVideoChannel (req: express.Request, res: express.Response) {
113 96
114 logger.info('Video channel with uuid %s created.', videoChannelCreated.Actor.uuid) 97 logger.info('Video channel with uuid %s created.', videoChannelCreated.Actor.uuid)
115 98
116 return videoChannelCreated 99 return res.json({
117} 100 videoChannel: {
118 101 id: videoChannelCreated.id,
119async function updateVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) { 102 uuid: videoChannelCreated.Actor.uuid
120 const options = { 103 }
121 arguments: [ req, res ], 104 }).end()
122 errorMessage: 'Cannot update the video with many retries.'
123 }
124
125 await retryTransactionWrapper(updateVideoChannel, options)
126
127 return res.type('json').status(204).end()
128} 105}
129 106
130async function updateVideoChannel (req: express.Request, res: express.Response) { 107async function updateVideoChannel (req: express.Request, res: express.Response) {
@@ -157,15 +134,6 @@ async function updateVideoChannel (req: express.Request, res: express.Response)
157 134
158 throw err 135 throw err
159 } 136 }
160}
161
162async function removeVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
163 const options = {
164 arguments: [ req, res ],
165 errorMessage: 'Cannot remove the video channel with many retries.'
166 }
167
168 await retryTransactionWrapper(removeVideoChannel, options)
169 137
170 return res.type('json').status(204).end() 138 return res.type('json').status(204).end()
171} 139}
@@ -173,12 +141,13 @@ async function removeVideoChannelRetryWrapper (req: express.Request, res: expres
173async function removeVideoChannel (req: express.Request, res: express.Response) { 141async function removeVideoChannel (req: express.Request, res: express.Response) {
174 const videoChannelInstance: VideoChannelModel = res.locals.videoChannel 142 const videoChannelInstance: VideoChannelModel = res.locals.videoChannel
175 143
176 return sequelizeTypescript.transaction(async t => { 144 await sequelizeTypescript.transaction(async t => {
177 await videoChannelInstance.destroy({ transaction: t }) 145 await videoChannelInstance.destroy({ transaction: t })
178 146
179 logger.info('Video channel with name %s and uuid %s deleted.', videoChannelInstance.name, videoChannelInstance.Actor.uuid) 147 logger.info('Video channel with name %s and uuid %s deleted.', videoChannelInstance.name, videoChannelInstance.Actor.uuid)
180 }) 148 })
181 149
150 return res.type('json').status(204).end()
182} 151}
183 152
184async function getVideoChannel (req: express.Request, res: express.Response, next: express.NextFunction) { 153async function getVideoChannel (req: express.Request, res: express.Response, next: express.NextFunction) {
diff --git a/server/controllers/api/videos/abuse.ts b/server/controllers/api/videos/abuse.ts
index 61ff3af4f..3413ae894 100644
--- a/server/controllers/api/videos/abuse.ts
+++ b/server/controllers/api/videos/abuse.ts
@@ -1,12 +1,18 @@
1import * as express from 'express' 1import * as express from 'express'
2import { UserRight, VideoAbuseCreate } from '../../../../shared' 2import { UserRight, VideoAbuseCreate } from '../../../../shared'
3import { retryTransactionWrapper } from '../../../helpers/database-utils'
4import { logger } from '../../../helpers/logger' 3import { logger } from '../../../helpers/logger'
5import { getFormattedObjects } from '../../../helpers/utils' 4import { getFormattedObjects } from '../../../helpers/utils'
6import { sequelizeTypescript } from '../../../initializers' 5import { sequelizeTypescript } from '../../../initializers'
7import { sendVideoAbuse } from '../../../lib/activitypub/send' 6import { sendVideoAbuse } from '../../../lib/activitypub/send'
8import { 7import {
9 asyncMiddleware, authenticate, ensureUserHasRight, paginationValidator, setDefaultSort, setDefaultPagination, videoAbuseReportValidator, 8 asyncMiddleware,
9 asyncRetryTransactionMiddleware,
10 authenticate,
11 ensureUserHasRight,
12 paginationValidator,
13 setDefaultPagination,
14 setDefaultSort,
15 videoAbuseReportValidator,
10 videoAbusesSortValidator 16 videoAbusesSortValidator
11} from '../../../middlewares' 17} from '../../../middlewares'
12import { AccountModel } from '../../../models/account/account' 18import { AccountModel } from '../../../models/account/account'
@@ -27,7 +33,7 @@ abuseVideoRouter.get('/abuse',
27abuseVideoRouter.post('/:id/abuse', 33abuseVideoRouter.post('/:id/abuse',
28 authenticate, 34 authenticate,
29 asyncMiddleware(videoAbuseReportValidator), 35 asyncMiddleware(videoAbuseReportValidator),
30 asyncMiddleware(reportVideoAbuseRetryWrapper) 36 asyncRetryTransactionMiddleware(reportVideoAbuse)
31) 37)
32 38
33// --------------------------------------------------------------------------- 39// ---------------------------------------------------------------------------
@@ -44,17 +50,6 @@ async function listVideoAbuses (req: express.Request, res: express.Response, nex
44 return res.json(getFormattedObjects(resultList.data, resultList.total)) 50 return res.json(getFormattedObjects(resultList.data, resultList.total))
45} 51}
46 52
47async function reportVideoAbuseRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
48 const options = {
49 arguments: [ req, res ],
50 errorMessage: 'Cannot report abuse to the video with many retries.'
51 }
52
53 await retryTransactionWrapper(reportVideoAbuse, options)
54
55 return res.type('json').status(204).end()
56}
57
58async function reportVideoAbuse (req: express.Request, res: express.Response) { 53async function reportVideoAbuse (req: express.Request, res: express.Response) {
59 const videoInstance = res.locals.video as VideoModel 54 const videoInstance = res.locals.video as VideoModel
60 const reporterAccount = res.locals.oauth.token.User.Account as AccountModel 55 const reporterAccount = res.locals.oauth.token.User.Account as AccountModel
@@ -77,4 +72,6 @@ async function reportVideoAbuse (req: express.Request, res: express.Response) {
77 }) 72 })
78 73
79 logger.info('Abuse report for video %s created.', videoInstance.name) 74 logger.info('Abuse report for video %s created.', videoInstance.name)
75
76 return res.type('json').status(204).end()
80} 77}
diff --git a/server/controllers/api/videos/comment.ts b/server/controllers/api/videos/comment.ts
index f8a669e35..bbeb0d557 100644
--- a/server/controllers/api/videos/comment.ts
+++ b/server/controllers/api/videos/comment.ts
@@ -1,15 +1,24 @@
1import * as express from 'express' 1import * as express from 'express'
2import { ResultList } from '../../../../shared/models' 2import { ResultList } from '../../../../shared/models'
3import { VideoCommentCreate } from '../../../../shared/models/videos/video-comment.model' 3import { VideoCommentCreate } from '../../../../shared/models/videos/video-comment.model'
4import { retryTransactionWrapper } from '../../../helpers/database-utils'
5import { logger } from '../../../helpers/logger' 4import { logger } from '../../../helpers/logger'
6import { getFormattedObjects } from '../../../helpers/utils' 5import { getFormattedObjects } from '../../../helpers/utils'
7import { sequelizeTypescript } from '../../../initializers' 6import { sequelizeTypescript } from '../../../initializers'
8import { buildFormattedCommentTree, createVideoComment } from '../../../lib/video-comment' 7import { buildFormattedCommentTree, createVideoComment } from '../../../lib/video-comment'
9import { asyncMiddleware, authenticate, paginationValidator, setDefaultSort, setDefaultPagination } from '../../../middlewares' 8import {
9 asyncMiddleware,
10 asyncRetryTransactionMiddleware,
11 authenticate,
12 paginationValidator,
13 setDefaultPagination,
14 setDefaultSort
15} from '../../../middlewares'
10import { videoCommentThreadsSortValidator } from '../../../middlewares/validators' 16import { videoCommentThreadsSortValidator } from '../../../middlewares/validators'
11import { 17import {
12 addVideoCommentReplyValidator, addVideoCommentThreadValidator, listVideoCommentThreadsValidator, listVideoThreadCommentsValidator, 18 addVideoCommentReplyValidator,
19 addVideoCommentThreadValidator,
20 listVideoCommentThreadsValidator,
21 listVideoThreadCommentsValidator,
13 removeVideoCommentValidator 22 removeVideoCommentValidator
14} from '../../../middlewares/validators/video-comments' 23} from '../../../middlewares/validators/video-comments'
15import { VideoModel } from '../../../models/video/video' 24import { VideoModel } from '../../../models/video/video'
@@ -33,17 +42,17 @@ videoCommentRouter.get('/:videoId/comment-threads/:threadId',
33videoCommentRouter.post('/:videoId/comment-threads', 42videoCommentRouter.post('/:videoId/comment-threads',
34 authenticate, 43 authenticate,
35 asyncMiddleware(addVideoCommentThreadValidator), 44 asyncMiddleware(addVideoCommentThreadValidator),
36 asyncMiddleware(addVideoCommentThreadRetryWrapper) 45 asyncRetryTransactionMiddleware(addVideoCommentThread)
37) 46)
38videoCommentRouter.post('/:videoId/comments/:commentId', 47videoCommentRouter.post('/:videoId/comments/:commentId',
39 authenticate, 48 authenticate,
40 asyncMiddleware(addVideoCommentReplyValidator), 49 asyncMiddleware(addVideoCommentReplyValidator),
41 asyncMiddleware(addVideoCommentReplyRetryWrapper) 50 asyncRetryTransactionMiddleware(addVideoCommentReply)
42) 51)
43videoCommentRouter.delete('/:videoId/comments/:commentId', 52videoCommentRouter.delete('/:videoId/comments/:commentId',
44 authenticate, 53 authenticate,
45 asyncMiddleware(removeVideoCommentValidator), 54 asyncMiddleware(removeVideoCommentValidator),
46 asyncMiddleware(removeVideoCommentRetryWrapper) 55 asyncRetryTransactionMiddleware(removeVideoComment)
47) 56)
48 57
49// --------------------------------------------------------------------------- 58// ---------------------------------------------------------------------------
@@ -86,23 +95,10 @@ async function listVideoThreadComments (req: express.Request, res: express.Respo
86 return res.json(buildFormattedCommentTree(resultList)) 95 return res.json(buildFormattedCommentTree(resultList))
87} 96}
88 97
89async function addVideoCommentThreadRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) { 98async function addVideoCommentThread (req: express.Request, res: express.Response) {
90 const options = {
91 arguments: [ req, res ],
92 errorMessage: 'Cannot insert the video comment thread with many retries.'
93 }
94
95 const comment = await retryTransactionWrapper(addVideoCommentThread, options)
96
97 res.json({
98 comment: comment.toFormattedJSON()
99 }).end()
100}
101
102function addVideoCommentThread (req: express.Request, res: express.Response) {
103 const videoCommentInfo: VideoCommentCreate = req.body 99 const videoCommentInfo: VideoCommentCreate = req.body
104 100
105 return sequelizeTypescript.transaction(async t => { 101 const comment = await sequelizeTypescript.transaction(async t => {
106 return createVideoComment({ 102 return createVideoComment({
107 text: videoCommentInfo.text, 103 text: videoCommentInfo.text,
108 inReplyToComment: null, 104 inReplyToComment: null,
@@ -110,25 +106,16 @@ function addVideoCommentThread (req: express.Request, res: express.Response) {
110 account: res.locals.oauth.token.User.Account 106 account: res.locals.oauth.token.User.Account
111 }, t) 107 }, t)
112 }) 108 })
113}
114 109
115async function addVideoCommentReplyRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) { 110 return res.json({
116 const options = {
117 arguments: [ req, res ],
118 errorMessage: 'Cannot insert the video comment reply with many retries.'
119 }
120
121 const comment = await retryTransactionWrapper(addVideoCommentReply, options)
122
123 res.json({
124 comment: comment.toFormattedJSON() 111 comment: comment.toFormattedJSON()
125 }).end() 112 }).end()
126} 113}
127 114
128function addVideoCommentReply (req: express.Request, res: express.Response, next: express.NextFunction) { 115async function addVideoCommentReply (req: express.Request, res: express.Response) {
129 const videoCommentInfo: VideoCommentCreate = req.body 116 const videoCommentInfo: VideoCommentCreate = req.body
130 117
131 return sequelizeTypescript.transaction(async t => { 118 const comment = await sequelizeTypescript.transaction(async t => {
132 return createVideoComment({ 119 return createVideoComment({
133 text: videoCommentInfo.text, 120 text: videoCommentInfo.text,
134 inReplyToComment: res.locals.videoComment, 121 inReplyToComment: res.locals.videoComment,
@@ -136,17 +123,10 @@ function addVideoCommentReply (req: express.Request, res: express.Response, next
136 account: res.locals.oauth.token.User.Account 123 account: res.locals.oauth.token.User.Account
137 }, t) 124 }, t)
138 }) 125 })
139}
140
141async function removeVideoCommentRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
142 const options = {
143 arguments: [ req, res ],
144 errorMessage: 'Cannot remove the video comment with many retries.'
145 }
146 126
147 await retryTransactionWrapper(removeVideoComment, options) 127 return res.json({
148 128 comment: comment.toFormattedJSON()
149 return res.type('json').status(204).end() 129 }).end()
150} 130}
151 131
152async function removeVideoComment (req: express.Request, res: express.Response) { 132async function removeVideoComment (req: express.Request, res: express.Response) {
@@ -157,4 +137,6 @@ async function removeVideoComment (req: express.Request, res: express.Response)
157 }) 137 })
158 138
159 logger.info('Video comment %d deleted.', videoCommentInstance.id) 139 logger.info('Video comment %d deleted.', videoCommentInstance.id)
140
141 return res.type('json').status(204).end()
160} 142}
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts
index 9d9b2b0e1..78963d89b 100644
--- a/server/controllers/api/videos/index.ts
+++ b/server/controllers/api/videos/index.ts
@@ -2,7 +2,6 @@ import * as express from 'express'
2import { extname, join } from 'path' 2import { extname, join } from 'path'
3import { VideoCreate, VideoPrivacy, VideoState, VideoUpdate } from '../../../../shared' 3import { VideoCreate, VideoPrivacy, VideoState, VideoUpdate } from '../../../../shared'
4import { renamePromise } from '../../../helpers/core-utils' 4import { renamePromise } from '../../../helpers/core-utils'
5import { retryTransactionWrapper } from '../../../helpers/database-utils'
6import { getVideoFileResolution } from '../../../helpers/ffmpeg-utils' 5import { getVideoFileResolution } from '../../../helpers/ffmpeg-utils'
7import { processImage } from '../../../helpers/image-utils' 6import { processImage } from '../../../helpers/image-utils'
8import { logger } from '../../../helpers/logger' 7import { logger } from '../../../helpers/logger'
@@ -30,6 +29,7 @@ import { JobQueue } from '../../../lib/job-queue'
30import { Redis } from '../../../lib/redis' 29import { Redis } from '../../../lib/redis'
31import { 30import {
32 asyncMiddleware, 31 asyncMiddleware,
32 asyncRetryTransactionMiddleware,
33 authenticate, 33 authenticate,
34 optionalAuthenticate, 34 optionalAuthenticate,
35 paginationValidator, 35 paginationValidator,
@@ -104,13 +104,13 @@ videosRouter.put('/:id',
104 authenticate, 104 authenticate,
105 reqVideoFileUpdate, 105 reqVideoFileUpdate,
106 asyncMiddleware(videosUpdateValidator), 106 asyncMiddleware(videosUpdateValidator),
107 asyncMiddleware(updateVideoRetryWrapper) 107 asyncRetryTransactionMiddleware(updateVideo)
108) 108)
109videosRouter.post('/upload', 109videosRouter.post('/upload',
110 authenticate, 110 authenticate,
111 reqVideoFileAdd, 111 reqVideoFileAdd,
112 asyncMiddleware(videosAddValidator), 112 asyncMiddleware(videosAddValidator),
113 asyncMiddleware(addVideoRetryWrapper) 113 asyncRetryTransactionMiddleware(addVideo)
114) 114)
115 115
116videosRouter.get('/:id/description', 116videosRouter.get('/:id/description',
@@ -129,7 +129,7 @@ videosRouter.post('/:id/views',
129videosRouter.delete('/:id', 129videosRouter.delete('/:id',
130 authenticate, 130 authenticate,
131 asyncMiddleware(videosRemoveValidator), 131 asyncMiddleware(videosRemoveValidator),
132 asyncMiddleware(removeVideoRetryWrapper) 132 asyncRetryTransactionMiddleware(removeVideo)
133) 133)
134 134
135// --------------------------------------------------------------------------- 135// ---------------------------------------------------------------------------
@@ -156,25 +156,8 @@ function listVideoPrivacies (req: express.Request, res: express.Response) {
156 res.json(VIDEO_PRIVACIES) 156 res.json(VIDEO_PRIVACIES)
157} 157}
158 158
159// Wrapper to video add that retry the function if there is a database error 159async function addVideo (req: express.Request, res: express.Response) {
160// We need this because we run the transaction in SERIALIZABLE isolation that can fail 160 const videoPhysicalFile = req.files['videofile'][0]
161async function addVideoRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
162 const options = {
163 arguments: [ req, res, req.files['videofile'][0] ],
164 errorMessage: 'Cannot insert the video with many retries.'
165 }
166
167 const video = await retryTransactionWrapper(addVideo, options)
168
169 res.json({
170 video: {
171 id: video.id,
172 uuid: video.uuid
173 }
174 }).end()
175}
176
177async function addVideo (req: express.Request, res: express.Response, videoPhysicalFile: Express.Multer.File) {
178 const videoInfo: VideoCreate = req.body 161 const videoInfo: VideoCreate = req.body
179 162
180 // Prepare data so we don't block the transaction 163 // Prepare data so we don't block the transaction
@@ -272,18 +255,12 @@ async function addVideo (req: express.Request, res: express.Response, videoPhysi
272 await JobQueue.Instance.createJob({ type: 'video-file', payload: dataInput }) 255 await JobQueue.Instance.createJob({ type: 'video-file', payload: dataInput })
273 } 256 }
274 257
275 return videoCreated 258 return res.json({
276} 259 video: {
277 260 id: videoCreated.id,
278async function updateVideoRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) { 261 uuid: videoCreated.uuid
279 const options = { 262 }
280 arguments: [ req, res ], 263 }).end()
281 errorMessage: 'Cannot update the video with many retries.'
282 }
283
284 await retryTransactionWrapper(updateVideo, options)
285
286 return res.type('json').status(204).end()
287} 264}
288 265
289async function updateVideo (req: express.Request, res: express.Response) { 266async function updateVideo (req: express.Request, res: express.Response) {
@@ -360,6 +337,8 @@ async function updateVideo (req: express.Request, res: express.Response) {
360 337
361 throw err 338 throw err
362 } 339 }
340
341 return res.type('json').status(204).end()
363} 342}
364 343
365function getVideo (req: express.Request, res: express.Response) { 344function getVideo (req: express.Request, res: express.Response) {
@@ -414,17 +393,6 @@ async function listVideos (req: express.Request, res: express.Response, next: ex
414 return res.json(getFormattedObjects(resultList.data, resultList.total)) 393 return res.json(getFormattedObjects(resultList.data, resultList.total))
415} 394}
416 395
417async function removeVideoRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
418 const options = {
419 arguments: [ req, res ],
420 errorMessage: 'Cannot remove the video with many retries.'
421 }
422
423 await retryTransactionWrapper(removeVideo, options)
424
425 return res.type('json').status(204).end()
426}
427
428async function removeVideo (req: express.Request, res: express.Response) { 396async function removeVideo (req: express.Request, res: express.Response) {
429 const videoInstance: VideoModel = res.locals.video 397 const videoInstance: VideoModel = res.locals.video
430 398
@@ -433,6 +401,8 @@ async function removeVideo (req: express.Request, res: express.Response) {
433 }) 401 })
434 402
435 logger.info('Video with name %s and uuid %s deleted.', videoInstance.name, videoInstance.uuid) 403 logger.info('Video with name %s and uuid %s deleted.', videoInstance.name, videoInstance.uuid)
404
405 return res.type('json').status(204).end()
436} 406}
437 407
438async function searchVideos (req: express.Request, res: express.Response, next: express.NextFunction) { 408async function searchVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
diff --git a/server/controllers/api/videos/rate.ts b/server/controllers/api/videos/rate.ts
index 23e9de9f3..9d63b5821 100644
--- a/server/controllers/api/videos/rate.ts
+++ b/server/controllers/api/videos/rate.ts
@@ -1,10 +1,9 @@
1import * as express from 'express' 1import * as express from 'express'
2import { UserVideoRateUpdate } from '../../../../shared' 2import { UserVideoRateUpdate } from '../../../../shared'
3import { retryTransactionWrapper } from '../../../helpers/database-utils'
4import { logger } from '../../../helpers/logger' 3import { logger } from '../../../helpers/logger'
5import { sequelizeTypescript, VIDEO_RATE_TYPES } from '../../../initializers' 4import { sequelizeTypescript, VIDEO_RATE_TYPES } from '../../../initializers'
6import { sendVideoRateChange } from '../../../lib/activitypub' 5import { sendVideoRateChange } from '../../../lib/activitypub'
7import { asyncMiddleware, authenticate, videoRateValidator } from '../../../middlewares' 6import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, videoRateValidator } from '../../../middlewares'
8import { AccountModel } from '../../../models/account/account' 7import { AccountModel } from '../../../models/account/account'
9import { AccountVideoRateModel } from '../../../models/account/account-video-rate' 8import { AccountVideoRateModel } from '../../../models/account/account-video-rate'
10import { VideoModel } from '../../../models/video/video' 9import { VideoModel } from '../../../models/video/video'
@@ -14,7 +13,7 @@ const rateVideoRouter = express.Router()
14rateVideoRouter.put('/:id/rate', 13rateVideoRouter.put('/:id/rate',
15 authenticate, 14 authenticate,
16 asyncMiddleware(videoRateValidator), 15 asyncMiddleware(videoRateValidator),
17 asyncMiddleware(rateVideoRetryWrapper) 16 asyncRetryTransactionMiddleware(rateVideo)
18) 17)
19 18
20// --------------------------------------------------------------------------- 19// ---------------------------------------------------------------------------
@@ -25,17 +24,6 @@ export {
25 24
26// --------------------------------------------------------------------------- 25// ---------------------------------------------------------------------------
27 26
28async function rateVideoRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
29 const options = {
30 arguments: [ req, res ],
31 errorMessage: 'Cannot update the user video rate.'
32 }
33
34 await retryTransactionWrapper(rateVideo, options)
35
36 return res.type('json').status(204).end()
37}
38
39async function rateVideo (req: express.Request, res: express.Response) { 27async function rateVideo (req: express.Request, res: express.Response) {
40 const body: UserVideoRateUpdate = req.body 28 const body: UserVideoRateUpdate = req.body
41 const rateType = body.rating 29 const rateType = body.rating
@@ -87,4 +75,6 @@ async function rateVideo (req: express.Request, res: express.Response) {
87 }) 75 })
88 76
89 logger.info('Account video rate for video %s of account %s updated.', videoInstance.name, accountInstance.name) 77 logger.info('Account video rate for video %s of account %s updated.', videoInstance.name, accountInstance.name)
78
79 return res.type('json').status(204).end()
90} 80}