geoapify-mcp-server
Version:
Geoapify API MCP Server for location-based services - 一键部署的地理位置服务
146 lines (128 loc) • 3.77 kB
JavaScript
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 };