UNPKG

geoapify-mcp-server

Version:

Geoapify API MCP Server for location-based services - 一键部署的地理位置服务

146 lines (128 loc) 3.77 kB
const redis = require('redis'); const { logger } = require('./logger.js'); class CacheManager { constructor() { this.useRedis = process.env.REDIS_URL || process.env.REDIS_HOST; this.memoryCache = new Map(); this.maxMemoryCacheSize = 1000; if (this.useRedis) { this.initRedis(); } else { logger.info('Using in-memory cache (Redis not configured)'); } } async initRedis() { try { const redisConfig = process.env.REDIS_URL ? { url: process.env.REDIS_URL } : { host: process.env.REDIS_HOST || 'localhost', port: parseInt(process.env.REDIS_PORT) || 6379, password: process.env.REDIS_PASSWORD, db: parseInt(process.env.REDIS_DB) || 0 }; this.redisClient = redis.createClient(redisConfig); this.redisClient.on('error', (err) => { logger.error('Redis Client Error:', err); this.useRedis = false; }); this.redisClient.on('connect', () => { logger.info('Connected to Redis'); }); this.redisClient.on('disconnect', () => { logger.warn('Disconnected from Redis, falling back to memory cache'); this.useRedis = false; }); await this.redisClient.connect(); this.useRedis = true; } catch (error) { logger.error('Failed to connect to Redis:', error); this.useRedis = false; } } async get(key) { try { if (this.useRedis && this.redisClient?.isOpen) { const value = await this.redisClient.get(key); return value ? JSON.parse(value) : null; } else { // 内存缓存 const cached = this.memoryCache.get(key); if (cached && cached.expiry > Date.now()) { return cached.value; } else if (cached) { this.memoryCache.delete(key); } return null; } } catch (error) { logger.error('Cache get error:', error); return null; } } async set(key, value, ttlSeconds = 3600) { try { if (this.useRedis && this.redisClient?.isOpen) { await this.redisClient.setEx(key, ttlSeconds, JSON.stringify(value)); } else { // 内存缓存 if (this.memoryCache.size >= this.maxMemoryCacheSize) { // 删除最旧的条目 const firstKey = this.memoryCache.keys().next().value; this.memoryCache.delete(firstKey); } this.memoryCache.set(key, { value, expiry: Date.now() + (ttlSeconds * 1000) }); } } catch (error) { logger.error('Cache set error:', error); } } async delete(key) { try { if (this.useRedis && this.redisClient?.isOpen) { await this.redisClient.del(key); } else { this.memoryCache.delete(key); } } catch (error) { logger.error('Cache delete error:', error); } } async clear() { try { if (this.useRedis && this.redisClient?.isOpen) { await this.redisClient.flushDb(); } else { this.memoryCache.clear(); } } catch (error) { logger.error('Cache clear error:', error); } } async disconnect() { if (this.redisClient?.isOpen) { await this.redisClient.disconnect(); } } // 清理过期的内存缓存 cleanupMemoryCache() { if (!this.useRedis) { const now = Date.now(); for (const [key, cached] of this.memoryCache.entries()) { if (cached.expiry <= now) { this.memoryCache.delete(key); } } } } } // 定期清理内存缓存 setInterval(() => { if (global.cacheManager) { global.cacheManager.cleanupMemoryCache(); } }, 60000); // 每分钟清理一次 module.exports = { CacheManager };