chore: complete update
This commit is contained in:
124
src/Framework/Cache/MultiLevelCache.php
Normal file
124
src/Framework/Cache/MultiLevelCache.php
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user