aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2021-02-25 13:56:07 +0100
committerChocobozzz <chocobozzz@cpy.re>2021-02-25 15:01:07 +0100
commitd61893f7236abbed30c25b1823e6ecad93a8e8dd (patch)
tree9cf1d47598d9a99f390c6754d289d2573788451d /server
parentd7df188f23bb3c4773ac26e6fa8b3d82b1229e6d (diff)
downloadPeerTube-d61893f7236abbed30c25b1823e6ecad93a8e8dd.tar.gz
PeerTube-d61893f7236abbed30c25b1823e6ecad93a8e8dd.tar.zst
PeerTube-d61893f7236abbed30c25b1823e6ecad93a8e8dd.zip
Async torrent creation
Diffstat (limited to 'server')
-rw-r--r--server/controllers/api/videos/index.ts38
-rw-r--r--server/models/video/video-file.ts8
-rw-r--r--server/models/video/video-format-utils.ts2
3 files changed, 40 insertions, 8 deletions
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts
index e89315930..58ab72370 100644
--- a/server/controllers/api/videos/index.ts
+++ b/server/controllers/api/videos/index.ts
@@ -9,12 +9,12 @@ import { LiveManager } from '@server/lib/live-manager'
9import { addOptimizeOrMergeAudioJob, buildLocalVideoFromReq, buildVideoThumbnailsFromReq, setVideoTags } from '@server/lib/video' 9import { addOptimizeOrMergeAudioJob, buildLocalVideoFromReq, buildVideoThumbnailsFromReq, setVideoTags } from '@server/lib/video'
10import { generateVideoFilename, getVideoFilePath } from '@server/lib/video-paths' 10import { generateVideoFilename, getVideoFilePath } from '@server/lib/video-paths'
11import { getServerActor } from '@server/models/application/application' 11import { getServerActor } from '@server/models/application/application'
12import { MVideoFullLight } from '@server/types/models' 12import { MVideo, MVideoFile, MVideoFullLight } from '@server/types/models'
13import { VideoCreate, VideoState, VideoUpdate } from '../../../../shared' 13import { VideoCreate, VideoState, VideoUpdate } from '../../../../shared'
14import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' 14import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
15import { VideoFilter } from '../../../../shared/models/videos/video-query.type' 15import { VideoFilter } from '../../../../shared/models/videos/video-query.type'
16import { auditLoggerFactory, getAuditIdFromRes, VideoAuditView } from '../../../helpers/audit-logger' 16import { auditLoggerFactory, getAuditIdFromRes, VideoAuditView } from '../../../helpers/audit-logger'
17import { resetSequelizeInstance } from '../../../helpers/database-utils' 17import { resetSequelizeInstance, retryTransactionWrapper } from '../../../helpers/database-utils'
18import { buildNSFWFilter, createReqFiles, getCountVideos } from '../../../helpers/express-utils' 18import { buildNSFWFilter, createReqFiles, getCountVideos } from '../../../helpers/express-utils'
19import { getMetadataFromFile, getVideoFileFPS, getVideoFileResolution } from '../../../helpers/ffprobe-utils' 19import { getMetadataFromFile, getVideoFileFPS, getVideoFileResolution } from '../../../helpers/ffprobe-utils'
20import { logger } from '../../../helpers/logger' 20import { logger } from '../../../helpers/logger'
@@ -221,9 +221,6 @@ async function addVideo (req: express.Request, res: express.Response) {
221 fallback: type => generateVideoMiniature({ video, videoFile, type }) 221 fallback: type => generateVideoMiniature({ video, videoFile, type })
222 }) 222 })
223 223
224 // Create the torrent file
225 await createTorrentAndSetInfoHash(video, videoFile)
226
227 const { videoCreated } = await sequelizeTypescript.transaction(async t => { 224 const { videoCreated } = await sequelizeTypescript.transaction(async t => {
228 const sequelizeOptions = { transaction: t } 225 const sequelizeOptions = { transaction: t }
229 226
@@ -258,7 +255,6 @@ async function addVideo (req: express.Request, res: express.Response) {
258 isNew: true, 255 isNew: true,
259 transaction: t 256 transaction: t
260 }) 257 })
261 await federateVideoIfNeeded(video, true, t)
262 258
263 auditLogger.create(getAuditIdFromRes(res), new VideoAuditView(videoCreated.toFormattedDetailsJSON())) 259 auditLogger.create(getAuditIdFromRes(res), new VideoAuditView(videoCreated.toFormattedDetailsJSON()))
264 logger.info('Video with name %s and uuid %s created.', videoInfo.name, videoCreated.uuid) 260 logger.info('Video with name %s and uuid %s created.', videoInfo.name, videoCreated.uuid)
@@ -266,7 +262,21 @@ async function addVideo (req: express.Request, res: express.Response) {
266 return { videoCreated } 262 return { videoCreated }
267 }) 263 })
268 264
269 Notifier.Instance.notifyOnNewVideoIfNeeded(videoCreated) 265 // Create the torrent file in async way because it could be long
266 createTorrentAndSetInfoHashAsync(video, videoFile)
267 .catch(err => logger.error('Cannot create torrent file for video %s', video.url, { err }))
268 .then(() => VideoModel.loadAndPopulateAccountAndServerAndTags(video.id))
269 .then(refreshedVideo => {
270 if (!refreshedVideo) return
271
272 // Only federate and notify after the torrent creation
273 Notifier.Instance.notifyOnNewVideoIfNeeded(refreshedVideo)
274
275 return retryTransactionWrapper(() => {
276 return sequelizeTypescript.transaction(t => federateVideoIfNeeded(refreshedVideo, true, t))
277 })
278 })
279 .catch(err => logger.error('Cannot federate or notify video creation %s', video.url, { err }))
270 280
271 if (video.state === VideoState.TO_TRANSCODE) { 281 if (video.state === VideoState.TO_TRANSCODE) {
272 await addOptimizeOrMergeAudioJob(videoCreated, videoFile, res.locals.oauth.token.User) 282 await addOptimizeOrMergeAudioJob(videoCreated, videoFile, res.locals.oauth.token.User)
@@ -526,3 +536,17 @@ async function removeVideo (req: express.Request, res: express.Response) {
526 .status(HttpStatusCode.NO_CONTENT_204) 536 .status(HttpStatusCode.NO_CONTENT_204)
527 .end() 537 .end()
528} 538}
539
540async function createTorrentAndSetInfoHashAsync (video: MVideo, fileArg: MVideoFile) {
541 await createTorrentAndSetInfoHash(video, fileArg)
542
543 // Refresh videoFile because the createTorrentAndSetInfoHash could be long
544 const refreshedFile = await VideoFileModel.loadWithVideo(fileArg.id)
545 // File does not exist anymore, remove the generated torrent
546 if (!refreshedFile) return fileArg.removeTorrent()
547
548 refreshedFile.infoHash = fileArg.infoHash
549 refreshedFile.torrentFilename = fileArg.torrentFilename
550
551 return refreshedFile.save()
552}
diff --git a/server/models/video/video-file.ts b/server/models/video/video-file.ts
index 4df2c20bc..1ad796104 100644
--- a/server/models/video/video-file.ts
+++ b/server/models/video/video-file.ts
@@ -457,18 +457,26 @@ export class VideoFileModel extends Model {
457 457
458 // We proxify torrent requests so use a local URL 458 // We proxify torrent requests so use a local URL
459 getTorrentUrl () { 459 getTorrentUrl () {
460 if (!this.torrentFilename) return null
461
460 return WEBSERVER.URL + this.getTorrentStaticPath() 462 return WEBSERVER.URL + this.getTorrentStaticPath()
461 } 463 }
462 464
463 getTorrentStaticPath () { 465 getTorrentStaticPath () {
466 if (!this.torrentFilename) return null
467
464 return join(LAZY_STATIC_PATHS.TORRENTS, this.torrentFilename) 468 return join(LAZY_STATIC_PATHS.TORRENTS, this.torrentFilename)
465 } 469 }
466 470
467 getTorrentDownloadUrl () { 471 getTorrentDownloadUrl () {
472 if (!this.torrentFilename) return null
473
468 return WEBSERVER.URL + join(STATIC_DOWNLOAD_PATHS.TORRENTS, this.torrentFilename) 474 return WEBSERVER.URL + join(STATIC_DOWNLOAD_PATHS.TORRENTS, this.torrentFilename)
469 } 475 }
470 476
471 removeTorrent () { 477 removeTorrent () {
478 if (!this.torrentFilename) return null
479
472 const torrentPath = getTorrentFilePath(this) 480 const torrentPath = getTorrentFilePath(this)
473 return remove(torrentPath) 481 return remove(torrentPath)
474 .catch(err => logger.warn('Cannot delete torrent %s.', torrentPath, { err })) 482 .catch(err => logger.warn('Cannot delete torrent %s.', torrentPath, { err }))
diff --git a/server/models/video/video-format-utils.ts b/server/models/video/video-format-utils.ts
index a6a1a4f0d..bcba90093 100644
--- a/server/models/video/video-format-utils.ts
+++ b/server/models/video/video-format-utils.ts
@@ -205,7 +205,7 @@ function videoFilesModelToFormattedJSON (
205 label: videoFile.resolution + 'p' 205 label: videoFile.resolution + 'p'
206 }, 206 },
207 207
208 magnetUri: includeMagnet 208 magnetUri: includeMagnet && videoFile.torrentFilename
209 ? generateMagnetUri(video, videoFile, trackerUrls) 209 ? generateMagnetUri(video, videoFile, trackerUrls)
210 : undefined, 210 : undefined,
211 211