import {Cache, Collection, Awaitable} from '../../util' /** * An in-memory implementation of the Cache. * This is the default implementation for compatibility, but applications should switch to a persistent-backed cache driver. */ export class MemoryCache extends Cache { /** Static collection of in-memory cache items. */ private static cacheItems: Collection<{key: string, value: string, expires?: Date}> = new Collection<{key: string; value: string, expires?: Date}>() /** Static collection of in-memory arrays. */ private static cacheArrays: Collection<{key: string, values: string[]}> = new Collection<{key: string; values: string[]}>() public fetch(key: string): string|undefined { const now = new Date() return MemoryCache.cacheItems .where('key', '=', key) .firstWhere(item => { return !item.expires || now < item.expires })?.value } public put(key: string, value: string, expires?: Date): Awaitable { const existing = MemoryCache.cacheItems.firstWhere('key', '=', key) if ( existing ) { existing.value = value existing.expires = expires } else { MemoryCache.cacheItems.push({ key, value, expires }) } } public has(key: string): Awaitable { const now = new Date() return Boolean(MemoryCache.cacheItems .where('key', '=', key) .firstWhere(item => { return !item.expires || now < item.expires })) } public drop(key: string): Awaitable { MemoryCache.cacheItems = MemoryCache.cacheItems.where('key', '!=', key) } public decrement(key: string, amount = 1): Awaitable { const nextValue = (parseInt(this.fetch(key) ?? '0', 10) ?? 0) - amount this.put(key, String(nextValue)) return nextValue } public increment(key: string, amount = 1): Awaitable { const nextValue = (parseInt(this.fetch(key) ?? '0', 10) ?? 0) + amount this.put(key, String(nextValue)) return nextValue } public pop(key: string): Awaitable { const value = this.fetch(key) this.drop(key) return value } public arrayPop(key: string): Awaitable { const arr = MemoryCache.cacheArrays.firstWhere('key', '=', key) if ( arr ) { return arr.values.shift() } } public arrayPush(key: string, value: string): Awaitable { const arr = MemoryCache.cacheArrays.firstWhere('key', '=', key) if ( arr ) { arr.values.push(value) } else { MemoryCache.cacheArrays.push({ key, values: [value], }) } } }