Open source vector database with HNSW indexing, graph relationships, and metadata facets. Features CLI with professional augmentation registry integration for discovering extensions and capabilities.
119 lines
No EOL
3.3 KiB
JavaScript
119 lines
No EOL
3.3 KiB
JavaScript
/**
|
|
* MetadataIndexCache - Caches metadata index data for improved performance
|
|
* Reuses the same pattern as SearchCache for consistency
|
|
*/
|
|
export class MetadataIndexCache {
|
|
constructor(config = {}) {
|
|
this.cache = new Map();
|
|
// Cache statistics
|
|
this.hits = 0;
|
|
this.misses = 0;
|
|
this.evictions = 0;
|
|
this.maxAge = config.maxAge ?? 5 * 60 * 1000; // 5 minutes
|
|
this.maxSize = config.maxSize ?? 500; // More entries than SearchCache since indexes are smaller
|
|
this.enabled = config.enabled ?? true;
|
|
this.hitCountWeight = config.hitCountWeight ?? 0.3;
|
|
}
|
|
/**
|
|
* Get cached entry
|
|
*/
|
|
get(key) {
|
|
if (!this.enabled)
|
|
return undefined;
|
|
const entry = this.cache.get(key);
|
|
if (!entry) {
|
|
this.misses++;
|
|
return undefined;
|
|
}
|
|
// Check if entry is expired
|
|
if (Date.now() - entry.timestamp > this.maxAge) {
|
|
this.cache.delete(key);
|
|
this.misses++;
|
|
return undefined;
|
|
}
|
|
// Update hit count
|
|
entry.hits++;
|
|
this.hits++;
|
|
return entry.data;
|
|
}
|
|
/**
|
|
* Set cache entry
|
|
*/
|
|
set(key, data) {
|
|
if (!this.enabled)
|
|
return;
|
|
// Evict entries if at max size
|
|
if (this.cache.size >= this.maxSize) {
|
|
this.evictLeastValuable();
|
|
}
|
|
this.cache.set(key, {
|
|
data,
|
|
timestamp: Date.now(),
|
|
hits: 0
|
|
});
|
|
}
|
|
/**
|
|
* Evict least valuable entry based on age and hit count
|
|
*/
|
|
evictLeastValuable() {
|
|
let leastValuableKey = null;
|
|
let lowestScore = Infinity;
|
|
for (const [key, entry] of this.cache.entries()) {
|
|
const age = Date.now() - entry.timestamp;
|
|
const ageScore = age / this.maxAge;
|
|
const hitScore = entry.hits * this.hitCountWeight;
|
|
const score = hitScore - ageScore;
|
|
if (score < lowestScore) {
|
|
lowestScore = score;
|
|
leastValuableKey = key;
|
|
}
|
|
}
|
|
if (leastValuableKey) {
|
|
this.cache.delete(leastValuableKey);
|
|
this.evictions++;
|
|
}
|
|
}
|
|
/**
|
|
* Invalidate cache entries matching a pattern
|
|
*/
|
|
invalidatePattern(pattern) {
|
|
const keysToDelete = [];
|
|
for (const key of this.cache.keys()) {
|
|
if (key.includes(pattern)) {
|
|
keysToDelete.push(key);
|
|
}
|
|
}
|
|
keysToDelete.forEach(key => this.cache.delete(key));
|
|
}
|
|
/**
|
|
* Clear all cache entries
|
|
*/
|
|
clear() {
|
|
this.cache.clear();
|
|
}
|
|
/**
|
|
* Get cache statistics
|
|
*/
|
|
getStats() {
|
|
return {
|
|
size: this.cache.size,
|
|
hits: this.hits,
|
|
misses: this.misses,
|
|
hitRate: this.hits / (this.hits + this.misses) || 0,
|
|
evictions: this.evictions
|
|
};
|
|
}
|
|
/**
|
|
* Get estimated memory usage
|
|
*/
|
|
getMemoryUsage() {
|
|
// Rough estimate: 100 bytes per entry + data size
|
|
let totalSize = 0;
|
|
for (const entry of this.cache.values()) {
|
|
totalSize += 100; // Base overhead
|
|
totalSize += JSON.stringify(entry.data).length * 2; // Unicode chars
|
|
}
|
|
return totalSize;
|
|
}
|
|
}
|
|
//# sourceMappingURL=metadataIndexCache.js.map
|