aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/files-cache
diff options
context:
space:
mode:
Diffstat (limited to 'server/lib/files-cache')
-rw-r--r--server/lib/files-cache/avatar-permanent-file-cache.ts27
-rw-r--r--server/lib/files-cache/index.ts9
-rw-r--r--server/lib/files-cache/shared/abstract-permanent-file-cache.ts119
-rw-r--r--server/lib/files-cache/shared/abstract-simple-file-cache.ts (renamed from server/lib/files-cache/abstract-video-static-file-cache.ts)4
-rw-r--r--server/lib/files-cache/shared/index.ts2
-rw-r--r--server/lib/files-cache/video-captions-simple-file-cache.ts (renamed from server/lib/files-cache/videos-caption-cache.ts)12
-rw-r--r--server/lib/files-cache/video-previews-simple-file-cache.ts (renamed from server/lib/files-cache/videos-preview-cache.ts)8
-rw-r--r--server/lib/files-cache/video-storyboards-simple-file-cache.ts (renamed from server/lib/files-cache/videos-storyboard-cache.ts)8
-rw-r--r--server/lib/files-cache/video-torrents-simple-file-cache.ts (renamed from server/lib/files-cache/videos-torrent-cache.ts)8
9 files changed, 174 insertions, 23 deletions
diff --git a/server/lib/files-cache/avatar-permanent-file-cache.ts b/server/lib/files-cache/avatar-permanent-file-cache.ts
new file mode 100644
index 000000000..89228c5a5
--- /dev/null
+++ b/server/lib/files-cache/avatar-permanent-file-cache.ts
@@ -0,0 +1,27 @@
1import { ACTOR_IMAGES_SIZE } from '@server/initializers/constants'
2import { ActorImageModel } from '@server/models/actor/actor-image'
3import { MActorImage } from '@server/types/models'
4import { AbstractPermanentFileCache } from './shared'
5import { CONFIG } from '@server/initializers/config'
6
7export class AvatarPermanentFileCache extends AbstractPermanentFileCache<ActorImageModel> {
8
9 constructor () {
10 super(CONFIG.STORAGE.ACTOR_IMAGES)
11 }
12
13 protected loadModel (filename: string) {
14 return ActorImageModel.loadByName(filename)
15 }
16
17 protected getImageSize (image: MActorImage): { width: number, height: number } {
18 if (image.width && image.height) {
19 return {
20 height: image.height,
21 width: image.width
22 }
23 }
24
25 return ACTOR_IMAGES_SIZE[image.type][0]
26 }
27}
diff --git a/server/lib/files-cache/index.ts b/server/lib/files-cache/index.ts
index 59cec7215..cc11d5385 100644
--- a/server/lib/files-cache/index.ts
+++ b/server/lib/files-cache/index.ts
@@ -1,4 +1,5 @@
1export * from './videos-caption-cache' 1export * from './avatar-permanent-file-cache'
2export * from './videos-preview-cache' 2export * from './video-captions-simple-file-cache'
3export * from './videos-storyboard-cache' 3export * from './video-previews-simple-file-cache'
4export * from './videos-torrent-cache' 4export * from './video-storyboards-simple-file-cache'
5export * from './video-torrents-simple-file-cache'
diff --git a/server/lib/files-cache/shared/abstract-permanent-file-cache.ts b/server/lib/files-cache/shared/abstract-permanent-file-cache.ts
new file mode 100644
index 000000000..22596c3eb
--- /dev/null
+++ b/server/lib/files-cache/shared/abstract-permanent-file-cache.ts
@@ -0,0 +1,119 @@
1import express from 'express'
2import { LRUCache } from 'lru-cache'
3import { logger } from '@server/helpers/logger'
4import { LRU_CACHE, STATIC_MAX_AGE } from '@server/initializers/constants'
5import { downloadImageFromWorker } from '@server/lib/worker/parent-process'
6import { HttpStatusCode } from '@shared/models'
7import { Model } from 'sequelize'
8
9type ImageModel = {
10 fileUrl: string
11 filename: string
12 onDisk: boolean
13
14 isOwned (): boolean
15 getPath (): string
16
17 save (): Promise<Model>
18}
19
20export abstract class AbstractPermanentFileCache <M extends ImageModel> {
21 // Unsafe because it can return paths that do not exist anymore
22 private readonly filenameToPathUnsafeCache = new LRUCache<string, string>({
23 max: LRU_CACHE.FILENAME_TO_PATH_PERMANENT_FILE_CACHE.MAX_SIZE
24 })
25
26 protected abstract getImageSize (image: M): { width: number, height: number }
27 protected abstract loadModel (filename: string): Promise<M>
28
29 constructor (private readonly directory: string) {
30
31 }
32
33 async lazyServe (options: {
34 filename: string
35 res: express.Response
36 next: express.NextFunction
37 }) {
38 const { filename, res, next } = options
39
40 if (this.filenameToPathUnsafeCache.has(filename)) {
41 return res.sendFile(this.filenameToPathUnsafeCache.get(filename), { maxAge: STATIC_MAX_AGE.SERVER })
42 }
43
44 const image = await this.loadModel(filename)
45 if (!image) return res.status(HttpStatusCode.NOT_FOUND_404).end()
46
47 if (image.onDisk === false) {
48 if (!image.fileUrl) return res.status(HttpStatusCode.NOT_FOUND_404).end()
49
50 try {
51 await this.downloadRemoteFile(image)
52 } catch (err) {
53 logger.warn('Cannot process remote image %s.', image.fileUrl, { err })
54
55 return res.status(HttpStatusCode.NOT_FOUND_404).end()
56 }
57 }
58
59 const path = image.getPath()
60 this.filenameToPathUnsafeCache.set(filename, path)
61
62 return res.sendFile(path, { maxAge: STATIC_MAX_AGE.LAZY_SERVER }, (err: any) => {
63 if (!err) return
64
65 this.onServeError({ err, image, next, filename })
66 })
67 }
68
69 private async downloadRemoteFile (image: M) {
70 logger.info('Download remote image %s lazily.', image.fileUrl)
71
72 await this.downloadImage({
73 filename: image.filename,
74 fileUrl: image.fileUrl,
75 size: this.getImageSize(image)
76 })
77
78 image.onDisk = true
79 image.save()
80 .catch(err => logger.error('Cannot save new image disk state.', { err }))
81 }
82
83 private onServeError (options: {
84 err: any
85 image: M
86 filename: string
87 next: express.NextFunction
88 }) {
89 const { err, image, filename, next } = options
90
91 // It seems this actor image is not on the disk anymore
92 if (err.status === HttpStatusCode.NOT_FOUND_404 && !image.isOwned()) {
93 logger.error('Cannot lazy serve image %s.', filename, { err })
94
95 this.filenameToPathUnsafeCache.delete(filename)
96
97 image.onDisk = false
98 image.save()
99 .catch(err => logger.error('Cannot save new image disk state.', { err }))
100 }
101
102 return next(err)
103 }
104
105 private downloadImage (options: {
106 fileUrl: string
107 filename: string
108 size: { width: number, height: number }
109 }) {
110 const downloaderOptions = {
111 url: options.fileUrl,
112 destDir: this.directory,
113 destName: options.filename,
114 size: options.size
115 }
116
117 return downloadImageFromWorker(downloaderOptions)
118 }
119}
diff --git a/server/lib/files-cache/abstract-video-static-file-cache.ts b/server/lib/files-cache/shared/abstract-simple-file-cache.ts
index a7ac88525..6fab322cd 100644
--- a/server/lib/files-cache/abstract-video-static-file-cache.ts
+++ b/server/lib/files-cache/shared/abstract-simple-file-cache.ts
@@ -1,10 +1,10 @@
1import { remove } from 'fs-extra' 1import { remove } from 'fs-extra'
2import { logger } from '../../helpers/logger' 2import { logger } from '../../../helpers/logger'
3import memoizee from 'memoizee' 3import memoizee from 'memoizee'
4 4
5type GetFilePathResult = { isOwned: boolean, path: string, downloadName?: string } | undefined 5type GetFilePathResult = { isOwned: boolean, path: string, downloadName?: string } | undefined
6 6
7export abstract class AbstractVideoStaticFileCache <T> { 7export abstract class AbstractSimpleFileCache <T> {
8 8
9 getFilePath: (params: T) => Promise<GetFilePathResult> 9 getFilePath: (params: T) => Promise<GetFilePathResult>
10 10
diff --git a/server/lib/files-cache/shared/index.ts b/server/lib/files-cache/shared/index.ts
new file mode 100644
index 000000000..61c4aacc7
--- /dev/null
+++ b/server/lib/files-cache/shared/index.ts
@@ -0,0 +1,2 @@
1export * from './abstract-permanent-file-cache'
2export * from './abstract-simple-file-cache'
diff --git a/server/lib/files-cache/videos-caption-cache.ts b/server/lib/files-cache/video-captions-simple-file-cache.ts
index d21acf4ef..cbeeff732 100644
--- a/server/lib/files-cache/videos-caption-cache.ts
+++ b/server/lib/files-cache/video-captions-simple-file-cache.ts
@@ -5,11 +5,11 @@ import { CONFIG } from '../../initializers/config'
5import { FILES_CACHE } from '../../initializers/constants' 5import { FILES_CACHE } from '../../initializers/constants'
6import { VideoModel } from '../../models/video/video' 6import { VideoModel } from '../../models/video/video'
7import { VideoCaptionModel } from '../../models/video/video-caption' 7import { VideoCaptionModel } from '../../models/video/video-caption'
8import { AbstractVideoStaticFileCache } from './abstract-video-static-file-cache' 8import { AbstractSimpleFileCache } from './shared/abstract-simple-file-cache'
9 9
10class VideosCaptionCache extends AbstractVideoStaticFileCache <string> { 10class VideoCaptionsSimpleFileCache extends AbstractSimpleFileCache <string> {
11 11
12 private static instance: VideosCaptionCache 12 private static instance: VideoCaptionsSimpleFileCache
13 13
14 private constructor () { 14 private constructor () {
15 super() 15 super()
@@ -23,7 +23,9 @@ class VideosCaptionCache extends AbstractVideoStaticFileCache <string> {
23 const videoCaption = await VideoCaptionModel.loadWithVideoByFilename(filename) 23 const videoCaption = await VideoCaptionModel.loadWithVideoByFilename(filename)
24 if (!videoCaption) return undefined 24 if (!videoCaption) return undefined
25 25
26 if (videoCaption.isOwned()) return { isOwned: true, path: join(CONFIG.STORAGE.CAPTIONS_DIR, videoCaption.filename) } 26 if (videoCaption.isOwned()) {
27 return { isOwned: true, path: join(CONFIG.STORAGE.CAPTIONS_DIR, videoCaption.filename) }
28 }
27 29
28 return this.loadRemoteFile(filename) 30 return this.loadRemoteFile(filename)
29 } 31 }
@@ -55,5 +57,5 @@ class VideosCaptionCache extends AbstractVideoStaticFileCache <string> {
55} 57}
56 58
57export { 59export {
58 VideosCaptionCache 60 VideoCaptionsSimpleFileCache
59} 61}
diff --git a/server/lib/files-cache/videos-preview-cache.ts b/server/lib/files-cache/video-previews-simple-file-cache.ts
index d19c3f4f4..a05e80e16 100644
--- a/server/lib/files-cache/videos-preview-cache.ts
+++ b/server/lib/files-cache/video-previews-simple-file-cache.ts
@@ -1,15 +1,15 @@
1import { join } from 'path' 1import { join } from 'path'
2import { FILES_CACHE } from '../../initializers/constants' 2import { FILES_CACHE } from '../../initializers/constants'
3import { VideoModel } from '../../models/video/video' 3import { VideoModel } from '../../models/video/video'
4import { AbstractVideoStaticFileCache } from './abstract-video-static-file-cache' 4import { AbstractSimpleFileCache } from './shared/abstract-simple-file-cache'
5import { doRequestAndSaveToFile } from '@server/helpers/requests' 5import { doRequestAndSaveToFile } from '@server/helpers/requests'
6import { ThumbnailModel } from '@server/models/video/thumbnail' 6import { ThumbnailModel } from '@server/models/video/thumbnail'
7import { ThumbnailType } from '@shared/models' 7import { ThumbnailType } from '@shared/models'
8import { logger } from '@server/helpers/logger' 8import { logger } from '@server/helpers/logger'
9 9
10class VideosPreviewCache extends AbstractVideoStaticFileCache <string> { 10class VideoPreviewsSimpleFileCache extends AbstractSimpleFileCache <string> {
11 11
12 private static instance: VideosPreviewCache 12 private static instance: VideoPreviewsSimpleFileCache
13 13
14 private constructor () { 14 private constructor () {
15 super() 15 super()
@@ -54,5 +54,5 @@ class VideosPreviewCache extends AbstractVideoStaticFileCache <string> {
54} 54}
55 55
56export { 56export {
57 VideosPreviewCache 57 VideoPreviewsSimpleFileCache
58} 58}
diff --git a/server/lib/files-cache/videos-storyboard-cache.ts b/server/lib/files-cache/video-storyboards-simple-file-cache.ts
index b0a55104f..4cd96e70c 100644
--- a/server/lib/files-cache/videos-storyboard-cache.ts
+++ b/server/lib/files-cache/video-storyboards-simple-file-cache.ts
@@ -3,11 +3,11 @@ import { logger } from '@server/helpers/logger'
3import { doRequestAndSaveToFile } from '@server/helpers/requests' 3import { doRequestAndSaveToFile } from '@server/helpers/requests'
4import { StoryboardModel } from '@server/models/video/storyboard' 4import { StoryboardModel } from '@server/models/video/storyboard'
5import { FILES_CACHE } from '../../initializers/constants' 5import { FILES_CACHE } from '../../initializers/constants'
6import { AbstractVideoStaticFileCache } from './abstract-video-static-file-cache' 6import { AbstractSimpleFileCache } from './shared/abstract-simple-file-cache'
7 7
8class VideosStoryboardCache extends AbstractVideoStaticFileCache <string> { 8class VideoStoryboardsSimpleFileCache extends AbstractSimpleFileCache <string> {
9 9
10 private static instance: VideosStoryboardCache 10 private static instance: VideoStoryboardsSimpleFileCache
11 11
12 private constructor () { 12 private constructor () {
13 super() 13 super()
@@ -49,5 +49,5 @@ class VideosStoryboardCache extends AbstractVideoStaticFileCache <string> {
49} 49}
50 50
51export { 51export {
52 VideosStoryboardCache 52 VideoStoryboardsSimpleFileCache
53} 53}
diff --git a/server/lib/files-cache/videos-torrent-cache.ts b/server/lib/files-cache/video-torrents-simple-file-cache.ts
index a6bf98dd4..8bcd0b9bf 100644
--- a/server/lib/files-cache/videos-torrent-cache.ts
+++ b/server/lib/files-cache/video-torrents-simple-file-cache.ts
@@ -6,11 +6,11 @@ import { MVideo, MVideoFile } from '@server/types/models'
6import { CONFIG } from '../../initializers/config' 6import { CONFIG } from '../../initializers/config'
7import { FILES_CACHE } from '../../initializers/constants' 7import { FILES_CACHE } from '../../initializers/constants'
8import { VideoModel } from '../../models/video/video' 8import { VideoModel } from '../../models/video/video'
9import { AbstractVideoStaticFileCache } from './abstract-video-static-file-cache' 9import { AbstractSimpleFileCache } from './shared/abstract-simple-file-cache'
10 10
11class VideosTorrentCache extends AbstractVideoStaticFileCache <string> { 11class VideoTorrentsSimpleFileCache extends AbstractSimpleFileCache <string> {
12 12
13 private static instance: VideosTorrentCache 13 private static instance: VideoTorrentsSimpleFileCache
14 14
15 private constructor () { 15 private constructor () {
16 super() 16 super()
@@ -66,5 +66,5 @@ class VideosTorrentCache extends AbstractVideoStaticFileCache <string> {
66} 66}
67 67
68export { 68export {
69 VideosTorrentCache 69 VideoTorrentsSimpleFileCache
70} 70}