Start-/Kategorieseiten bauten nach Ablauf der 5-Minuten-TTL im Besucher- Request neu (~25-30 Archiv-Queries über ~100k PMs) — Long-Tail-Rubriken waren dadurch praktisch bei jedem Aufruf langsam. WebPageCache nutzt jetzt Cache::flexible([300, 3600]): Innerhalb 5 Min frisch wie bisher, danach wird bis zu 1 h sofort der alte Stand serviert und der Neuaufbau läuft nach der Response (deferred). HomePageData/CategoryPageData/TickerData laufen dafür über die gemeinsame WebPageCache-Konvention (Keys unverändert), die Hub-Kennzahlen über flexible([3600, 14400]). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
61 lines
2 KiB
PHP
61 lines
2 KiB
PHP
<?php
|
||
|
||
namespace App\Support;
|
||
|
||
use Closure;
|
||
use Illuminate\Support\Facades\Cache;
|
||
|
||
/**
|
||
* Gemeinsame Cache-Konvention der öffentlichen Web-Seitendaten (HomePageData,
|
||
* CategoryPageData, TickerData, NewsroomDetail/NewsroomsPageData,
|
||
* SuchePageData, CategoryNavigation). Bündelt TTL und `web.`-Präfix an einer
|
||
* Stelle, statt mehrere Konstanten/Magic-Numbers zu pflegen.
|
||
*
|
||
* Stale-while-revalidate (Cache::flexible): Innerhalb der Frische-TTL kommt
|
||
* der Wert direkt aus dem Cache. Danach wird bis zur Stale-Grenze sofort der
|
||
* alte Stand serviert und der Neuaufbau läuft NACH der Response (deferred) —
|
||
* Besucher zahlen den teuren Seitenaufbau (~25–30 Archiv-Queries) nicht mehr
|
||
* im Request, solange die Seite mindestens einmal pro Stale-Fenster besucht
|
||
* wird. Erst nach Ablauf der Stale-Grenze baut der Request wieder synchron.
|
||
*/
|
||
class WebPageCache
|
||
{
|
||
/**
|
||
* Frische-Fenster der Web-Seitendaten in Sekunden: solange gilt der
|
||
* Cache-Eintrag als aktuell und wird ohne Neuaufbau ausgeliefert.
|
||
*/
|
||
public const TtlSeconds = 300;
|
||
|
||
/**
|
||
* Stale-Grenze in Sekunden (ab Cache-Write): bis hierhin wird ein
|
||
* abgelaufener Eintrag noch serviert, während der Neuaufbau im
|
||
* Hintergrund läuft.
|
||
*/
|
||
public const StaleSeconds = 3600;
|
||
|
||
/**
|
||
* Baut einen `web.`-Cache-Key aus Segmenten (leere Segmente entfallen).
|
||
*
|
||
* @param array<int, string|int> $segments
|
||
*/
|
||
public static function key(string $group, array $segments = []): string
|
||
{
|
||
$parts = array_filter(
|
||
array_map(static fn (string|int $segment): string => (string) $segment, $segments),
|
||
static fn (string $segment): bool => $segment !== '',
|
||
);
|
||
|
||
return implode('.', array_merge(['web', $group], $parts));
|
||
}
|
||
|
||
/**
|
||
* @template TValue
|
||
*
|
||
* @param Closure(): TValue $callback
|
||
* @return TValue
|
||
*/
|
||
public static function remember(string $key, Closure $callback): mixed
|
||
{
|
||
return Cache::flexible($key, [self::TtlSeconds, self::StaleSeconds], $callback);
|
||
}
|
||
}
|