From 04c7e61fc076e2fa5ddf3d0faf6ebb73f4d52d82 Mon Sep 17 00:00:00 2001 From: Max Isom Date: Thu, 18 Nov 2021 20:55:57 -0500 Subject: Add FileCache model --- src/services/cache.ts | 56 ----------------------------------------- src/services/get-songs.ts | 6 ++--- src/services/key-value-cache.ts | 56 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 59 deletions(-) delete mode 100644 src/services/cache.ts create mode 100644 src/services/key-value-cache.ts (limited to 'src/services') diff --git a/src/services/cache.ts b/src/services/cache.ts deleted file mode 100644 index 95c6731..0000000 --- a/src/services/cache.ts +++ /dev/null @@ -1,56 +0,0 @@ -import {injectable} from 'inversify'; -import {KeyValueCache} from '../models/index.js'; -import debug from '../utils/debug.js'; - -type Seconds = number; - -type Options = { - expiresIn: Seconds; - key?: string; -}; - -const futureTimeToDate = (time: Seconds) => new Date(new Date().getTime() + (time * 1000)); - -@injectable() -export default class CacheProvider { - async wrap(func: (...options: any) => Promise, ...options: T): Promise { - if (options.length === 0) { - throw new Error('Missing cache options'); - } - - const functionArgs = options.slice(0, options.length - 1); - - const { - key = JSON.stringify(functionArgs), - expiresIn, - } = options[options.length - 1] as Options; - - if (key.length < 4) { - throw new Error(`Cache key ${key} is too short.`); - } - - const cachedResult = await KeyValueCache.findByPk(key); - - if (cachedResult) { - if (new Date() < cachedResult.expiresAt) { - debug(`Cache hit: ${key}`); - return JSON.parse(cachedResult.value) as F; - } - - await cachedResult.destroy(); - } - - debug(`Cache miss: ${key}`); - - const result = await func(...options as any[]); - - // Save result - await KeyValueCache.upsert({ - key, - value: JSON.stringify(result), - expiresAt: futureTimeToDate(expiresIn), - }); - - return result; - } -} diff --git a/src/services/get-songs.ts b/src/services/get-songs.ts index ba4401c..e7e3d5a 100644 --- a/src/services/get-songs.ts +++ b/src/services/get-songs.ts @@ -14,7 +14,7 @@ import {TYPES} from '../types.js'; import {cleanUrl} from '../utils/url.js'; import ThirdParty from './third-party.js'; import Config from './config.js'; -import CacheProvider from './cache.js'; +import KeyValueCacheProvider from './key-value-cache.js'; type QueuedSongWithoutChannel = Except; @@ -26,14 +26,14 @@ export default class { private readonly youtube: YouTube; private readonly youtubeKey: string; private readonly spotify: Spotify; - private readonly cache: CacheProvider; + private readonly cache: KeyValueCacheProvider; private readonly ytsrQueue: PQueue; constructor( @inject(TYPES.ThirdParty) thirdParty: ThirdParty, @inject(TYPES.Config) config: Config, - @inject(TYPES.Cache) cache: CacheProvider) { + @inject(TYPES.KeyValueCache) cache: KeyValueCacheProvider) { this.youtube = thirdParty.youtube; this.youtubeKey = config.YOUTUBE_API_KEY; this.spotify = thirdParty.spotify; diff --git a/src/services/key-value-cache.ts b/src/services/key-value-cache.ts new file mode 100644 index 0000000..7f1164d --- /dev/null +++ b/src/services/key-value-cache.ts @@ -0,0 +1,56 @@ +import {injectable} from 'inversify'; +import {KeyValueCache} from '../models/index.js'; +import debug from '../utils/debug.js'; + +type Seconds = number; + +type Options = { + expiresIn: Seconds; + key?: string; +}; + +const futureTimeToDate = (time: Seconds) => new Date(new Date().getTime() + (time * 1000)); + +@injectable() +export default class KeyValueCacheProvider { + async wrap(func: (...options: any) => Promise, ...options: T): Promise { + if (options.length === 0) { + throw new Error('Missing cache options'); + } + + const functionArgs = options.slice(0, options.length - 1); + + const { + key = JSON.stringify(functionArgs), + expiresIn, + } = options[options.length - 1] as Options; + + if (key.length < 4) { + throw new Error(`Cache key ${key} is too short.`); + } + + const cachedResult = await KeyValueCache.findByPk(key); + + if (cachedResult) { + if (new Date() < cachedResult.expiresAt) { + debug(`Cache hit: ${key}`); + return JSON.parse(cachedResult.value) as F; + } + + await cachedResult.destroy(); + } + + debug(`Cache miss: ${key}`); + + const result = await func(...options as any[]); + + // Save result + await KeyValueCache.upsert({ + key, + value: JSON.stringify(result), + expiresAt: futureTimeToDate(expiresIn), + }); + + return result; + } +} -- cgit v1.2.3