0.1.2•Updated a month ago
// deno-lint-ignore-file no-explicit-any
interface MemCacheEntry<T = any> {
expires_at: number
data: T
}
export class MemCache<T = any> {
readonly expiration_period_seconds: number
readonly interval_ms: number
private interval_id!: number
/**
* Creates a new non-persistent cache.
*
* @param expiration_period_seconds How long an entry should be kept in this cache.
* @param clean_interval_seconds How frequently this cache should be checked for stale entries and cleaned up.
*/
constructor(expiration_period_seconds: number = 60, clean_interval_seconds: number = 10) {
this.expiration_period_seconds = expiration_period_seconds;
this.interval_ms = clean_interval_seconds * 1000;
if(!Deno.args.includes('build')) this.queue();
}
private _entries: Map<string, MemCacheEntry<T>> = new Map<string, MemCacheEntry<T>>()
/**
* Get the value of a cached item
*/
get(key: string): T | null {
if(!this._entries.has(key)) return null;
const entry = this._entries.get(key)!;
entry.expires_at = Date.now();
return entry.data as T;
}
/**
* Checks whether a cached item exists
*/
has(key: string) {
return this._entries.has(key);
}
/**
* Sets the cached item and returns it
*/
set(key: string, value: T) {
this._entries.set(key, { data: value, expires_at: Date.now() + this.expiration_period_seconds * 1000 });
return value;
}
/**
* Removes the cached item and returns it (if it exists)
*/
delete(key: string) {
if(!this._entries.has(key)) return null;
const value = this.get(key);
this._entries.delete(key);
return value;
}
private queue() {
this.interval_id = setTimeout(this.clean.bind(this), this.interval_ms);
}
private clean() {
clearTimeout(this.interval_id);
const expiration_timestamp = Date.now();
for(const [key, { expires_at }] of Object.entries(this._entries)) {
if(expires_at < expiration_timestamp) this._entries.delete(key);
}
this.queue();
}
}