Task 28 — Кэширование
Phase: 2
Status: done
Owner: —
Slug: caching
Goal
Deterministic tool results, embeddings, routing decisions и provider-supported prompt prefixes кэшируются с scope, TTL, invalidation и sensitivity-правилами.
Acceptance criteria
Cache/CacheConfig.cs—CacheConfigс настройками TTL, scope, sensitivity per cache classCache/ICacheService.cs—ICacheServiceinterface сGetOrSetAsync<T>,Invalidate,InvalidatePatternCache/CacheService.cs— in-memory реализация с sliding expiration, background cleanupCache/CacheClass.cs— enum:Embedding,RoutingDecision,LlmPromptPrefix,DeterministicToolResultCache/SensitivityLevel.cs— enum:Public,Internal,Sensitive,Restricted- Wiring:
EmbeddingScorerиспользуетICacheServiceвместо inlineDictionary<string, float[]> - Wiring:
DeterministicRouterполучает routing decision cache (sliding TTL, key = hash of input) - Wiring:
ILLMClientFactoryкэширует prompt prefixes per provider CacheConfigдобавлена вAppConfig- DI registration в
Program.cs(CLI + WebAPI) CacheController—GET /api/cache/stats,POST /api/cache/invalidateCacheServiceTests— TTL expiry, sensitivity rules, invalidationdotnet buildпроходитdotnet testпроходит (pre-existing failures unchanged)
Scope / Likely files
src/agent/Cache/
Dependencies
- блокирует / опирается на: task_022 — semantic-routing
Risks / Rollback
Stale cache для sensitive данных; per-data-class TTL.
Implementation notes
2026-08-12
Реализовано:
CacheConfig— per-class TTL (Embedding: 1h, RoutingDecision: 30s, LlmCapability: 24h, LlmPromptPrefix: 24h, DeterministicToolResult: 5min), sensitivity levels, sliding expiration, max entries, cleanup intervalICacheService—GetOrSetAsync<T>(async factory),Invalidate,InvalidateClass,InvalidatePattern,InvalidateAll,GetStats;where T : class?constraintCacheService— in-memoryConcurrentDictionary-based implementation with background timer cleanup, per-class hit/miss/eviction stats, capacity eviction (oldest by expiry)NullCacheService— no-op implementation for backward compatibility (tests, disabled cache)EmbeddingScorer— replaced inline_embeddingCachedict withICacheService(task_028 wiring); usesGetOrSetAsyncfor skill embeddings withCacheClass.EmbeddingDeterministicRouter— addedICacheService?parameter; routing decisions cached with 30s TTL viaCacheClass.RoutingDecision; key = SHA256(input)[:16]ProviderCapabilityDetector— addedICacheService?parameter; results cached viaCacheClass.LlmCapabilitywith 24h TTLLlmClientFactory— addedICacheService?parameter; clients cached viaCacheClass.LlmPromptPrefix(provider name as key)AppConfig— addedpublic CacheConfig Cache { get; set; } = new()- DI registration —
ICacheService, CacheServiceregistered as singleton in both CLI and WebAPI Program.cs; all affected services (EmbeddingScorer, DeterministicRouter, ProviderCapabilityDetector, LlmClientFactory) receiveICacheServicevia constructor CacheController—GET /api/cache/stats(hit/miss/entries/evicted per class + hit rate),POST /api/cache/invalidate(by class/key/pattern)CacheServiceTests— 14 tests: miss, hit, separate classes, null factory, invalidation, pattern invalidation, class invalidation, all invalidation, disabled cache, stats tracking, capacity eviction, null not cached, sliding expiration
Links
- Backlog: ../backlog.md
- Roadmap (EN): ../../ROADMAP-EN.md
- Roadmap (RU): ../../ROADMAP-RU.md