diff options
author | Chocobozzz <me@florianbigard.com> | 2023-06-06 15:59:51 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2023-06-29 10:19:33 +0200 |
commit | f162d32da098aa55f6de2367142faa166edb7c08 (patch) | |
tree | 31c6a96972994171853cb6c4e0b88b63241f8979 /server/controllers/lazy-static.ts | |
parent | a673d9e848e51186602548a621e05925663b98be (diff) | |
download | PeerTube-f162d32da098aa55f6de2367142faa166edb7c08.tar.gz PeerTube-f162d32da098aa55f6de2367142faa166edb7c08.tar.zst PeerTube-f162d32da098aa55f6de2367142faa166edb7c08.zip |
Support lazy download thumbnails
Diffstat (limited to 'server/controllers/lazy-static.ts')
-rw-r--r-- | server/controllers/lazy-static.ts | 100 |
1 files changed, 28 insertions, 72 deletions
diff --git a/server/controllers/lazy-static.ts b/server/controllers/lazy-static.ts index 6ffd39730..8e18b0642 100644 --- a/server/controllers/lazy-static.ts +++ b/server/controllers/lazy-static.ts | |||
@@ -1,14 +1,27 @@ | |||
1 | import cors from 'cors' | 1 | import cors from 'cors' |
2 | import express from 'express' | 2 | import express from 'express' |
3 | import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache' | 3 | import { CONFIG } from '@server/initializers/config' |
4 | import { MActorImage } from '@server/types/models' | ||
5 | import { HttpStatusCode } from '../../shared/models/http/http-error-codes' | 4 | import { HttpStatusCode } from '../../shared/models/http/http-error-codes' |
6 | import { logger } from '../helpers/logger' | 5 | import { FILES_CACHE, LAZY_STATIC_PATHS, STATIC_MAX_AGE } from '../initializers/constants' |
7 | import { ACTOR_IMAGES_SIZE, LAZY_STATIC_PATHS, STATIC_MAX_AGE } from '../initializers/constants' | 6 | import { |
8 | import { VideosCaptionCache, VideosPreviewCache, VideosStoryboardCache } from '../lib/files-cache' | 7 | AvatarPermanentFileCache, |
9 | import { actorImagePathUnsafeCache, downloadActorImageFromWorker } from '../lib/local-actor' | 8 | VideoCaptionsSimpleFileCache, |
9 | VideoPreviewsSimpleFileCache, | ||
10 | VideoStoryboardsSimpleFileCache, | ||
11 | VideoTorrentsSimpleFileCache | ||
12 | } from '../lib/files-cache' | ||
10 | import { asyncMiddleware, handleStaticError } from '../middlewares' | 13 | import { asyncMiddleware, handleStaticError } from '../middlewares' |
11 | import { ActorImageModel } from '../models/actor/actor-image' | 14 | |
15 | // --------------------------------------------------------------------------- | ||
16 | // Cache initializations | ||
17 | // --------------------------------------------------------------------------- | ||
18 | |||
19 | VideoPreviewsSimpleFileCache.Instance.init(CONFIG.CACHE.PREVIEWS.SIZE, FILES_CACHE.PREVIEWS.MAX_AGE) | ||
20 | VideoCaptionsSimpleFileCache.Instance.init(CONFIG.CACHE.VIDEO_CAPTIONS.SIZE, FILES_CACHE.VIDEO_CAPTIONS.MAX_AGE) | ||
21 | VideoTorrentsSimpleFileCache.Instance.init(CONFIG.CACHE.TORRENTS.SIZE, FILES_CACHE.TORRENTS.MAX_AGE) | ||
22 | VideoStoryboardsSimpleFileCache.Instance.init(CONFIG.CACHE.STORYBOARDS.SIZE, FILES_CACHE.STORYBOARDS.MAX_AGE) | ||
23 | |||
24 | // --------------------------------------------------------------------------- | ||
12 | 25 | ||
13 | const lazyStaticRouter = express.Router() | 26 | const lazyStaticRouter = express.Router() |
14 | 27 | ||
@@ -60,94 +73,37 @@ export { | |||
60 | 73 | ||
61 | // --------------------------------------------------------------------------- | 74 | // --------------------------------------------------------------------------- |
62 | 75 | ||
63 | async function getActorImage (req: express.Request, res: express.Response, next: express.NextFunction) { | 76 | const avatarPermanentFileCache = new AvatarPermanentFileCache() |
64 | const filename = req.params.filename | ||
65 | |||
66 | if (actorImagePathUnsafeCache.has(filename)) { | ||
67 | return res.sendFile(actorImagePathUnsafeCache.get(filename), { maxAge: STATIC_MAX_AGE.SERVER }) | ||
68 | } | ||
69 | |||
70 | const image = await ActorImageModel.loadByName(filename) | ||
71 | if (!image) return res.status(HttpStatusCode.NOT_FOUND_404).end() | ||
72 | |||
73 | if (image.onDisk === false) { | ||
74 | if (!image.fileUrl) return res.status(HttpStatusCode.NOT_FOUND_404).end() | ||
75 | |||
76 | logger.info('Lazy serve remote actor image %s.', image.fileUrl) | ||
77 | 77 | ||
78 | try { | 78 | function getActorImage (req: express.Request, res: express.Response, next: express.NextFunction) { |
79 | await downloadActorImageFromWorker({ | 79 | const filename = req.params.filename |
80 | filename: image.filename, | ||
81 | fileUrl: image.fileUrl, | ||
82 | size: getActorImageSize(image), | ||
83 | type: image.type | ||
84 | }) | ||
85 | } catch (err) { | ||
86 | logger.warn('Cannot process remote actor image %s.', image.fileUrl, { err }) | ||
87 | return res.status(HttpStatusCode.NOT_FOUND_404).end() | ||
88 | } | ||
89 | |||
90 | image.onDisk = true | ||
91 | image.save() | ||
92 | .catch(err => logger.error('Cannot save new actor image disk state.', { err })) | ||
93 | } | ||
94 | |||
95 | const path = image.getPath() | ||
96 | |||
97 | actorImagePathUnsafeCache.set(filename, path) | ||
98 | |||
99 | return res.sendFile(path, { maxAge: STATIC_MAX_AGE.LAZY_SERVER }, (err: any) => { | ||
100 | if (!err) return | ||
101 | |||
102 | // It seems this actor image is not on the disk anymore | ||
103 | if (err.status === HttpStatusCode.NOT_FOUND_404 && !image.isOwned()) { | ||
104 | logger.error('Cannot lazy serve actor image %s.', filename, { err }) | ||
105 | |||
106 | actorImagePathUnsafeCache.delete(filename) | ||
107 | |||
108 | image.onDisk = false | ||
109 | image.save() | ||
110 | .catch(err => logger.error('Cannot save new actor image disk state.', { err })) | ||
111 | } | ||
112 | |||
113 | return next(err) | ||
114 | }) | ||
115 | } | ||
116 | |||
117 | function getActorImageSize (image: MActorImage): { width: number, height: number } { | ||
118 | if (image.width && image.height) { | ||
119 | return { | ||
120 | height: image.height, | ||
121 | width: image.width | ||
122 | } | ||
123 | } | ||
124 | 80 | ||
125 | return ACTOR_IMAGES_SIZE[image.type][0] | 81 | return avatarPermanentFileCache.lazyServe({ filename, res, next }) |
126 | } | 82 | } |
127 | 83 | ||
128 | async function getPreview (req: express.Request, res: express.Response) { | 84 | async function getPreview (req: express.Request, res: express.Response) { |
129 | const result = await VideosPreviewCache.Instance.getFilePath(req.params.filename) | 85 | const result = await VideoPreviewsSimpleFileCache.Instance.getFilePath(req.params.filename) |
130 | if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end() | 86 | if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end() |
131 | 87 | ||
132 | return res.sendFile(result.path, { maxAge: STATIC_MAX_AGE.LAZY_SERVER }) | 88 | return res.sendFile(result.path, { maxAge: STATIC_MAX_AGE.LAZY_SERVER }) |
133 | } | 89 | } |
134 | 90 | ||
135 | async function getStoryboard (req: express.Request, res: express.Response) { | 91 | async function getStoryboard (req: express.Request, res: express.Response) { |
136 | const result = await VideosStoryboardCache.Instance.getFilePath(req.params.filename) | 92 | const result = await VideoStoryboardsSimpleFileCache.Instance.getFilePath(req.params.filename) |
137 | if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end() | 93 | if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end() |
138 | 94 | ||
139 | return res.sendFile(result.path, { maxAge: STATIC_MAX_AGE.LAZY_SERVER }) | 95 | return res.sendFile(result.path, { maxAge: STATIC_MAX_AGE.LAZY_SERVER }) |
140 | } | 96 | } |
141 | 97 | ||
142 | async function getVideoCaption (req: express.Request, res: express.Response) { | 98 | async function getVideoCaption (req: express.Request, res: express.Response) { |
143 | const result = await VideosCaptionCache.Instance.getFilePath(req.params.filename) | 99 | const result = await VideoCaptionsSimpleFileCache.Instance.getFilePath(req.params.filename) |
144 | if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end() | 100 | if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end() |
145 | 101 | ||
146 | return res.sendFile(result.path, { maxAge: STATIC_MAX_AGE.LAZY_SERVER }) | 102 | return res.sendFile(result.path, { maxAge: STATIC_MAX_AGE.LAZY_SERVER }) |
147 | } | 103 | } |
148 | 104 | ||
149 | async function getTorrent (req: express.Request, res: express.Response) { | 105 | async function getTorrent (req: express.Request, res: express.Response) { |
150 | const result = await VideosTorrentCache.Instance.getFilePath(req.params.filename) | 106 | const result = await VideoTorrentsSimpleFileCache.Instance.getFilePath(req.params.filename) |
151 | if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end() | 107 | if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end() |
152 | 108 | ||
153 | // Torrents still use the old naming convention (video uuid + .torrent) | 109 | // Torrents still use the old naming convention (video uuid + .torrent) |