import Globals from './globals'; import { Resource, ShouldNeverHappenError } from './data-types'; export default class ResourceRAMCache { private data = new Map(); // (guildId, resourceId) -> { resource, lastUsed } private size = 0; public putResource(guildId: number, resource: Resource): void { if (resource.data.length > Globals.MAX_RESOURCE_SIZE) { // skip resources if they would flood the cache return; } let id = `s#${guildId}/r#${resource.id}`; this.data.set(id, { resource: resource, lastUsed: new Date() }); this.size += resource.data.length; if (this.size > Globals.MAX_GUILD_RESOURCE_CACHE_SIZE) { // TODO: this feature needs to be tested let entries = Array.from(this.data.entries()) .map(([ key, value ]) => { return { id: key, value: value }; }) .sort((a, b) => b.value.lastUsed.getTime() - a.value.lastUsed.getTime()); // oldest last (for pop) while (this.size > Globals.MAX_GUILD_RESOURCE_CACHE_SIZE) { let entry = entries.pop(); if (entry === undefined) throw new ShouldNeverHappenError('No entry in the array but the ram cache still has a size...'); this.data.delete(entry.id); this.size -= entry.value.resource.data.length; } } } public getResource(guildId: number, resourceId: string): Resource | null { let id = `s#${guildId}/r#${resourceId}`; let v = this.data.get(id); if (!v) return null; v.lastUsed = new Date(); return v.resource; } }