chore: complete update

This commit is contained in:
2025-07-17 16:24:20 +02:00
parent 899227b0a4
commit 64a7051137
1300 changed files with 85570 additions and 2756 deletions

View File

@@ -0,0 +1,124 @@
<?php
namespace App\Framework\Cache;
final readonly class MultiLevelCache implements Cache
{
private const int MAX_FAST_CACHE_SIZE = 1024; //1KB
private const int FAST_CACHE_TTL = 300;
public function __construct(
private Cache $fastCache, // z.B. ArrayCache
private Cache $slowCache // z.B. RedisCache, FileCache
) {}
public function get(string $key): CacheItem
{
$item = $this->fastCache->get($key);
if ($item->isHit) {
return $item;
}
// Fallback auf "langsame" Ebene
$item = $this->slowCache->get($key);
if ($item->isHit) {
// In schnellen Cache zurücklegen (optional mit TTL aus Slow-Item)
if($this->shouldCacheInFast($item->value)) {
$this->fastCache->set($key, $item->value, self::FAST_CACHE_TTL);
}
}
return $item;
}
public function set(string $key, mixed $value, ?int $ttl = null): bool
{
$slowSuccess = $this->slowCache->set($key, $value, $ttl);
$fastSuccess = true;
if($this->shouldCacheInFast($value)) {
$fastTtl = min($ttl ?? self::FAST_CACHE_TTL, self::FAST_CACHE_TTL);
$fastSuccess = $this->fastCache->set($key, $value, $fastTtl);
}
return $slowSuccess && $fastSuccess;
}
public function forget(string $key): bool
{
$s1 = $this->fastCache->forget($key);
$s2 = $this->slowCache->forget($key);
return $s1 && $s2;
}
public function clear(): bool
{
$s1 = $this->fastCache->clear();
$s2 = $this->slowCache->clear();
return $s1 && $s2;
}
/*
* - **has**: Versucht zuerst den schnelleren Layer. Im Falle eines Hits im "slowCache" wird der Wert aufgewärmt/gecached, damit zukünftige Zugriffe wieder schneller sind.
*/
public function has(string $key): bool
{
// Schneller Check im Fast-Cache
if ($this->fastCache->has($key)) {
return true;
}
// Ggf. im Slow-Cache prüfen (und dann in Fast-Cache "aufwärmen")
$slowHit = $this->slowCache->get($key);
if ($slowHit->isHit) {
if($this->shouldCacheInFast($slowHit->value)) {
$this->fastCache->set($key, $slowHit->value, self::FAST_CACHE_TTL);
}
return true;
}
return false;
}
/*
* - **remember**: Holt sich das Item per`get`(inkl. aller Multi-Level-Vorteile, wie bereits vorhanden). Wenn nicht im Cache, wird das Callback ausgeführt, gespeichert und als Treffer zurückgegeben.
*/
public function remember(string $key, callable $callback, int $ttl = 3600): CacheItem
{
$item = $this->get($key);
if ($item->isHit) {
return $item;
}
// Wert generieren, speichern und zurückgeben
$value = $callback();
$this->set($key, $value, $ttl);
// Erstelle neuen CacheItem als Treffer
return CacheItem::hit($key, $value);
}
private function shouldCacheInFast(mixed $value): bool
{
// Wenn es bereits ein String ist (serialisiert), nutze dessen Länge
if (is_string($value)) {
return strlen($value) <= self::MAX_FAST_CACHE_SIZE;
}
// Für Arrays: Schnelle Heuristik ohne Serialisierung
if (is_array($value)) {
$elementCount = count($value, COUNT_RECURSIVE);
// Grobe Schätzung: 50 Bytes pro Element
$estimatedSize = $elementCount * 50;
return $estimatedSize <= self::MAX_FAST_CACHE_SIZE;
}
// Für Objekte: Konservativ - nicht in fast cache
if (is_object($value)) {
return false;
}
// Primitive Typen: Immer cachen
return true;
}
}