Skip to main content
Glama

Replicate MCP Server

by deepfates
cache.ts4.35 kB
/** * Cache service implementation with TTL and LRU strategy. */ import type { Collection, CollectionList } from "../models/collection.js"; import type { Model, ModelList } from "../models/model.js"; import type { Prediction } from "../models/prediction.js"; interface CacheEntry<T> { value: T; timestamp: number; lastAccessed: number; } export interface CacheStats { hits: number; misses: number; evictions: number; size: number; } export class Cache<T> { private cache: Map<string, CacheEntry<T>>; private maxSize: number; private ttl: number; private stats: CacheStats; constructor(maxSize = 1000, ttlSeconds = 300) { this.cache = new Map(); this.maxSize = maxSize; this.ttl = ttlSeconds * 1000; // Convert to milliseconds this.stats = { hits: 0, misses: 0, evictions: 0, size: 0, }; } /** * Set a value in the cache with TTL. */ set(key: string, value: T): void { // Evict oldest entries if cache is full if (this.cache.size >= this.maxSize) { this.evictOldest(); } this.cache.set(key, { value, timestamp: Date.now(), lastAccessed: Date.now(), }); this.stats.size = this.cache.size; } /** * Get a value from the cache, considering TTL. */ get(key: string): T | null { const entry = this.cache.get(key); if (!entry) { this.stats.misses++; return null; } // Check if entry has expired if (Date.now() - entry.timestamp > this.ttl) { this.cache.delete(key); this.stats.evictions++; this.stats.size = this.cache.size; this.stats.misses++; return null; } // Update last accessed time for LRU entry.lastAccessed = Date.now(); this.stats.hits++; return entry.value; } /** * Remove a specific key from the cache. */ delete(key: string): void { if (this.cache.delete(key)) { this.stats.evictions++; this.stats.size = this.cache.size; } } /** * Clear all entries from the cache. */ clear(): void { this.cache.clear(); this.stats.evictions += this.stats.size; this.stats.size = 0; } /** * Get cache statistics. */ getStats(): CacheStats { return { ...this.stats }; } /** * Warm up the cache with initial data. */ warmup(entries: [string, T][]): void { for (const [key, value] of entries) { this.set(key, value); } } /** * Remove expired entries from the cache. */ cleanup(): number { const now = Date.now(); let removed = 0; for (const [key, entry] of this.cache.entries()) { if (now - entry.timestamp > this.ttl) { this.cache.delete(key); removed++; } } this.stats.evictions += removed; this.stats.size = this.cache.size; return removed; } /** * Get all valid (non-expired) keys in the cache. */ keys(): string[] { const now = Date.now(); return Array.from(this.cache.entries()) .filter(([_, entry]) => now - entry.timestamp <= this.ttl) .map(([key]) => key); } /** * Check if a key exists and is not expired. */ has(key: string): boolean { const entry = this.cache.get(key); if (!entry) return false; const expired = Date.now() - entry.timestamp > this.ttl; if (expired) { this.cache.delete(key); this.stats.evictions++; this.stats.size = this.cache.size; return false; } return true; } private evictOldest(): void { let oldestKey: string | null = null; let oldestAccess = Number.POSITIVE_INFINITY; // Find the least recently used entry for (const [key, entry] of this.cache.entries()) { if (entry.lastAccessed < oldestAccess) { oldestAccess = entry.lastAccessed; oldestKey = key; } } // Remove the oldest entry if (oldestKey) { this.cache.delete(oldestKey); this.stats.evictions++; this.stats.size = this.cache.size; } } } // Create specialized cache instances for different types export const modelCache = new Cache<ModelList>(500, 3600); // 1 hour TTL for models export const predictionCache = new Cache<Prediction[]>(1000, 60); // 1 minute TTL for predictions export const collectionCache = new Cache<CollectionList>(100, 3600); // 1 hour TTL for collections

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/deepfates/mcp-replicate'

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