diff options
author | Chocobozzz <me@florianbigard.com> | 2021-02-25 13:56:07 +0100 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2021-02-25 15:01:07 +0100 |
commit | d61893f7236abbed30c25b1823e6ecad93a8e8dd (patch) | |
tree | 9cf1d47598d9a99f390c6754d289d2573788451d /server | |
parent | d7df188f23bb3c4773ac26e6fa8b3d82b1229e6d (diff) | |
download | PeerTube-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.ts | 38 | ||||
-rw-r--r-- | server/models/video/video-file.ts | 8 | ||||
-rw-r--r-- | server/models/video/video-format-utils.ts | 2 |
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' | |||
9 | import { addOptimizeOrMergeAudioJob, buildLocalVideoFromReq, buildVideoThumbnailsFromReq, setVideoTags } from '@server/lib/video' | 9 | import { addOptimizeOrMergeAudioJob, buildLocalVideoFromReq, buildVideoThumbnailsFromReq, setVideoTags } from '@server/lib/video' |
10 | import { generateVideoFilename, getVideoFilePath } from '@server/lib/video-paths' | 10 | import { generateVideoFilename, getVideoFilePath } from '@server/lib/video-paths' |
11 | import { getServerActor } from '@server/models/application/application' | 11 | import { getServerActor } from '@server/models/application/application' |
12 | import { MVideoFullLight } from '@server/types/models' | 12 | import { MVideo, MVideoFile, MVideoFullLight } from '@server/types/models' |
13 | import { VideoCreate, VideoState, VideoUpdate } from '../../../../shared' | 13 | import { VideoCreate, VideoState, VideoUpdate } from '../../../../shared' |
14 | import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' | 14 | import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' |
15 | import { VideoFilter } from '../../../../shared/models/videos/video-query.type' | 15 | import { VideoFilter } from '../../../../shared/models/videos/video-query.type' |
16 | import { auditLoggerFactory, getAuditIdFromRes, VideoAuditView } from '../../../helpers/audit-logger' | 16 | import { auditLoggerFactory, getAuditIdFromRes, VideoAuditView } from '../../../helpers/audit-logger' |
17 | import { resetSequelizeInstance } from '../../../helpers/database-utils' | 17 | import { resetSequelizeInstance, retryTransactionWrapper } from '../../../helpers/database-utils' |
18 | import { buildNSFWFilter, createReqFiles, getCountVideos } from '../../../helpers/express-utils' | 18 | import { buildNSFWFilter, createReqFiles, getCountVideos } from '../../../helpers/express-utils' |
19 | import { getMetadataFromFile, getVideoFileFPS, getVideoFileResolution } from '../../../helpers/ffprobe-utils' | 19 | import { getMetadataFromFile, getVideoFileFPS, getVideoFileResolution } from '../../../helpers/ffprobe-utils' |
20 | import { logger } from '../../../helpers/logger' | 20 | import { 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 | |||
540 | async 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 | ||