web: Stale-while-revalidate-Cache für die öffentlichen Seitendaten

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>
This commit is contained in:
Kevin Adametz 2026-07-20 14:29:15 +00:00
parent 5011f28f88
commit bd4ad855ba
6 changed files with 77 additions and 37 deletions

View file

@ -4,6 +4,7 @@ use App\Enums\Portal;
use App\Models\Category;
use App\Models\Company;
use App\Models\PressRelease;
use App\Support\WebPageCache;
use Illuminate\Support\Facades\Cache;
use Livewire\Volt\Volt as LivewireVolt;
use Tests\TestCase;
@ -71,6 +72,33 @@ test('homepage data is cached per portal and language', function () {
expect($freshLead->title)->toBe('Neue Meldung nach Cache-Aufbau');
});
test('web page cache serves stale data instantly instead of rebuilding in the request', function () {
/** @var TestCase $this */
$calls = 0;
$build = function () use (&$calls): string {
$calls++;
return 'version-'.$calls;
};
expect(WebPageCache::remember('web.swr-test', $build))->toBe('version-1');
expect(WebPageCache::remember('web.swr-test', $build))->toBe('version-1');
expect($calls)->toBe(1);
// Frische-TTL (300s) überschritten, Stale-Grenze (3600s) nicht: Der
// Besucher bekommt sofort den alten Stand; der Neuaufbau läuft deferred
// nach der Response, nicht synchron im Request.
$this->travel(10)->minutes();
expect(WebPageCache::remember('web.swr-test', $build))->toBe('version-1');
expect($calls)->toBe(1);
// Nach Ablauf der Stale-Grenze baut der Request wieder synchron.
$this->travel(2)->hours();
expect(WebPageCache::remember('web.swr-test', $build))->toBe('version-2');
});
test('category page data is cached per portal, language and slug but 404s are not cached', function () {
/** @var TestCase $this */
$category = makeCategoryWithSlug(Portal::Businessportal24, 'Mobilität', 'mobilitaet');