]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - server/lib/video-path-manager.ts
Merge branch 'feature/improve-live' into develop
[github/Chocobozzz/PeerTube.git] / server / lib / video-path-manager.ts
index 429b36df989fe8ccbef3457c2767cb011dcc03aa..9953cae5de2b99a772904c66770cb0a93e215b04 100644 (file)
@@ -1,29 +1,31 @@
+import { Mutex } from 'async-mutex'
 import { remove } from 'fs-extra'
 import { extname, join } from 'path'
-import { buildUUID } from '@shared/core-utils/uuid'
+import { logger, loggerTagsFactory } from '@server/helpers/logger'
 import { extractVideo } from '@server/helpers/video'
 import { CONFIG } from '@server/initializers/config'
-import {
-  MStreamingPlaylistVideo,
-  MVideo,
-  MVideoFile,
-  MVideoFileStreamingPlaylistVideo,
-  MVideoFileVideo,
-  MVideoUUID
-} from '@server/types/models'
+import { DIRECTORIES } from '@server/initializers/constants'
+import { MStreamingPlaylistVideo, MVideo, MVideoFile, MVideoFileStreamingPlaylistVideo, MVideoFileVideo } from '@server/types/models'
+import { buildUUID } from '@shared/extra-utils'
 import { VideoStorage } from '@shared/models'
 import { makeHLSFileAvailable, makeWebTorrentFileAvailable } from './object-storage'
 import { getHLSDirectory, getHLSRedundancyDirectory, getHlsResolutionPlaylistFilename } from './paths'
+import { isVideoInPrivateDirectory } from './video-privacy'
 
 type MakeAvailableCB <T> = (path: string) => Promise<T> | T
 
+const lTags = loggerTagsFactory('video-path-manager')
+
 class VideoPathManager {
 
   private static instance: VideoPathManager
 
+  // Key is a video UUID
+  private readonly videoFileMutexStore = new Map<string, Mutex>()
+
   private constructor () {}
 
-  getFSHLSOutputPath (video: MVideoUUID, filename?: string) {
+  getFSHLSOutputPath (video: MVideo, filename?: string) {
     const base = getHLSDirectory(video)
     if (!filename) return base
 
@@ -41,13 +43,17 @@ class VideoPathManager {
   }
 
   getFSVideoFileOutputPath (videoOrPlaylist: MVideo | MStreamingPlaylistVideo, videoFile: MVideoFile) {
-    if (videoFile.isHLS()) {
-      const video = extractVideo(videoOrPlaylist)
+    const video = extractVideo(videoOrPlaylist)
 
+    if (videoFile.isHLS()) {
       return join(getHLSDirectory(video), videoFile.filename)
     }
 
-    return join(CONFIG.STORAGE.VIDEOS_DIR, videoFile.filename)
+    if (isVideoInPrivateDirectory(video.privacy)) {
+      return join(DIRECTORIES.VIDEOS.PRIVATE, videoFile.filename)
+    }
+
+    return join(DIRECTORIES.VIDEOS.PUBLIC, videoFile.filename)
   }
 
   async makeAvailableVideoFile <T> (videoFile: MVideoFileVideo | MVideoFileStreamingPlaylistVideo, cb: MakeAvailableCB<T>) {
@@ -113,6 +119,27 @@ class VideoPathManager {
     )
   }
 
+  async lockFiles (videoUUID: string) {
+    if (!this.videoFileMutexStore.has(videoUUID)) {
+      this.videoFileMutexStore.set(videoUUID, new Mutex())
+    }
+
+    const mutex = this.videoFileMutexStore.get(videoUUID)
+    const releaser = await mutex.acquire()
+
+    logger.debug('Locked files of %s.', videoUUID, lTags(videoUUID))
+
+    return releaser
+  }
+
+  unlockFiles (videoUUID: string) {
+    const mutex = this.videoFileMutexStore.get(videoUUID)
+
+    mutex.release()
+
+    logger.debug('Released lockfiles of %s.', videoUUID, lTags(videoUUID))
+  }
+
   private async makeAvailableFactory <T> (method: () => Promise<string> | string, clean: boolean, cb: MakeAvailableCB<T>) {
     let result: T