UNPKG

codecrucible-synth

Version:

Production-Ready AI Development Platform with Multi-Voice Synthesis, Smithery MCP Integration, Enterprise Security, and Zero-Timeout Reliability

244 lines 8.49 kB
/** * CacheCoordinator - Extracted from UnifiedModelClient * Centralizes all caching logic following Living Spiral methodology * * Council Perspectives Applied: * - Performance Engineer: Intelligent TTL and hit rate optimization * - Maintainer: Clean abstraction for cache operations * - Security Guardian: Safe key generation and data validation * - Explorer: Extensible cache strategies and storage backends * - Architect: Clear separation between caching logic and client operations */ import { unifiedCache } from '../cache/unified-cache-system.js'; import { logger } from '../logger.js'; /** * CacheCoordinator Implementation * Centralizes all caching operations with intelligent strategies */ export class CacheCoordinator { cache = unifiedCache; CACHE_TTL = 300000; // 5 minutes MAX_CACHE_SIZE = 500; HEALTH_CACHE_TTL = 30000; // 30 seconds // Cache statistics tracking cacheStats = { hits: 0, misses: 0, sets: 0, hitRate: '0%', totalRequests: 0, }; // Health check caching healthCheckCache = new Map(); constructor() { this.updateCacheStats(); } /** * Enhanced cache getter with hit tracking */ async get(key) { const cached = await this.cache.get(key); if (cached?.hit) { this.cacheStats.hits++; // Update hit count for intelligence if (cached.metadata?.cachedAt) { const age = Math.round((Date.now() - cached.metadata.cachedAt) / 1000); console.log(`🧠 Cache hit! (source: ${cached.source}, age: ${age}s, similarity: ${cached.similarity || 'exact'})`); } this.updateCacheStats(); return cached.value; } else { this.cacheStats.misses++; console.log('🧠 Cache miss'); this.updateCacheStats(); return null; } } /** * Enhanced cache setter with intelligent TTL and monitoring */ set(key, value, options) { try { const ttl = options?.ttl || this.getIntelligentTTL(); // Store with metadata in unified cache system this.cache.set(key, value, { ttl: ttl, metadata: options?.metadata || { cachedAt: Date.now(), requestType: 'general', hitCount: 0, }, }); this.cacheStats.sets++; console.log(`🧠 Response cached with intelligent TTL: ${Math.round(ttl / 1000)}s`); } catch (error) { // Fallback to basic caching this.cache.set(key, value, { ttl: options?.ttl || this.CACHE_TTL }); this.cacheStats.sets++; logger.warn('Fallback to basic caching due to error:', error); } this.updateCacheStats(); } /** * Generate intelligent cache key based on request content and context */ generateIntelligentCacheKey(request, context) { // Create content fingerprint for cache key const contextFingerprint = context ? JSON.stringify({ files: Array.isArray(context.files) ? context.files.map((f) => f.path) : [], projectType: context.projectType || 'unknown', timestamp: Math.floor(Date.now() / 300000), // 5-minute time buckets }) : ''; const requestFingerprint = JSON.stringify({ prompt: this.normalizePromptForCaching(request.prompt || ''), model: request.model || 'default', temperature: request.temperature || 0.7, maxTokens: request.maxTokens || 4000, }); // Create base64 hash for efficient storage const combinedContent = requestFingerprint + contextFingerprint; const cacheKey = Buffer.from(combinedContent).toString('base64').slice(0, 32); console.log(`🧠 Cache key generated: ${cacheKey.slice(0, 16)}... (prompt: ${(request.prompt || '').slice(0, 50)}...)`); return cacheKey; } /** * Normalize prompt for consistent caching */ normalizePromptForCaching(prompt) { return prompt .trim() .toLowerCase() .replace(/\s+/g, ' ') // Normalize whitespace .replace(/[^\w\s]/g, '') // Remove special characters .slice(0, 500); // Limit length for cache key efficiency } /** * Determine intelligent TTL based on request characteristics */ getIntelligentTTL(request) { if (!request) return this.CACHE_TTL; const prompt = request.prompt || ''; const promptLength = prompt.length; // Longer, more complex prompts get longer cache time if (promptLength > 1000) return 1800000; // 30 minutes if (promptLength > 500) return 900000; // 15 minutes if (promptLength > 200) return 600000; // 10 minutes // Code-related requests get longer cache time if (/code|function|class|implement|debug/.test(prompt.toLowerCase())) { return 900000; // 15 minutes } // Real-time or time-sensitive requests get shorter cache time if (/now|current|today|latest|realtime|live/.test(prompt.toLowerCase())) { return 60000; // 1 minute } return this.CACHE_TTL; // Default 5 minutes } /** * Check if request should be cached */ shouldUseIntelligentCache(request) { const prompt = request.prompt || ''; // Don't cache very short prompts or streaming requests if (prompt.length < 20 || request.stream) { return false; } // Don't cache real-time or time-sensitive requests if (/now|current|today|latest|realtime|live/.test(prompt.toLowerCase())) { return false; } return true; } /** * Classify request type for intelligent caching */ classifyRequestType(request) { if (!request?.prompt) return 'unknown'; const prompt = request.prompt.toLowerCase(); if (/code|function|class|implement|debug|fix|refactor/.test(prompt)) { return 'code_generation'; } if (/explain|describe|what|how|why/.test(prompt)) { return 'explanation'; } if (/analyze|review|assess|evaluate/.test(prompt)) { return 'analysis'; } if (/create|generate|write|build|make/.test(prompt)) { return 'creation'; } return 'general'; } /** * Update cache statistics with hit rate calculation */ updateCacheStats() { this.cacheStats.totalRequests = this.cacheStats.hits + this.cacheStats.misses; this.cacheStats.hitRate = this.cacheStats.totalRequests > 0 ? ((this.cacheStats.hits / this.cacheStats.totalRequests) * 100).toFixed(1) + '%' : '0%'; } /** * Get basic cache statistics */ getCacheStats() { return this.cache.getStats(); } /** * Get intelligent cache statistics with hit rates and persistence info */ getIntelligentCacheStats() { const enhancedStats = this.cache.getStats(); return { basic: enhancedStats, intelligence: { ...this.cacheStats, }, }; } /** * Health check cache management */ getHealthCheckCache() { return this.healthCheckCache; } setHealthCheck(key, healthy) { this.healthCheckCache.set(key, { healthy, timestamp: Date.now() }); } isHealthCheckCached(key, ttl = this.HEALTH_CACHE_TTL) { const cached = this.healthCheckCache.get(key); return cached ? Date.now() - cached.timestamp < ttl : false; } /** * Clear all caches */ clear() { this.cache.clear(); this.healthCheckCache.clear(); this.cacheStats = { hits: 0, misses: 0, sets: 0, hitRate: '0%', totalRequests: 0, }; } /** * Destroy cache coordinator and persist data */ destroy() { console.log('🗃️ Saving cache before shutdown...'); this.cache.destroy(); this.healthCheckCache.clear(); } } //# sourceMappingURL=cache-coordinator.js.map