diff options
author | Chocobozzz <me@florianbigard.com> | 2018-03-19 15:02:36 +0100 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2018-03-19 15:22:18 +0100 |
commit | a797728009eb5c26cf55624a4a01e8ecb73f1297 (patch) | |
tree | 3dcfe4870986c9bacdfbd2a671143b5dfc4f47d3 | |
parent | 9d145133d82c11edfb2781871076b7063cc3ae3d (diff) | |
download | PeerTube-a797728009eb5c26cf55624a4a01e8ecb73f1297.tar.gz PeerTube-a797728009eb5c26cf55624a4a01e8ecb73f1297.tar.zst PeerTube-a797728009eb5c26cf55624a4a01e8ecb73f1297.zip |
Fix video_share_url duplicate key in transcoding job
-rw-r--r-- | CHANGELOG.md | 9 | ||||
-rw-r--r-- | server/controllers/activitypub/inbox.ts | 2 | ||||
-rw-r--r-- | server/helpers/ffmpeg-utils.ts | 6 | ||||
-rw-r--r-- | server/initializers/constants.ts | 7 | ||||
-rw-r--r-- | server/lib/activitypub/share.ts | 47 | ||||
-rw-r--r-- | server/lib/job-queue/handlers/video-file.ts | 40 |
6 files changed, 65 insertions, 46 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 04b8b7c31..fb6ace20e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | ### BREAKING CHANGES | 5 | ### BREAKING CHANGES |
6 | 6 | ||
7 | * Update videos list/search/get API response: | 7 | * Update videos list/search/get API response: |
8 | * Removed `resolution` field | 8 | * Removed `resolution` field |
9 | * Removed `resolutionLabel` field | 9 | * Removed `resolutionLabel` field |
10 | * Removed `category` field | 10 | * Removed `category` field |
@@ -26,6 +26,10 @@ | |||
26 | * Added `privacy.id` field | 26 | * Added `privacy.id` field |
27 | * Added `privacy.label` field | 27 | * Added `privacy.label` field |
28 | 28 | ||
29 | ### Bug fixes | ||
30 | |||
31 | * Fix video_share_url duplicate key on failed transcoding job | ||
32 | |||
29 | 33 | ||
30 | ## v1.0.0-alpha.8 | 34 | ## v1.0.0-alpha.8 |
31 | 35 | ||
@@ -60,8 +64,7 @@ | |||
60 | 64 | ||
61 | ### Features | 65 | ### Features |
62 | 66 | ||
63 | * Add "Local" in menu that lists only local videos | 67 | * Add "Local" in menu that lists only local videos |
64 | |||
65 | 68 | ||
66 | 69 | ||
67 | ## v1.0.0-alpha.4 | 70 | ## v1.0.0-alpha.4 |
diff --git a/server/controllers/activitypub/inbox.ts b/server/controllers/activitypub/inbox.ts index 0354d7833..df041aebf 100644 --- a/server/controllers/activitypub/inbox.ts +++ b/server/controllers/activitypub/inbox.ts | |||
@@ -56,7 +56,7 @@ async function inboxController (req: express.Request, res: express.Response, nex | |||
56 | specificActor = res.locals.videoChannel | 56 | specificActor = res.locals.videoChannel |
57 | } | 57 | } |
58 | 58 | ||
59 | logger.info('Receiving inbox requests for %d activities by %s.', activities.length, res.locals.signature.actor) | 59 | logger.info('Receiving inbox requests for %d activities by %s.', activities.length, res.locals.signature.actor.url) |
60 | 60 | ||
61 | await processActivities(activities, res.locals.signature.actor, specificActor) | 61 | await processActivities(activities, res.locals.signature.actor, specificActor) |
62 | 62 | ||
diff --git a/server/helpers/ffmpeg-utils.ts b/server/helpers/ffmpeg-utils.ts index 4f75ba5a8..4d6cd3a82 100644 --- a/server/helpers/ffmpeg-utils.ts +++ b/server/helpers/ffmpeg-utils.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | import * as ffmpeg from 'fluent-ffmpeg' | 1 | import * as ffmpeg from 'fluent-ffmpeg' |
2 | import { join } from 'path' | 2 | import { join } from 'path' |
3 | import { VideoResolution } from '../../shared/models/videos' | 3 | import { VideoResolution } from '../../shared/models/videos' |
4 | import { CONFIG, MAX_VIDEO_TRANSCODING_FPS } from '../initializers' | 4 | import { CONFIG, VIDEO_TRANSCODING_FPS } from '../initializers' |
5 | import { unlinkPromise } from './core-utils' | 5 | import { unlinkPromise } from './core-utils' |
6 | import { processImage } from './image-utils' | 6 | import { processImage } from './image-utils' |
7 | import { logger } from './logger' | 7 | import { logger } from './logger' |
@@ -92,7 +92,9 @@ function transcode (options: TranscodeOptions) { | |||
92 | .outputOption('-movflags faststart') | 92 | .outputOption('-movflags faststart') |
93 | // .outputOption('-crf 18') | 93 | // .outputOption('-crf 18') |
94 | 94 | ||
95 | if (fps > MAX_VIDEO_TRANSCODING_FPS) command = command.withFPS(MAX_VIDEO_TRANSCODING_FPS) | 95 | // Our player has some FPS limits |
96 | if (fps > VIDEO_TRANSCODING_FPS.MAX) command = command.withFPS(VIDEO_TRANSCODING_FPS.MAX) | ||
97 | else if (fps < VIDEO_TRANSCODING_FPS.MIN) command = command.withFPS(VIDEO_TRANSCODING_FPS.MIN) | ||
96 | 98 | ||
97 | if (options.resolution !== undefined) { | 99 | if (options.resolution !== undefined) { |
98 | // '?x720' or '720x?' for example | 100 | // '?x720' or '720x?' for example |
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index d12d96803..3cf9ea36d 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts | |||
@@ -234,7 +234,10 @@ const CONSTRAINTS_FIELDS = { | |||
234 | } | 234 | } |
235 | 235 | ||
236 | let VIDEO_VIEW_LIFETIME = 60000 * 60 // 1 hour | 236 | let VIDEO_VIEW_LIFETIME = 60000 * 60 // 1 hour |
237 | const MAX_VIDEO_TRANSCODING_FPS = 30 | 237 | const VIDEO_TRANSCODING_FPS = { |
238 | MIN: 10, | ||
239 | MAX: 30 | ||
240 | } | ||
238 | 241 | ||
239 | const VIDEO_RATE_TYPES: { [ id: string ]: VideoRateType } = { | 242 | const VIDEO_RATE_TYPES: { [ id: string ]: VideoRateType } = { |
240 | LIKE: 'like', | 243 | LIKE: 'like', |
@@ -445,7 +448,7 @@ export { | |||
445 | VIDEO_LICENCES, | 448 | VIDEO_LICENCES, |
446 | VIDEO_RATE_TYPES, | 449 | VIDEO_RATE_TYPES, |
447 | VIDEO_MIMETYPE_EXT, | 450 | VIDEO_MIMETYPE_EXT, |
448 | MAX_VIDEO_TRANSCODING_FPS, | 451 | VIDEO_TRANSCODING_FPS, |
449 | USER_PASSWORD_RESET_LIFETIME, | 452 | USER_PASSWORD_RESET_LIFETIME, |
450 | IMAGE_MIMETYPE_EXT, | 453 | IMAGE_MIMETYPE_EXT, |
451 | SCHEDULER_INTERVAL, | 454 | SCHEDULER_INTERVAL, |
diff --git a/server/lib/activitypub/share.ts b/server/lib/activitypub/share.ts index 53ecd3dab..038f19b7d 100644 --- a/server/lib/activitypub/share.ts +++ b/server/lib/activitypub/share.ts | |||
@@ -12,27 +12,42 @@ async function shareVideoByServerAndChannel (video: VideoModel, t: Transaction) | |||
12 | const serverActor = await getServerActor() | 12 | const serverActor = await getServerActor() |
13 | 13 | ||
14 | const serverShareUrl = getAnnounceActivityPubUrl(video.url, serverActor) | 14 | const serverShareUrl = getAnnounceActivityPubUrl(video.url, serverActor) |
15 | const serverSharePromise = VideoShareModel.create({ | 15 | const serverSharePromise = VideoShareModel.findOrCreate({ |
16 | actorId: serverActor.id, | 16 | defaults: { |
17 | videoId: video.id, | 17 | actorId: serverActor.id, |
18 | url: serverShareUrl | 18 | videoId: video.id, |
19 | }, { transaction: t }) | 19 | url: serverShareUrl |
20 | }, | ||
21 | where: { | ||
22 | url: serverShareUrl | ||
23 | }, | ||
24 | transaction: t | ||
25 | }).then(([ serverShare, created ]) => { | ||
26 | if (created) return sendVideoAnnounceToFollowers(serverActor, serverShare, video, t) | ||
27 | |||
28 | return undefined | ||
29 | }) | ||
20 | 30 | ||
21 | const videoChannelShareUrl = getAnnounceActivityPubUrl(video.url, video.VideoChannel.Actor) | 31 | const videoChannelShareUrl = getAnnounceActivityPubUrl(video.url, video.VideoChannel.Actor) |
22 | const videoChannelSharePromise = VideoShareModel.create({ | 32 | const videoChannelSharePromise = VideoShareModel.findOrCreate({ |
23 | actorId: video.VideoChannel.actorId, | 33 | defaults: { |
24 | videoId: video.id, | 34 | actorId: video.VideoChannel.actorId, |
25 | url: videoChannelShareUrl | 35 | videoId: video.id, |
26 | }, { transaction: t }) | 36 | url: videoChannelShareUrl |
37 | }, | ||
38 | where: { | ||
39 | url: videoChannelShareUrl | ||
40 | }, | ||
41 | transaction: t | ||
42 | }).then(([ videoChannelShare, created ]) => { | ||
43 | if (created) return sendVideoAnnounceToFollowers(serverActor, videoChannelShare, video, t) | ||
27 | 44 | ||
28 | const [ serverShare, videoChannelShare ] = await Promise.all([ | 45 | return undefined |
29 | serverSharePromise, | 46 | }) |
30 | videoChannelSharePromise | ||
31 | ]) | ||
32 | 47 | ||
33 | return Promise.all([ | 48 | return Promise.all([ |
34 | sendVideoAnnounceToFollowers(serverActor, videoChannelShare, video, t), | 49 | serverSharePromise, |
35 | sendVideoAnnounceToFollowers(serverActor, serverShare, video, t) | 50 | videoChannelSharePromise |
36 | ]) | 51 | ]) |
37 | } | 52 | } |
38 | 53 | ||
diff --git a/server/lib/job-queue/handlers/video-file.ts b/server/lib/job-queue/handlers/video-file.ts index bd9412290..1b41d29e8 100644 --- a/server/lib/job-queue/handlers/video-file.ts +++ b/server/lib/job-queue/handlers/video-file.ts | |||
@@ -63,8 +63,10 @@ async function onVideoFileOptimizerSuccess (video: VideoModel) { | |||
63 | 63 | ||
64 | if (video.privacy !== VideoPrivacy.PRIVATE) { | 64 | if (video.privacy !== VideoPrivacy.PRIVATE) { |
65 | // Now we'll add the video's meta data to our followers | 65 | // Now we'll add the video's meta data to our followers |
66 | await sendCreateVideo(video, undefined) | 66 | await sequelizeTypescript.transaction(async t => { |
67 | await shareVideoByServerAndChannel(video, undefined) | 67 | await sendCreateVideo(video, t) |
68 | await shareVideoByServerAndChannel(video, t) | ||
69 | }) | ||
68 | } | 70 | } |
69 | 71 | ||
70 | const { videoFileResolution } = await videoDatabase.getOriginalFileResolution() | 72 | const { videoFileResolution } = await videoDatabase.getOriginalFileResolution() |
@@ -77,27 +79,21 @@ async function onVideoFileOptimizerSuccess (video: VideoModel) { | |||
77 | ) | 79 | ) |
78 | 80 | ||
79 | if (resolutionsEnabled.length !== 0) { | 81 | if (resolutionsEnabled.length !== 0) { |
80 | try { | 82 | const tasks: Promise<any>[] = [] |
81 | await sequelizeTypescript.transaction(async t => { | 83 | |
82 | const tasks: Promise<any>[] = [] | 84 | for (const resolution of resolutionsEnabled) { |
83 | 85 | const dataInput = { | |
84 | for (const resolution of resolutionsEnabled) { | 86 | videoUUID: videoDatabase.uuid, |
85 | const dataInput = { | 87 | resolution |
86 | videoUUID: videoDatabase.uuid, | 88 | } |
87 | resolution | 89 | |
88 | } | 90 | const p = JobQueue.Instance.createJob({ type: 'video-file', payload: dataInput }) |
89 | 91 | tasks.push(p) | |
90 | const p = JobQueue.Instance.createJob({ type: 'video-file', payload: dataInput }) | ||
91 | tasks.push(p) | ||
92 | } | ||
93 | |||
94 | await Promise.all(tasks) | ||
95 | }) | ||
96 | |||
97 | logger.info('Transcoding jobs created for uuid %s.', videoDatabase.uuid, { resolutionsEnabled }) | ||
98 | } catch (err) { | ||
99 | logger.warn('Cannot transcode the video.', err) | ||
100 | } | 92 | } |
93 | |||
94 | await Promise.all(tasks) | ||
95 | |||
96 | logger.info('Transcoding jobs created for uuid %s.', videoDatabase.uuid, { resolutionsEnabled }) | ||
101 | } else { | 97 | } else { |
102 | logger.info('No transcoding jobs created for video %s (no resolutions enabled).') | 98 | logger.info('No transcoding jobs created for video %s (no resolutions enabled).') |
103 | return undefined | 99 | return undefined |