UNPKG

@siva-sub/mcp-public-transport

Version:

A Model Context Protocol server for Singapore transport data with real-time information and routing

71 lines (70 loc) 1.99 kB
import NodeCache from 'node-cache'; import { logger } from '../utils/logger.js'; export class CacheService { cache; hitCount = 0; missCount = 0; constructor(defaultTtl = 300) { this.cache = new NodeCache({ stdTTL: defaultTtl, checkperiod: 60, useClones: false, deleteOnExpire: true, }); this.cache.on('expired', (key) => { logger.debug(`Cache key expired: ${key}`); }); this.cache.on('del', (key) => { logger.debug(`Cache key deleted: ${key}`); }); } async getOrSet(key, fetchFn, ttl) { const cached = this.cache.get(key); if (cached !== undefined) { this.hitCount++; logger.debug(`Cache hit: ${key}`); return cached; } this.missCount++; logger.debug(`Cache miss: ${key}`); try { const data = await fetchFn(); this.cache.set(key, data, ttl || 300); logger.debug(`Cache set: ${key} (TTL: ${ttl || 'default'})`); return data; } catch (error) { logger.error(`Failed to fetch data for cache key: ${key}`, error); throw error; } } get(key) { const value = this.cache.get(key); if (value !== undefined) { this.hitCount++; } else { this.missCount++; } return value; } set(key, value, ttl) { return this.cache.set(key, value, ttl || 300); } del(key) { return this.cache.del(key); } flush() { this.cache.flushAll(); logger.info('Cache flushed'); } getStats() { const cacheStats = this.cache.getStats(); return { ...cacheStats, hitRate: this.hitCount / (this.hitCount + this.missCount) || 0, hitCount: this.hitCount, missCount: this.missCount, }; } }