Skip to main content
Glama
cacheManager.ts•9.72 kB
/** * Cache manager for the Code-Map Generator tool. * This file contains functions for managing multiple cache instances. */ import path from 'path'; import logger from '../../../logger.js'; import { FileCache } from './fileCache.js'; import { TieredCache, TieredCacheOptions } from './tieredCache.js'; import { CacheOptions, CacheStats } from './types.js'; import { CodeMapGeneratorConfig } from '../types.js'; import { getCacheDirectory } from '../directoryUtils.js'; // Interface for cache instances with common methods interface CacheInstance { clear(): Promise<void>; prune(): Promise<number>; getStats(): CacheStats | Promise<CacheStats>; close(): void; } // Map of cache instances by name const cacheInstances = new Map<string, CacheInstance>(); /** * Creates a cache manager instance. * @param config The Code-Map Generator configuration * @returns An object with methods for managing caches */ export function createCacheManager(config: CodeMapGeneratorConfig) { const cacheDir = getCacheDirectory(config); /** * Gets or creates a file cache instance. * @param name The name of the cache * @param options Additional cache options * @returns A promise that resolves to the cache instance */ async function getFileCache<T>(name: string, options?: Partial<CacheOptions>): Promise<FileCache<T>> { // Check if the cache is already created if (cacheInstances.has(name)) { const cache = cacheInstances.get(name); if (cache instanceof FileCache) { return cache as FileCache<T>; } else { throw new Error(`Cache ${name} exists but is not a FileCache`); } } // Create a new cache instance const cacheOptions: CacheOptions = { name, cacheDir: path.join(cacheDir, name), maxEntries: options?.maxEntries || config.cache?.maxEntries, maxAge: options?.maxAge || config.cache?.maxAge, validateOnGet: options?.validateOnGet, pruneOnStartup: options?.pruneOnStartup, pruneInterval: options?.pruneInterval, serialize: options?.serialize, deserialize: options?.deserialize, }; const cache = new FileCache<T>(cacheOptions); await cache.init(); // Store the cache instance (cast to CacheInstance interface) cacheInstances.set(name, cache as CacheInstance); logger.debug(`Created file cache instance: ${name}`); return cache; } /** * Gets or creates a tiered cache instance. * @param name The name of the cache * @param options Additional cache options * @returns A promise that resolves to the cache instance */ async function getTieredCache<T>(name: string, options?: Partial<TieredCacheOptions>): Promise<TieredCache<T>> { // Check if the cache is already created if (cacheInstances.has(name)) { const cache = cacheInstances.get(name); if (cache instanceof TieredCache) { return cache as TieredCache<T>; } else { throw new Error(`Cache ${name} exists but is not a TieredCache`); } } // Create a new cache instance const cacheOptions: TieredCacheOptions = { name, cacheDir: path.join(cacheDir, name), maxEntries: options?.maxEntries || config.cache?.maxEntries, maxAge: options?.maxAge || config.cache?.maxAge, validateOnGet: options?.validateOnGet, pruneOnStartup: options?.pruneOnStartup, pruneInterval: options?.pruneInterval, serialize: options?.serialize, deserialize: options?.deserialize, useMemoryCache: options?.useMemoryCache ?? config.cache?.useMemoryCache ?? true, memoryMaxEntries: options?.memoryMaxEntries, memoryMaxAge: options?.memoryMaxAge, memoryThreshold: options?.memoryThreshold, memorySizeCalculator: options?.memorySizeCalculator }; const cache = new TieredCache<T>(cacheOptions); await cache.init(); // Store the cache instance (cast to CacheInstance interface) cacheInstances.set(name, cache as CacheInstance); logger.debug(`Created tiered cache instance: ${name}`); return cache; } /** * Gets or creates a cache instance. * For backward compatibility, defaults to FileCache. * @param name The name of the cache * @param options Additional cache options * @returns A promise that resolves to the cache instance */ async function getCache<T>(name: string, options?: Partial<CacheOptions>): Promise<FileCache<T>> { return getFileCache<T>(name, options); } /** * Clears a specific cache. * @param name The name of the cache * @returns A promise that resolves when the cache is cleared */ async function clearCache(name: string): Promise<void> { const cache = cacheInstances.get(name); if (cache) { await cache.clear(); logger.debug(`Cleared cache: ${name}`); } } /** * Clears all cache instances. * @returns A promise that resolves when all caches are cleared */ async function clearAllCaches(): Promise<void> { const clearPromises = Array.from(cacheInstances.entries()).map(async ([name, cache]) => { await cache.clear(); logger.debug(`Cleared cache: ${name}`); }); await Promise.all(clearPromises); logger.info(`Cleared all caches (${cacheInstances.size} instances)`); } /** * Prunes a specific cache. * @param name The name of the cache * @returns A promise that resolves to the number of entries pruned */ async function pruneCache(name: string): Promise<number> { const cache = cacheInstances.get(name); if (cache) { const prunedCount = await cache.prune(); logger.debug(`Pruned ${prunedCount} entries from cache: ${name}`); return prunedCount; } return 0; } /** * Prunes all cache instances. * @returns A promise that resolves to the total number of entries pruned */ async function pruneAllCaches(): Promise<number> { let totalPruned = 0; const prunePromises = Array.from(cacheInstances.entries()).map(async ([name, cache]) => { const prunedCount = await cache.prune(); logger.debug(`Pruned ${prunedCount} entries from cache: ${name}`); return prunedCount; }); const results = await Promise.all(prunePromises); totalPruned = results.reduce((total: number, count: number) => total + count, 0); logger.info(`Pruned ${totalPruned} entries from all caches (${cacheInstances.size} instances)`); return totalPruned; } /** * Gets statistics about a specific cache. * @param name The name of the cache * @returns The cache statistics, or undefined if the cache doesn't exist */ async function getCacheStats(name: string): Promise<CacheStats | undefined> { const cache = cacheInstances.get(name); if (cache) { const stats = cache.getStats(); return stats instanceof Promise ? await stats : stats; } return undefined; } /** * Gets statistics about all cache instances. * @returns An object mapping cache names to their statistics */ async function getAllCacheStats(): Promise<Record<string, CacheStats>> { const stats: Record<string, CacheStats> = {}; for (const [name, cache] of cacheInstances.entries()) { const cacheStats = cache.getStats(); stats[name] = cacheStats instanceof Promise ? await cacheStats : cacheStats; } return stats; } /** * Closes all cache instances. */ function closeAllCaches(): void { for (const [name, cache] of cacheInstances.entries()) { cache.close(); logger.debug(`Closed cache: ${name}`); } cacheInstances.clear(); logger.info('Closed all cache instances'); } return { getCache, getFileCache, getTieredCache, clearCache, clearAllCaches, pruneCache, pruneAllCaches, getCacheStats, getAllCacheStats, closeAllCaches, }; } /** * Clears all cache instances. * @returns A promise that resolves when all caches are cleared */ export async function clearAllCaches(): Promise<void> { const clearPromises = Array.from(cacheInstances.entries()).map(async ([name, cache]) => { await cache.clear(); logger.debug(`Cleared cache: ${name}`); }); await Promise.all(clearPromises); logger.info(`Cleared all caches (${cacheInstances.size} instances)`); } /** * Prunes all cache instances. * @returns A promise that resolves to the total number of entries pruned */ export async function pruneAllCaches(): Promise<number> { let totalPruned = 0; const prunePromises = Array.from(cacheInstances.entries()).map(async ([name, cache]) => { const prunedCount = await cache.prune(); logger.debug(`Pruned ${prunedCount} entries from cache: ${name}`); return prunedCount; }); const results = await Promise.all(prunePromises); totalPruned = results.reduce((total: number, count: number) => total + count, 0); logger.info(`Pruned ${totalPruned} entries from all caches (${cacheInstances.size} instances)`); return totalPruned; } /** * Gets statistics about all cache instances. * @returns An object mapping cache names to their statistics */ export async function getCacheStats(): Promise<Record<string, CacheStats>> { const stats: Record<string, CacheStats> = {}; for (const [name, cache] of cacheInstances.entries()) { const cacheStats = cache.getStats(); stats[name] = cacheStats instanceof Promise ? await cacheStats : cacheStats; } return stats; } /** * Closes all cache instances. */ export function closeAllCaches(): void { for (const [name, cache] of cacheInstances.entries()) { cache.close(); logger.debug(`Closed cache: ${name}`); } cacheInstances.clear(); logger.info('Closed all cache instances'); }

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/freshtechbro/vibe-coder-mcp'

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