aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChocobozzz <florian.bigard@gmail.com>2017-12-08 10:08:36 +0100
committerChocobozzz <florian.bigard@gmail.com>2017-12-08 10:08:36 +0100
commite11f68a3562d2468480c396f47f1bdd2a306e17a (patch)
treec773ea89b0ea4b871e0265449501477b64233b00
parentcadb46d832724ea1a17b085b992142aa32e212be (diff)
downloadPeerTube-e11f68a3562d2468480c396f47f1bdd2a306e17a.tar.gz
PeerTube-e11f68a3562d2468480c396f47f1bdd2a306e17a.tar.zst
PeerTube-e11f68a3562d2468480c396f47f1bdd2a306e17a.zip
Optimise transaction for video upload
-rw-r--r--server/controllers/api/videos/index.ts87
-rw-r--r--server/tests/api/single-server.ts13
-rw-r--r--server/tests/utils/videos.ts2
3 files changed, 49 insertions, 53 deletions
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts
index f427a25c0..0f71a7f7f 100644
--- a/server/controllers/api/videos/index.ts
+++ b/server/controllers/api/videos/index.ts
@@ -164,52 +164,54 @@ async function addVideoRetryWrapper (req: express.Request, res: express.Response
164 }).end() 164 }).end()
165} 165}
166 166
167function addVideo (req: express.Request, res: express.Response, videoPhysicalFile: Express.Multer.File) { 167async function addVideo (req: express.Request, res: express.Response, videoPhysicalFile: Express.Multer.File) {
168 const videoInfo: VideoCreate = req.body 168 const videoInfo: VideoCreate = req.body
169 169
170 return db.sequelize.transaction(async t => { 170 // Prepare data so we don't block the transaction
171 const sequelizeOptions = { transaction: t } 171 const videoData = {
172 name: videoInfo.name,
173 remote: false,
174 extname: extname(videoPhysicalFile.filename),
175 category: videoInfo.category,
176 licence: videoInfo.licence,
177 language: videoInfo.language,
178 nsfw: videoInfo.nsfw,
179 description: videoInfo.description,
180 privacy: videoInfo.privacy,
181 duration: videoPhysicalFile['duration'], // duration was added by a previous middleware
182 channelId: res.locals.videoChannel.id
183 }
184 const video = db.Video.build(videoData)
185 video.url = getVideoActivityPubUrl(video)
172 186
173 const videoData = { 187 const videoFilePath = join(CONFIG.STORAGE.VIDEOS_DIR, videoPhysicalFile.filename)
174 name: videoInfo.name, 188 const videoFileHeight = await getVideoFileHeight(videoFilePath)
175 remote: false,
176 extname: extname(videoPhysicalFile.filename),
177 category: videoInfo.category,
178 licence: videoInfo.licence,
179 language: videoInfo.language,
180 nsfw: videoInfo.nsfw,
181 description: videoInfo.description,
182 privacy: videoInfo.privacy,
183 duration: videoPhysicalFile['duration'], // duration was added by a previous middleware
184 channelId: res.locals.videoChannel.id
185 }
186 const video = db.Video.build(videoData)
187 video.url = getVideoActivityPubUrl(video)
188 189
189 const videoFilePath = join(CONFIG.STORAGE.VIDEOS_DIR, videoPhysicalFile.filename) 190 const videoFileData = {
190 const videoFileHeight = await getVideoFileHeight(videoFilePath) 191 extname: extname(videoPhysicalFile.filename),
192 resolution: videoFileHeight,
193 size: videoPhysicalFile.size
194 }
195 const videoFile = db.VideoFile.build(videoFileData)
196 const videoDir = CONFIG.STORAGE.VIDEOS_DIR
197 const source = join(videoDir, videoPhysicalFile.filename)
198 const destination = join(videoDir, video.getVideoFilename(videoFile))
191 199
192 const videoFileData = { 200 await renamePromise(source, destination)
193 extname: extname(videoPhysicalFile.filename), 201 // This is important in case if there is another attempt in the retry process
194 resolution: videoFileHeight, 202 videoPhysicalFile.filename = video.getVideoFilename(videoFile)
195 size: videoPhysicalFile.size
196 }
197 const videoFile = db.VideoFile.build(videoFileData)
198 const videoDir = CONFIG.STORAGE.VIDEOS_DIR
199 const source = join(videoDir, videoPhysicalFile.filename)
200 const destination = join(videoDir, video.getVideoFilename(videoFile))
201 203
202 await renamePromise(source, destination) 204 const tasks = []
203 // This is important in case if there is another attempt in the retry process
204 videoPhysicalFile.filename = video.getVideoFilename(videoFile)
205 205
206 const tasks = [] 206 tasks.push(
207 video.createTorrentAndSetInfoHash(videoFile),
208 video.createThumbnail(videoFile),
209 video.createPreview(videoFile)
210 )
211 await Promise.all(tasks)
207 212
208 tasks.push( 213 return db.sequelize.transaction(async t => {
209 video.createTorrentAndSetInfoHash(videoFile), 214 const sequelizeOptions = { transaction: t }
210 video.createThumbnail(videoFile),
211 video.createPreview(videoFile)
212 )
213 215
214 if (CONFIG.TRANSCODING.ENABLED === true) { 216 if (CONFIG.TRANSCODING.ENABLED === true) {
215 // Put uuid because we don't have id auto incremented for now 217 // Put uuid because we don't have id auto incremented for now
@@ -217,20 +219,17 @@ function addVideo (req: express.Request, res: express.Response, videoPhysicalFil
217 videoUUID: video.uuid 219 videoUUID: video.uuid
218 } 220 }
219 221
220 tasks.push( 222 await transcodingJobScheduler.createJob(t, 'videoFileOptimizer', dataInput)
221 transcodingJobScheduler.createJob(t, 'videoFileOptimizer', dataInput)
222 )
223 } 223 }
224 await Promise.all(tasks)
225 224
226 const videoCreated = await video.save(sequelizeOptions) 225 const videoCreated = await video.save(sequelizeOptions)
227 // Do not forget to add video channel information to the created video 226 // Do not forget to add video channel information to the created video
228 videoCreated.VideoChannel = res.locals.videoChannel 227 videoCreated.VideoChannel = res.locals.videoChannel
229 228
230 videoFile.videoId = video.id 229 videoFile.videoId = video.id
231
232 await videoFile.save(sequelizeOptions) 230 await videoFile.save(sequelizeOptions)
233 video.VideoFiles = [videoFile] 231
232 video.VideoFiles = [ videoFile ]
234 233
235 if (videoInfo.tags) { 234 if (videoInfo.tags) {
236 const tagInstances = await db.Tag.findOrCreateTags(videoInfo.tags, t) 235 const tagInstances = await db.Tag.findOrCreateTags(videoInfo.tags, t)
diff --git a/server/tests/api/single-server.ts b/server/tests/api/single-server.ts
index ed79f9e1c..e99955ef4 100644
--- a/server/tests/api/single-server.ts
+++ b/server/tests/api/single-server.ts
@@ -364,7 +364,7 @@ describe('Test a single server', function () {
364 'video_short1.webm', 'video_short2.webm', 'video_short3.webm' 364 'video_short1.webm', 'video_short2.webm', 'video_short3.webm'
365 ] 365 ]
366 366
367 // const tasks: Promise<any>[] = [] 367 const tasks: Promise<any>[] = []
368 for (const video of videos) { 368 for (const video of videos) {
369 const videoAttributes = { 369 const videoAttributes = {
370 name: video + ' name', 370 name: video + ' name',
@@ -378,13 +378,10 @@ describe('Test a single server', function () {
378 } 378 }
379 379
380 const p = uploadVideo(server.url, server.accessToken, videoAttributes) 380 const p = uploadVideo(server.url, server.accessToken, videoAttributes)
381 await p 381 tasks.push(p)
382 } 382 }
383 // FIXME: concurrent uploads does not work :( 383
384 // tasks.push(p) 384 await Promise.all(tasks)
385 // }
386 //
387 // await Promise.all(tasks)
388 }) 385 })
389 386
390 it('Should have the correct durations', async function () { 387 it('Should have the correct durations', async function () {
@@ -712,7 +709,7 @@ describe('Test a single server', function () {
712 const filePath = join(__dirname, '..', 'api', 'fixtures', 'video_short.webm') 709 const filePath = join(__dirname, '..', 'api', 'fixtures', 'video_short.webm')
713 710
714 await req.attach('videofile', filePath) 711 await req.attach('videofile', filePath)
715 .expect(204) 712 .expect(200)
716 713
717 const res = await getVideosList(server.url) 714 const res = await getVideosList(server.url)
718 const video = res.body.data.find(v => v.name === 'minimum parameters') 715 const video = res.body.data.find(v => v.name === 'minimum parameters')
diff --git a/server/tests/utils/videos.ts b/server/tests/utils/videos.ts
index bdf3368ac..fb758cf29 100644
--- a/server/tests/utils/videos.ts
+++ b/server/tests/utils/videos.ts
@@ -201,7 +201,7 @@ async function testVideoImage (url: string, imageName: string, imagePath: string
201 } 201 }
202} 202}
203 203
204async function uploadVideo (url: string, accessToken: string, videoAttributesArg: VideoAttributes, specialStatus = 201) { 204async function uploadVideo (url: string, accessToken: string, videoAttributesArg: VideoAttributes, specialStatus = 200) {
205 const path = '/api/v1/videos/upload' 205 const path = '/api/v1/videos/upload'
206 let defaultChannelId = '1' 206 let defaultChannelId = '1'
207 207