Skip to main content
Glama
tree-cache.js3.67 kB
// src/core/tree-cache.js const fs = require('fs').promises; const crypto = require('crypto'); /** * 文件树缓存管理器 - 缓存目录结构以减少文件系统操作 */ class TreeCache { /** * @param {object} options 缓存选项 * @param {number} options.maxEntries 最大缓存条目数 * @param {number} options.ttl 缓存生存时间(ms) */ constructor(options = {}) { this.maxEntries = options.maxEntries || 50; this.ttl = options.ttl || 60 * 1000; // 默认1分钟 this.cache = new Map(); this.stats = { hits: 0, misses: 0, evictions: 0 }; } /** * 生成缓存键 * @param {string} dirPath 目录路径 * @param {object} options 过滤选项 * @returns {string} 缓存键 */ generateKey(dirPath, options) { // 将目录路径和选项组合成缓存键 const optionsStr = JSON.stringify(options || {}); return crypto.createHash('md5').update(`${dirPath}:${optionsStr}`).digest('hex'); } /** * 获取缓存的文件树 * @param {string} dirPath 目录路径 * @param {object} options 过滤选项 * @returns {Array|null} 缓存的文件树或null */ get(dirPath, options) { const key = this.generateKey(dirPath, options); if (this.cache.has(key)) { const entry = this.cache.get(key); // 检查缓存是否过期 if (Date.now() - entry.timestamp < this.ttl) { // 检查目录是否被修改 try { const stats = fs.statSync(dirPath); if (stats.mtimeMs <= entry.mtime) { this.stats.hits++; return entry.data; } } catch (error) { // 如果无法获取目录状态,使用缓存内容 this.stats.hits++; return entry.data; } } // 缓存过期,删除 this.cache.delete(key); this.stats.evictions++; } this.stats.misses++; return null; } /** * 设置缓存 * @param {string} dirPath 目录路径 * @param {object} options 过滤选项 * @param {Array} data 文件树数据 */ set(dirPath, options, data) { const key = this.generateKey(dirPath, options); // 如果缓存已满,删除最旧的项 if (this.cache.size >= this.maxEntries) { const oldestKey = this.cache.keys().next().value; this.cache.delete(oldestKey); this.stats.evictions++; } // 获取目录的修改时间 let mtime = Date.now(); try { const stats = fs.statSync(dirPath); mtime = stats.mtimeMs; } catch (error) { // 忽略错误,使用当前时间 } this.cache.set(key, { data, timestamp: Date.now(), mtime }); } /** * 清除缓存 * @param {string} [dirPath] 特定目录路径,不提供则清除所有缓存 * @param {object} [options] 过滤选项,不提供则清除指定目录的所有缓存 */ invalidate(dirPath, options) { if (dirPath && options) { const key = this.generateKey(dirPath, options); this.cache.delete(key); } else if (dirPath) { // 清除指定目录的所有缓存 for (const [key, entry] of this.cache.entries()) { if (key.startsWith(dirPath)) { this.cache.delete(key); } } } else { // 清除所有缓存 this.cache.clear(); } } /** * 获取缓存统计信息 * @returns {object} 统计信息 */ getStats() { return { ...this.stats, size: this.cache.size, hitRate: this.stats.hits / (this.stats.hits + this.stats.misses) || 0 }; } } module.exports = TreeCache;

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/yy1588133/code-merge-mcp'

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