Files
michaelschiemer/src/Framework/Database/Cache/CacheAdapterStrategy.php
Michael Schiemer 55a330b223 Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug
- Add DISCOVERY_SHOW_PROGRESS=true
- Temporary changes for debugging InitializerProcessor fixes on production
2025-08-11 20:13:26 +02:00

218 lines
5.8 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Framework\Database\Cache;
use App\Framework\Cache\Cache;
final class CacheAdapterStrategy implements CacheStrategy
{
private array $stats;
public function __construct(
private readonly Cache $cache,
private readonly string $keyPrefix = 'db_query:'
) {
$this->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}*");
}
}