From f981dae8617271a2dc713bb683951730b306e0c5 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 12 Jul 2017 11:56:02 +0200 Subject: Add previews cache system between pods --- server/lib/cache/index.ts | 1 + server/lib/cache/videos-preview-cache.ts | 74 ++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 server/lib/cache/index.ts create mode 100644 server/lib/cache/videos-preview-cache.ts (limited to 'server/lib/cache') diff --git a/server/lib/cache/index.ts b/server/lib/cache/index.ts new file mode 100644 index 000000000..7bf63790a --- /dev/null +++ b/server/lib/cache/index.ts @@ -0,0 +1 @@ +export * from './videos-preview-cache' diff --git a/server/lib/cache/videos-preview-cache.ts b/server/lib/cache/videos-preview-cache.ts new file mode 100644 index 000000000..9d365e496 --- /dev/null +++ b/server/lib/cache/videos-preview-cache.ts @@ -0,0 +1,74 @@ +import * as request from 'request' +import * as asyncLRU from 'async-lru' +import { join } from 'path' +import { createWriteStream } from 'fs' +import * as Promise from 'bluebird' + +import { database as db, CONFIG, CACHE } from '../../initializers' +import { logger, writeFilePromise, unlinkPromise } from '../../helpers' +import { VideoInstance } from '../../models' +import { fetchRemotePreview } from '../../lib' + +class VideosPreviewCache { + + private static instance: VideosPreviewCache + + private lru + + private constructor () { } + + static get Instance () { + return this.instance || (this.instance = new this()) + } + + init (max: number) { + this.lru = new asyncLRU({ + max, + load: (key, cb) => { + this.loadPreviews(key) + .then(res => cb(null, res)) + .catch(err => cb(err)) + } + }) + + this.lru.on('evict', (obj: { key: string, value: string }) => { + unlinkPromise(obj.value).then(() => logger.debug('%s evicted from VideosPreviewCache', obj.value)) + }) + } + + getPreviewPath (key: string) { + return new Promise((res, rej) => { + this.lru.get(key, (err, value) => { + err ? rej(err) : res(value) + }) + }) + } + + private loadPreviews (key: string) { + return db.Video.loadByUUIDAndPopulateAuthorAndPodAndTags(key) + .then(video => { + if (!video) return undefined + + if (video.isOwned()) return join(CONFIG.STORAGE.PREVIEWS_DIR, video.getPreviewName()) + + return this.saveRemotePreviewAndReturnPath(video) + }) + } + + private saveRemotePreviewAndReturnPath (video: VideoInstance) { + const req = fetchRemotePreview(video.Author.Pod, video) + + return new Promise((res, rej) => { + const path = join(CACHE.DIRECTORIES.PREVIEWS, video.getPreviewName()) + const stream = createWriteStream(path) + + req.pipe(stream) + .on('finish', () => res(path)) + .on('error', (err) => rej(err)) + }) + } +} + +export { + VideosPreviewCache +} -- cgit v1.2.3