aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/job-queue
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2022-03-16 15:34:21 +0100
committerChocobozzz <me@florianbigard.com>2022-03-16 15:45:58 +0100
commitf012319a644fe8d9d33f2f567fa828442a3b39fd (patch)
tree8fc7aeff10749ed8088e3f89745433b59bb62c20 /server/lib/job-queue
parent83664918901564830f3b7d1bd9879411a1b857a8 (diff)
downloadPeerTube-f012319a644fe8d9d33f2f567fa828442a3b39fd.tar.gz
PeerTube-f012319a644fe8d9d33f2f567fa828442a3b39fd.tar.zst
PeerTube-f012319a644fe8d9d33f2f567fa828442a3b39fd.zip
Process video torrents in order
Prevent update before video torrent generation for example
Diffstat (limited to 'server/lib/job-queue')
-rw-r--r--server/lib/job-queue/handlers/manage-video-torrent.ts88
-rw-r--r--server/lib/job-queue/job-queue.ts7
2 files changed, 94 insertions, 1 deletions
diff --git a/server/lib/job-queue/handlers/manage-video-torrent.ts b/server/lib/job-queue/handlers/manage-video-torrent.ts
new file mode 100644
index 000000000..5cb4287e1
--- /dev/null
+++ b/server/lib/job-queue/handlers/manage-video-torrent.ts
@@ -0,0 +1,88 @@
1import { Job } from 'bull'
2import { createTorrentAndSetInfoHash, updateTorrentMetadata } from '@server/helpers/webtorrent'
3import { VideoModel } from '@server/models/video/video'
4import { VideoFileModel } from '@server/models/video/video-file'
5import { VideoStreamingPlaylistModel } from '@server/models/video/video-streaming-playlist'
6import { ManageVideoTorrentPayload } from '@shared/models'
7import { logger } from '../../../helpers/logger'
8
9async function processManageVideoTorrent (job: Job) {
10 const payload = job.data as ManageVideoTorrentPayload
11 logger.info('Processing torrent in job %d.', job.id)
12
13 if (payload.action === 'create') return doCreateAction(payload)
14 if (payload.action === 'update-metadata') return doUpdateMetadataAction(payload)
15}
16
17// ---------------------------------------------------------------------------
18
19export {
20 processManageVideoTorrent
21}
22
23// ---------------------------------------------------------------------------
24
25async function doCreateAction (payload: ManageVideoTorrentPayload & { action: 'create' }) {
26 const [ video, file ] = await Promise.all([
27 loadVideoOrLog(payload.videoId),
28 loadFileOrLog(payload.videoFileId)
29 ])
30
31 await createTorrentAndSetInfoHash(video, file)
32
33 // Refresh videoFile because the createTorrentAndSetInfoHash could be long
34 const refreshedFile = await VideoFileModel.loadWithVideo(file.id)
35 // File does not exist anymore, remove the generated torrent
36 if (!refreshedFile) return file.removeTorrent()
37
38 refreshedFile.infoHash = file.infoHash
39 refreshedFile.torrentFilename = file.torrentFilename
40
41 return refreshedFile.save()
42}
43
44async function doUpdateMetadataAction (payload: ManageVideoTorrentPayload & { action: 'update-metadata' }) {
45 const [ video, streamingPlaylist, file ] = await Promise.all([
46 loadVideoOrLog(payload.videoId),
47 loadStreamingPlaylistOrLog(payload.streamingPlaylistId),
48 loadFileOrLog(payload.videoFileId)
49 ])
50
51 await updateTorrentMetadata(video || streamingPlaylist, file)
52
53 await file.save()
54}
55
56async function loadVideoOrLog (videoId: number) {
57 if (!videoId) return undefined
58
59 const video = await VideoModel.load(videoId)
60 if (!video) {
61 logger.debug('Do not process torrent for video %d: does not exist anymore.', videoId)
62 }
63
64 return video
65}
66
67async function loadStreamingPlaylistOrLog (streamingPlaylistId: number) {
68 if (!streamingPlaylistId) return undefined
69
70 const streamingPlaylist = await VideoStreamingPlaylistModel.loadWithVideo(streamingPlaylistId)
71 if (!streamingPlaylist) {
72 logger.debug('Do not process torrent for streaming playlist %d: does not exist anymore.', streamingPlaylistId)
73 }
74
75 return streamingPlaylist
76}
77
78async function loadFileOrLog (videoFileId: number) {
79 if (!videoFileId) return undefined
80
81 const file = await VideoFileModel.loadWithVideo(videoFileId)
82
83 if (!file) {
84 logger.debug('Do not process torrent for file %d: does not exist anymore.', videoFileId)
85 }
86
87 return file
88}
diff --git a/server/lib/job-queue/job-queue.ts b/server/lib/job-queue/job-queue.ts
index e10a3bab5..3224abcc3 100644
--- a/server/lib/job-queue/job-queue.ts
+++ b/server/lib/job-queue/job-queue.ts
@@ -12,6 +12,7 @@ import {
12 EmailPayload, 12 EmailPayload,
13 JobState, 13 JobState,
14 JobType, 14 JobType,
15 ManageVideoTorrentPayload,
15 MoveObjectStoragePayload, 16 MoveObjectStoragePayload,
16 RefreshPayload, 17 RefreshPayload,
17 VideoEditionPayload, 18 VideoEditionPayload,
@@ -31,6 +32,7 @@ import { processActivityPubHttpUnicast } from './handlers/activitypub-http-unica
31import { refreshAPObject } from './handlers/activitypub-refresher' 32import { refreshAPObject } from './handlers/activitypub-refresher'
32import { processActorKeys } from './handlers/actor-keys' 33import { processActorKeys } from './handlers/actor-keys'
33import { processEmail } from './handlers/email' 34import { processEmail } from './handlers/email'
35import { processManageVideoTorrent } from './handlers/manage-video-torrent'
34import { processMoveToObjectStorage } from './handlers/move-to-object-storage' 36import { processMoveToObjectStorage } from './handlers/move-to-object-storage'
35import { processVideoEdition } from './handlers/video-edition' 37import { processVideoEdition } from './handlers/video-edition'
36import { processVideoFileImport } from './handlers/video-file-import' 38import { processVideoFileImport } from './handlers/video-file-import'
@@ -56,6 +58,7 @@ type CreateJobArgument =
56 { type: 'video-redundancy', payload: VideoRedundancyPayload } | 58 { type: 'video-redundancy', payload: VideoRedundancyPayload } |
57 { type: 'delete-resumable-upload-meta-file', payload: DeleteResumableUploadMetaFilePayload } | 59 { type: 'delete-resumable-upload-meta-file', payload: DeleteResumableUploadMetaFilePayload } |
58 { type: 'video-edition', payload: VideoEditionPayload } | 60 { type: 'video-edition', payload: VideoEditionPayload } |
61 { type: 'manage-video-torrent', payload: ManageVideoTorrentPayload } |
59 { type: 'move-to-object-storage', payload: MoveObjectStoragePayload } 62 { type: 'move-to-object-storage', payload: MoveObjectStoragePayload }
60 63
61export type CreateJobOptions = { 64export type CreateJobOptions = {
@@ -79,6 +82,7 @@ const handlers: { [id in JobType]: (job: Job) => Promise<any> } = {
79 'actor-keys': processActorKeys, 82 'actor-keys': processActorKeys,
80 'video-redundancy': processVideoRedundancy, 83 'video-redundancy': processVideoRedundancy,
81 'move-to-object-storage': processMoveToObjectStorage, 84 'move-to-object-storage': processMoveToObjectStorage,
85 'manage-video-torrent': processManageVideoTorrent,
82 'video-edition': processVideoEdition 86 'video-edition': processVideoEdition
83} 87}
84 88
@@ -98,6 +102,7 @@ const jobTypes: JobType[] = [
98 'actor-keys', 102 'actor-keys',
99 'video-live-ending', 103 'video-live-ending',
100 'move-to-object-storage', 104 'move-to-object-storage',
105 'manage-video-torrent',
101 'video-edition' 106 'video-edition'
102] 107]
103 108
@@ -185,7 +190,7 @@ class JobQueue {
185 } 190 }
186 191
187 createJobWithPromise (obj: CreateJobArgument, options: CreateJobOptions = {}) { 192 createJobWithPromise (obj: CreateJobArgument, options: CreateJobOptions = {}) {
188 const queue = this.queues[obj.type] 193 const queue: Queue = this.queues[obj.type]
189 if (queue === undefined) { 194 if (queue === undefined) {
190 logger.error('Unknown queue %s: cannot create job.', obj.type) 195 logger.error('Unknown queue %s: cannot create job.', obj.type)
191 return 196 return