limitless-ai-mcp-server
Version:
MCP server for integrating Limitless AI Pendant recordings with AI assistants
151 lines • 4.85 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.searchCache = exports.lifelogArrayCache = exports.lifelogCache = exports.LRUCache = void 0;
exports.buildLifelogCacheKey = buildLifelogCacheKey;
exports.buildDateCacheKey = buildDateCacheKey;
exports.buildSearchCacheKey = buildSearchCacheKey;
exports.buildRecentCacheKey = buildRecentCacheKey;
const logger_1 = require("../utils/logger");
class LRUCache {
cache;
options;
_stats;
constructor(options = {}) {
this.options = {
maxSize: options.maxSize || 100,
ttl: options.ttl || 5 * 60 * 1000, // 5 minutes default
onEvict: options.onEvict || (() => { }),
};
this.cache = new Map();
this._stats = {
hits: 0,
misses: 0,
evictions: 0,
size: 0,
maxSize: this.options.maxSize,
};
logger_1.logger.info('LRU cache initialized', {
maxSize: this.options.maxSize,
ttl: this.options.ttl,
});
}
get(key) {
const entry = this.cache.get(key);
if (!entry) {
this._stats.misses++;
logger_1.logger.debug('Cache miss', { key });
return undefined;
}
// Check if entry is expired
if (this.isExpired(entry)) {
this.delete(key);
this._stats.misses++;
logger_1.logger.debug('Cache entry expired', { key });
return undefined;
}
// Move to end (most recently used)
this.cache.delete(key);
entry.hits++;
this.cache.set(key, entry);
this._stats.hits++;
logger_1.logger.debug('Cache hit', { key, hits: entry.hits });
return entry.data;
}
set(key, value) {
// Delete existing entry if present
if (this.cache.has(key)) {
this.cache.delete(key);
}
else {
this._stats.size++;
}
// Check if we need to evict
if (this.cache.size >= this.options.maxSize) {
this.evictOldest();
}
const entry = {
data: value,
timestamp: Date.now(),
hits: 0,
};
this.cache.set(key, entry);
logger_1.logger.debug('Cache set', { key, size: this.cache.size });
}
has(key) {
const entry = this.cache.get(key);
if (!entry)
return false;
if (this.isExpired(entry)) {
this.delete(key);
return false;
}
return true;
}
delete(key) {
const existed = this.cache.delete(key);
if (existed) {
this._stats.size--;
logger_1.logger.debug('Cache entry deleted', { key });
}
return existed;
}
clear() {
const size = this.cache.size;
this.cache.clear();
this._stats.size = 0;
logger_1.logger.info('Cache cleared', { entriesCleared: size });
}
size() {
return this.cache.size;
}
stats() {
return { ...this._stats };
}
isExpired(entry) {
return Date.now() - entry.timestamp > this.options.ttl;
}
evictOldest() {
const firstKey = this.cache.keys().next().value;
if (firstKey !== undefined) {
const entry = this.cache.get(firstKey);
this.cache.delete(firstKey);
this._stats.evictions++;
this._stats.size--;
if (entry) {
this.options.onEvict(firstKey, entry);
}
logger_1.logger.debug('Cache entry evicted', { key: firstKey });
}
}
}
exports.LRUCache = LRUCache;
// Global cache instances
exports.lifelogCache = new LRUCache({
maxSize: parseInt(process.env.CACHE_MAX_SIZE || '100'),
ttl: parseInt(process.env.CACHE_TTL || String(5 * 60 * 1000)), // 5 minutes
});
exports.lifelogArrayCache = new LRUCache({
maxSize: parseInt(process.env.CACHE_MAX_SIZE || '100'),
ttl: parseInt(process.env.CACHE_TTL || String(5 * 60 * 1000)), // 5 minutes
});
exports.searchCache = new LRUCache({
maxSize: parseInt(process.env.SEARCH_CACHE_MAX_SIZE || '50'),
ttl: parseInt(process.env.SEARCH_CACHE_TTL || String(3 * 60 * 1000)), // 3 minutes
});
// Cache key builders
function buildLifelogCacheKey(id) {
return `lifelog:${id}`;
}
function buildDateCacheKey(date, options) {
const optStr = options ? JSON.stringify(options) : '';
return `date:${date}:${optStr}`;
}
function buildSearchCacheKey(searchTerm, options) {
const optStr = options ? JSON.stringify(options) : '';
return `search:${searchTerm}:${optStr}`;
}
function buildRecentCacheKey(options) {
const optStr = options ? JSON.stringify(options) : '';
return `recent:${optStr}`;
}
//# sourceMappingURL=cache.js.map