Skip to main content
Glama
cache.ts3.43 kB
/** * 任务缓存模块 * 缓存相似任务的结果,减少 API 调用 */ import { createHash } from 'node:crypto'; /** * 缓存条目 */ interface CacheEntry { /** 任务描述 */ task: string; /** 执行结果 */ result: string; /** 创建时间 */ createdAt: number; /** 命中次数 */ hits: number; } /** * 缓存配置 */ export interface CacheConfig { /** 最大缓存条目数 */ maxSize?: number; /** 缓存过期时间(毫秒) */ ttl?: number; /** 是否启用 */ enabled?: boolean; } /** * 任务缓存管理器 */ export class TaskCache { private cache: Map<string, CacheEntry> = new Map(); private readonly maxSize: number; private readonly ttl: number; private readonly enabled: boolean; constructor(config: CacheConfig = {}) { this.maxSize = config.maxSize ?? 100; this.ttl = config.ttl ?? 30 * 60 * 1000; // 默认 30 分钟 this.enabled = config.enabled ?? true; } /** * 生成任务的哈希键 */ private generateKey(task: string, context?: string): string { const normalized = this.normalizeTask(task, context); return createHash('md5').update(normalized).digest('hex'); } /** * 标准化任务描述 * 移除多余空格、统一大小写等 */ private normalizeTask(task: string, context?: string): string { const normalizedTask = task .toLowerCase() .trim() .replace(/\s+/g, ' '); const normalizedContext = context ? context.toLowerCase().trim().replace(/\s+/g, ' ') : ''; return `${normalizedTask}|${normalizedContext}`; } /** * 获取缓存结果 */ get(task: string, context?: string): string | null { if (!this.enabled) return null; const key = this.generateKey(task, context); const entry = this.cache.get(key); if (!entry) return null; // 检查是否过期 if (Date.now() - entry.createdAt > this.ttl) { this.cache.delete(key); return null; } // 更新命中次数 entry.hits++; return entry.result; } /** * 设置缓存 */ set(task: string, result: string, context?: string): void { if (!this.enabled) return; // 检查缓存大小 if (this.cache.size >= this.maxSize) { this.evict(); } const key = this.generateKey(task, context); this.cache.set(key, { task, result, createdAt: Date.now(), hits: 0, }); } /** * 清理过期和最少使用的缓存 */ private evict(): void { const now = Date.now(); // 先删除过期的 for (const [key, entry] of this.cache) { if (now - entry.createdAt > this.ttl) { this.cache.delete(key); } } // 如果还是超过限制,删除命中次数最少的 if (this.cache.size >= this.maxSize) { const entries = Array.from(this.cache.entries()) .sort((a, b) => a[1].hits - b[1].hits); const deleteCount = Math.ceil(this.maxSize * 0.2); // 删除 20% for (let i = 0; i < deleteCount && i < entries.length; i++) { this.cache.delete(entries[i][0]); } } } /** * 清空缓存 */ clear(): void { this.cache.clear(); } /** * 获取缓存统计 */ getStats(): { size: number; maxSize: number; enabled: boolean } { return { size: this.cache.size, maxSize: this.maxSize, enabled: this.enabled, }; } }

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/7836246/claude-team-mcp'

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