diff options
author | Chocobozzz <florian.bigard@gmail.com> | 2017-12-08 10:08:36 +0100 |
---|---|---|
committer | Chocobozzz <florian.bigard@gmail.com> | 2017-12-08 10:08:36 +0100 |
commit | e11f68a3562d2468480c396f47f1bdd2a306e17a (patch) | |
tree | c773ea89b0ea4b871e0265449501477b64233b00 | |
parent | cadb46d832724ea1a17b085b992142aa32e212be (diff) | |
download | PeerTube-e11f68a3562d2468480c396f47f1bdd2a306e17a.tar.gz PeerTube-e11f68a3562d2468480c396f47f1bdd2a306e17a.tar.zst PeerTube-e11f68a3562d2468480c396f47f1bdd2a306e17a.zip |
Optimise transaction for video upload
-rw-r--r-- | server/controllers/api/videos/index.ts | 87 | ||||
-rw-r--r-- | server/tests/api/single-server.ts | 13 | ||||
-rw-r--r-- | server/tests/utils/videos.ts | 2 |
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 | ||
167 | function addVideo (req: express.Request, res: express.Response, videoPhysicalFile: Express.Multer.File) { | 167 | async 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 | ||
204 | async function uploadVideo (url: string, accessToken: string, videoAttributesArg: VideoAttributes, specialStatus = 201) { | 204 | async 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 | ||