web: Startseiten-Feed cachen + Index gegen Filesort der Feed-Query
Der Livewire-Feed lief auf jeder Startseiten-Impression ungecacht; seine ORDER-BY-published_at-Query kann wegen portal IN (…) keinen bestehenden Index zur Sortierung nutzen und filesortete ~10-20k Zeilen (live gemessen 2,3 s pro Aufruf — die Startseite blieb dadurch trotz Seitendaten-Cache bei 6-9 s TTFB). Zwei Maßnahmen: - Neuer Index (language, status, deleted_at, published_at): Backward Index Scan statt Filesort, Query 2 ms statt 2,3 s — greift auch für ungecachte Livewire-Interaktionen (Zeitraum-Filter, tiefe Seiten). - Feed-Seiten 1-3 laufen über WebPageCache (SWR wie die übrigen Seitendaten); gecacht werden nur items + total, der Paginator wird pro Request neu gebaut (keine Host-URLs des Cache-Erzeugers im Cache). Unbekannte timeframe-Werte aus der URL fallen auf 'all' zurück und erreichen weder Query noch Cache-Key. Der doppelte Gesamt-COUNT pro Request entfällt; der 'Mehr laden'-Zähler nutzt jetzt den gefilterten Total des Paginators. Lokal mit Live-Datenbestand: Startseite kalt 875 ms (vorher 2,5 s), warm 11 ms (vorher 72 ms). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
da189c05b6
commit
6fcc825c64
3 changed files with 151 additions and 15 deletions
|
|
@ -55,8 +55,8 @@ test('homepage data is cached per portal and language', function () {
|
|||
]);
|
||||
|
||||
// Innerhalb der TTL liefert HomePageData den gecachten Stand: Lead bleibt
|
||||
// die alte Meldung. (Der Livewire-Feed ist bewusst ungecacht und zeigt
|
||||
// neue Meldungen sofort.)
|
||||
// die alte Meldung. (Auch der Livewire-Feed cached seine vorderen Seiten
|
||||
// über WebPageCache — neue Meldungen erscheinen nach Ablauf der Frische-TTL.)
|
||||
$cachedLead = $this->get('https://presseecho.test/de')
|
||||
->assertSuccessful()
|
||||
->viewData('leadRelease');
|
||||
|
|
@ -99,6 +99,47 @@ test('web page cache serves stale data instantly instead of rebuilding in the re
|
|||
expect(WebPageCache::remember('web.swr-test', $build))->toBe('version-2');
|
||||
});
|
||||
|
||||
test('the press release feed caches its front pages but not deep pages or junk timeframes', function () {
|
||||
/** @var TestCase $this */
|
||||
$category = makeCategoryWithSlug(Portal::Presseecho, 'Feed-Rubrik', 'feed-rubrik');
|
||||
$company = Company::factory()->presseecho()->create();
|
||||
|
||||
PressRelease::factory()
|
||||
->published()
|
||||
->forPortal(Portal::Presseecho)
|
||||
->for($category)
|
||||
->for($company)
|
||||
->create([
|
||||
'title' => 'Feed-Meldung eins',
|
||||
'slug' => 'feed-meldung-eins',
|
||||
'published_at' => now()->subHour(),
|
||||
]);
|
||||
|
||||
$this->get('https://presseecho.test/de')
|
||||
->assertSuccessful()
|
||||
->assertSeeText('Feed-Meldung eins');
|
||||
|
||||
expect(Cache::has('web.feed.presseecho.de.all.page.1'))->toBeTrue();
|
||||
|
||||
// Tiefe Seiten bleiben ungecacht (Schutz vor unbegrenztem Key-Raum).
|
||||
$this->get('https://presseecho.test/de?page=25')->assertSuccessful();
|
||||
|
||||
expect(Cache::has('web.feed.presseecho.de.all.page.25'))->toBeFalse();
|
||||
|
||||
// Unbekannte timeframe-Werte aus der URL fallen auf "all" zurück und
|
||||
// erzeugen keinen eigenen (poisonbaren) Cache-Key.
|
||||
$this->get('https://presseecho.test/de?timeframe=boesewert')->assertSuccessful();
|
||||
|
||||
expect(Cache::has('web.feed.presseecho.de.boesewert.page.1'))->toBeFalse();
|
||||
|
||||
// Der Cache hält nur items + total — der Paginator (inkl. Host-URLs der
|
||||
// Pagination-Links) wird pro Request neu gebaut, damit der gecachte Feed
|
||||
// nicht den Host des Cache-Erzeugers an andere Besucher ausliefert.
|
||||
expect(Cache::get('web.feed.presseecho.de.all.page.1'))
|
||||
->toBeArray()
|
||||
->toHaveKeys(['items', 'total']);
|
||||
});
|
||||
|
||||
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');
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue