sheetjs-vscode-extension/src/cacheManagement/lruCache.ts

126 lines
2.7 KiB
TypeScript
Raw Normal View History

/**
* generic Least Recently Used (LRU) cache implementation
*/
export class LRUCache<K, V> {
private cache = new Map<K, V>();
private accessTimes = new Map<K, number>();
private readonly maxSize: number;
/**
* create a new LRU cache
* @param maxSize Maximum number of items to store in the cache
*/
constructor(maxSize: number) {
this.maxSize = maxSize;
}
/**
* get an item from the cache
* @param key cache key
* @returns cached value or undefined if not found
*/
get(key: K): V | undefined {
if (!this.cache.has(key)) {
return undefined;
}
2026-01-12 23:19:57 +00:00
// update access time
this.accessTimes.set(key, Date.now());
return this.cache.get(key);
}
/**
* store an item in the cache
* @param key cache key
* @param value value to cache
*/
set(key: K, value: V): void {
// check if we need to make room
if (!this.cache.has(key) && this.cache.size >= this.maxSize) {
this.evictLeastRecentlyUsed();
}
2026-01-12 23:19:57 +00:00
// store the value and update access time
this.cache.set(key, value);
this.accessTimes.set(key, Date.now());
}
/**
* check if an item exists in the cache
* @param key The cache key
* @returns True if the item exists
*/
has(key: K): boolean {
return this.cache.has(key);
}
/**
* remove an item from the cache
* @param key key to remove
* @returns True if an item was removed
*/
delete(key: K): boolean {
this.accessTimes.delete(key);
return this.cache.delete(key);
}
/**
* get all keys in the cache
* @returns Array of cache keys
*/
keys(): K[] {
return [...this.cache.keys()];
}
/**
* get the current size of the cache
*/
get size(): number {
return this.cache.size;
}
/**
* clear all items from the cache
*/
clear(): void {
this.cache.clear();
this.accessTimes.clear();
}
/**
* remove items matching a prefix
* @param predicate Function that returns true for keys to remove
*/
deleteByPredicate(predicate: (key: K) => boolean): void {
for (const key of this.keys()) {
if (predicate(key)) {
this.delete(key);
}
}
}
/**
* remove the least recently used item from the cache
* @private
*/
private evictLeastRecentlyUsed(): void {
if (this.cache.size === 0) { return; }
2026-01-12 23:19:57 +00:00
// find the oldest entry
let oldestKey: K | undefined;
let oldestTime = Infinity;
2026-01-12 23:19:57 +00:00
for (const [key, time] of this.accessTimes.entries()) {
if (time < oldestTime) {
oldestTime = time;
oldestKey = key;
}
}
2026-01-12 23:19:57 +00:00
// remove the oldest entry
if (oldestKey !== undefined) {
console.log(`Evicting least recently used cache entry: ${String(oldestKey)}`);
this.delete(oldestKey);
}
}
}