75 lines
1.6 KiB
TypeScript
75 lines
1.6 KiB
TypeScript
export interface ICacheEntry<T> {
|
|
data: T;
|
|
timestamp: number;
|
|
}
|
|
|
|
export class MetricsCache {
|
|
private cache = new Map<string, ICacheEntry<any>>();
|
|
private readonly defaultTTL: number;
|
|
|
|
constructor(defaultTTL: number = 500) {
|
|
this.defaultTTL = defaultTTL;
|
|
}
|
|
|
|
/**
|
|
* Get cached data or compute and cache it
|
|
*/
|
|
public get<T>(key: string, computeFn: () => T | Promise<T>, ttl?: number): T | Promise<T> {
|
|
const cached = this.cache.get(key);
|
|
const now = Date.now();
|
|
const actualTTL = ttl ?? this.defaultTTL;
|
|
|
|
if (cached && (now - cached.timestamp) < actualTTL) {
|
|
return cached.data;
|
|
}
|
|
|
|
const result = computeFn();
|
|
|
|
// Handle both sync and async compute functions
|
|
if (result instanceof Promise) {
|
|
return result.then(data => {
|
|
this.cache.set(key, { data, timestamp: now });
|
|
return data;
|
|
});
|
|
} else {
|
|
this.cache.set(key, { data: result, timestamp: now });
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Invalidate a specific cache entry
|
|
*/
|
|
public invalidate(key: string): void {
|
|
this.cache.delete(key);
|
|
}
|
|
|
|
/**
|
|
* Clear all cache entries
|
|
*/
|
|
public clear(): void {
|
|
this.cache.clear();
|
|
}
|
|
|
|
/**
|
|
* Get cache statistics
|
|
*/
|
|
public getStats(): { size: number; keys: string[] } {
|
|
return {
|
|
size: this.cache.size,
|
|
keys: Array.from(this.cache.keys())
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Clean up expired entries
|
|
*/
|
|
public cleanup(): void {
|
|
const now = Date.now();
|
|
for (const [key, entry] of this.cache.entries()) {
|
|
if (now - entry.timestamp > this.defaultTTL) {
|
|
this.cache.delete(key);
|
|
}
|
|
}
|
|
}
|
|
} |