diff options
Diffstat (limited to 'server/lib/files-cache')
-rw-r--r-- | server/lib/files-cache/avatar-permanent-file-cache.ts | 27 | ||||
-rw-r--r-- | server/lib/files-cache/index.ts | 9 | ||||
-rw-r--r-- | server/lib/files-cache/shared/abstract-permanent-file-cache.ts | 119 | ||||
-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.ts | 2 | ||||
-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 @@ | |||
1 | import { ACTOR_IMAGES_SIZE } from '@server/initializers/constants' | ||
2 | import { ActorImageModel } from '@server/models/actor/actor-image' | ||
3 | import { MActorImage } from '@server/types/models' | ||
4 | import { AbstractPermanentFileCache } from './shared' | ||
5 | import { CONFIG } from '@server/initializers/config' | ||
6 | |||
7 | export 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 @@ | |||
1 | export * from './videos-caption-cache' | 1 | export * from './avatar-permanent-file-cache' |
2 | export * from './videos-preview-cache' | 2 | export * from './video-captions-simple-file-cache' |
3 | export * from './videos-storyboard-cache' | 3 | export * from './video-previews-simple-file-cache' |
4 | export * from './videos-torrent-cache' | 4 | export * from './video-storyboards-simple-file-cache' |
5 | export * 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 @@ | |||
1 | import express from 'express' | ||
2 | import { LRUCache } from 'lru-cache' | ||
3 | import { logger } from '@server/helpers/logger' | ||
4 | import { LRU_CACHE, STATIC_MAX_AGE } from '@server/initializers/constants' | ||
5 | import { downloadImageFromWorker } from '@server/lib/worker/parent-process' | ||
6 | import { HttpStatusCode } from '@shared/models' | ||
7 | import { Model } from 'sequelize' | ||
8 | |||
9 | type ImageModel = { | ||
10 | fileUrl: string | ||
11 | filename: string | ||
12 | onDisk: boolean | ||
13 | |||
14 | isOwned (): boolean | ||
15 | getPath (): string | ||
16 | |||
17 | save (): Promise<Model> | ||
18 | } | ||
19 | |||
20 | export 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 @@ | |||
1 | import { remove } from 'fs-extra' | 1 | import { remove } from 'fs-extra' |
2 | import { logger } from '../../helpers/logger' | 2 | import { logger } from '../../../helpers/logger' |
3 | import memoizee from 'memoizee' | 3 | import memoizee from 'memoizee' |
4 | 4 | ||
5 | type GetFilePathResult = { isOwned: boolean, path: string, downloadName?: string } | undefined | 5 | type GetFilePathResult = { isOwned: boolean, path: string, downloadName?: string } | undefined |
6 | 6 | ||
7 | export abstract class AbstractVideoStaticFileCache <T> { | 7 | export 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 @@ | |||
1 | export * from './abstract-permanent-file-cache' | ||
2 | export * 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' | |||
5 | import { FILES_CACHE } from '../../initializers/constants' | 5 | import { FILES_CACHE } from '../../initializers/constants' |
6 | import { VideoModel } from '../../models/video/video' | 6 | import { VideoModel } from '../../models/video/video' |
7 | import { VideoCaptionModel } from '../../models/video/video-caption' | 7 | import { VideoCaptionModel } from '../../models/video/video-caption' |
8 | import { AbstractVideoStaticFileCache } from './abstract-video-static-file-cache' | 8 | import { AbstractSimpleFileCache } from './shared/abstract-simple-file-cache' |
9 | 9 | ||
10 | class VideosCaptionCache extends AbstractVideoStaticFileCache <string> { | 10 | class 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 | ||
57 | export { | 59 | export { |
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 @@ | |||
1 | import { join } from 'path' | 1 | import { join } from 'path' |
2 | import { FILES_CACHE } from '../../initializers/constants' | 2 | import { FILES_CACHE } from '../../initializers/constants' |
3 | import { VideoModel } from '../../models/video/video' | 3 | import { VideoModel } from '../../models/video/video' |
4 | import { AbstractVideoStaticFileCache } from './abstract-video-static-file-cache' | 4 | import { AbstractSimpleFileCache } from './shared/abstract-simple-file-cache' |
5 | import { doRequestAndSaveToFile } from '@server/helpers/requests' | 5 | import { doRequestAndSaveToFile } from '@server/helpers/requests' |
6 | import { ThumbnailModel } from '@server/models/video/thumbnail' | 6 | import { ThumbnailModel } from '@server/models/video/thumbnail' |
7 | import { ThumbnailType } from '@shared/models' | 7 | import { ThumbnailType } from '@shared/models' |
8 | import { logger } from '@server/helpers/logger' | 8 | import { logger } from '@server/helpers/logger' |
9 | 9 | ||
10 | class VideosPreviewCache extends AbstractVideoStaticFileCache <string> { | 10 | class 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 | ||
56 | export { | 56 | export { |
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' | |||
3 | import { doRequestAndSaveToFile } from '@server/helpers/requests' | 3 | import { doRequestAndSaveToFile } from '@server/helpers/requests' |
4 | import { StoryboardModel } from '@server/models/video/storyboard' | 4 | import { StoryboardModel } from '@server/models/video/storyboard' |
5 | import { FILES_CACHE } from '../../initializers/constants' | 5 | import { FILES_CACHE } from '../../initializers/constants' |
6 | import { AbstractVideoStaticFileCache } from './abstract-video-static-file-cache' | 6 | import { AbstractSimpleFileCache } from './shared/abstract-simple-file-cache' |
7 | 7 | ||
8 | class VideosStoryboardCache extends AbstractVideoStaticFileCache <string> { | 8 | class 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 | ||
51 | export { | 51 | export { |
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' | |||
6 | import { CONFIG } from '../../initializers/config' | 6 | import { CONFIG } from '../../initializers/config' |
7 | import { FILES_CACHE } from '../../initializers/constants' | 7 | import { FILES_CACHE } from '../../initializers/constants' |
8 | import { VideoModel } from '../../models/video/video' | 8 | import { VideoModel } from '../../models/video/video' |
9 | import { AbstractVideoStaticFileCache } from './abstract-video-static-file-cache' | 9 | import { AbstractSimpleFileCache } from './shared/abstract-simple-file-cache' |
10 | 10 | ||
11 | class VideosTorrentCache extends AbstractVideoStaticFileCache <string> { | 11 | class 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 | ||
68 | export { | 68 | export { |
69 | VideosTorrentCache | 69 | VideoTorrentsSimpleFileCache |
70 | } | 70 | } |