Skip to main content
Glama
ttl-cache.tsβ€’2.99 kB
/** * Simple TTL (Time-To-Live) Cache Implementation * * Provides automatic expiration of cached entries after a specified duration. * Used for workspace-level caching of attribute metadata to reduce API calls * while preventing stale data issues. */ export interface TTLCacheEntry<T> { value: T; expiresAt: number; } export class TTLCache<K, V> { private cache: Map<K, TTLCacheEntry<V>>; private readonly ttlMs: number; private cleanupInterval?: NodeJS.Timeout; /** * Creates a new TTL cache * * @param ttlMs - Time-to-live in milliseconds (default: 15 minutes) * @param cleanupIntervalMs - How often to check for expired entries (default: 5 minutes) */ constructor( ttlMs: number = 15 * 60 * 1000, cleanupIntervalMs: number = 5 * 60 * 1000 ) { this.cache = new Map(); this.ttlMs = ttlMs; // Start periodic cleanup this.cleanupInterval = setInterval(() => { this.cleanup(); }, cleanupIntervalMs); // Ensure cleanup interval doesn't keep process alive if (this.cleanupInterval.unref) { this.cleanupInterval.unref(); } } /** * Gets a value from the cache * * @param key - The cache key * @returns The cached value, or undefined if not found or expired */ get(key: K): V | undefined { const entry = this.cache.get(key); if (!entry) { return undefined; } // Check if expired if (Date.now() > entry.expiresAt) { this.cache.delete(key); return undefined; } return entry.value; } /** * Sets a value in the cache with TTL * * @param key - The cache key * @param value - The value to cache */ set(key: K, value: V): void { this.cache.set(key, { value, expiresAt: Date.now() + this.ttlMs, }); } /** * Checks if a key exists and is not expired * * @param key - The cache key * @returns True if the key exists and is not expired */ has(key: K): boolean { return this.get(key) !== undefined; } /** * Removes a specific key from the cache * * @param key - The cache key to remove */ delete(key: K): boolean { return this.cache.delete(key); } /** * Clears all entries from the cache */ clear(): void { this.cache.clear(); } /** * Returns the number of entries in the cache (including expired ones) */ get size(): number { return this.cache.size; } /** * Removes expired entries from the cache * Called automatically by cleanup interval */ private cleanup(): void { const now = Date.now(); for (const [key, entry] of this.cache.entries()) { if (now > entry.expiresAt) { this.cache.delete(key); } } } /** * Stops the cleanup interval * Should be called when the cache is no longer needed */ destroy(): void { if (this.cleanupInterval) { clearInterval(this.cleanupInterval); this.cleanupInterval = undefined; } this.clear(); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kesslerio/attio-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server