stats = [ 'hits' => 0, 'misses' => 0, 'sets' => 0, 'deletes' => 0, 'invalidations' => 0, ]; } public function set(QueryCacheKey $key, array $value, int $ttlSeconds): bool { $fullKey = $this->keyPrefix . $key->toString(); try { $success = $this->cache->set($fullKey, $value, $ttlSeconds); if ($success) { $this->stats['sets']++; } return $success; } catch (\Throwable) { return false; } } public function get(QueryCacheKey $key): ?array { $fullKey = $this->keyPrefix . $key->toString(); try { $value = $this->cache->get($fullKey); if ($value === null) { $this->stats['misses']++; return null; } $this->stats['hits']++; return $value->value; } catch (\Throwable) { $this->stats['misses']++; return null; } } public function has(QueryCacheKey $key): bool { $fullKey = $this->keyPrefix . $key->toString(); try { return $this->cache->has($fullKey); } catch (\Throwable) { return false; } } public function delete(QueryCacheKey $key): bool { $fullKey = $this->keyPrefix . $key->toString(); try { $success = $this->cache->forget($fullKey); if ($success) { $this->stats['deletes']++; } return $success; } catch (\Throwable) { return false; } } public function invalidatePattern(string $pattern): int { // Fallback für Cache-Implementierungen ohne Pattern-Support if (! method_exists($this->cache, 'deleteByPattern')) { // Für einfache Caches: kompletter Clear bei Pattern-Invalidierung $this->clear(); return 1; // Unbekannte Anzahl, also 1 als Indikator } try { $searchPattern = $this->keyPrefix . '*' . $pattern . '*'; $deleted = $this->cache->deleteByPattern($searchPattern); $this->stats['invalidations'] += $deleted; return $deleted; } catch (\Throwable) { return 0; } } public function clear(): void { try { // Wenn Cache Tagged-Cache unterstützt, nutze Tags if (method_exists($this->cache, 'deleteByTag')) { $deleted = $this->cache->deleteByTag('database_query'); $this->stats['invalidations'] += $deleted; return; } // Wenn Pattern-Deletion unterstützt wird if (method_exists($this->cache, 'deleteByPattern')) { $deleted = $this->cache->deleteByPattern($this->keyPrefix . '*'); $this->stats['invalidations'] += $deleted; return; } // Fallback: Ganzer Cache wird geleert (nicht ideal) if (method_exists($this->cache, 'clear')) { $this->cache->clear(); $this->stats['invalidations']++; } } catch (\Throwable) { // Ignoriere Fehler bei Cache-Clear } } public function getStats(): array { $baseStats = $this->stats; // Erweitere um Framework-Cache-spezifische Stats falls verfügbar if (method_exists($this->cache, 'getStats')) { try { $cacheStats = $this->cache->getStats(); $baseStats = array_merge($baseStats, [ 'cache_stats' => $cacheStats, 'cache_type' => get_class($this->cache), ]); } catch (\Throwable) { // Ignoriere Fehler bei Stats-Abruf } } // Hit Ratio berechnen $baseStats['hit_ratio'] = $this->calculateHitRatio(); return $baseStats; } private function calculateHitRatio(): float { $total = $this->stats['hits'] + $this->stats['misses']; return $total > 0 ? ($this->stats['hits'] / $total) : 0.0; } /** * Factory-Methode für TaggedCache wenn verfügbar */ public static function withTags(Cache $cache, array $tags = ['database_query'], string $keyPrefix = 'db_query:'): self { // Wenn TaggedCache verfügbar ist, nutze es if (method_exists($cache, 'tags')) { $taggedCache = $cache->tags($tags); return new self($taggedCache, $keyPrefix); } return new self($cache, $keyPrefix); } /** * Hilfsmethode für Cache-Tagging */ private function setWithTags(string $key, array $value, int $ttl, array $tags = []): bool { if (method_exists($this->cache, 'setWithTags')) { return $this->cache->setWithTags($key, $value, $ttl, array_merge(['database_query'], $tags)); } return $this->cache->set($key, $value, $ttl); } /** * Invalidierung basierend auf Tabellen-Tags */ public function invalidateByTable(string $tableName): int { if (method_exists($this->cache, 'deleteByTag')) { try { return $this->cache->deleteByTag("table:{$tableName}"); } catch (\Throwable) { // Fallback zu Pattern-basierter Invalidierung } } // Fallback: Pattern-basierte Invalidierung return $this->invalidatePattern("*{$tableName}*"); } }