performance: Caching, deferred Tracking & externe Timeouts (H7, M12, M13)

- Navigations-Chrome (CategoryNavigation), Suche- und Newsroom-Seitendaten
  300s gecacht; gemeinsamer WebPageCache-Helper (eine TTL/Key-Konvention).
- Cache-Poisoning über ?page= geschlossen (Key an Paginator ausgerichtet,
  kein withQueryString im Cache); Newsrooms cachet nur den ungefilterten
  Fall und die ersten Seiten (kein unbegrenzter Key-Raum).
- Detailseiten schreiben Hits/View-Events deferred nach der Response
  (M12); OpenAI-/Markt-/USt-ID-Aufrufe mit Connect-Timeouts und
  begrenzten Retries; Admin-Memo-Caches konsistent invalidiert.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-07-14 13:49:47 +00:00
parent 5a492926dd
commit 23cbd0bfe2
18 changed files with 419 additions and 39 deletions

View file

@ -24,12 +24,30 @@ class CategoryNavigation
* Sortiert nach Anzahl veröffentlichter Pressemitteilungen; `null` als
* Limit liefert alle Rubriken (z. B. für das „Mehr“-Dropdown im Header).
*
* Die Navigation rendert auf jeder Web-Seite (Header/Footer/Branchenindex/
* Suche) und ist rein portal-/sprachabhängig → 300s gecacht (wie TickerData),
* sonst ≥2 uncachede Count-Aggregate pro anonymem Seitenaufruf.
*
* @return Collection<int, array{label:string, slug:string, href:string}>
*/
public static function items(?int $limit = 9): Collection
{
$portal = Portal::tryFrom((string) config('app.theme')) ?? Portal::Businessportal24;
$language = app()->getLocale();
$cacheKey = WebPageCache::key('category-nav', [$portal->value, $language, $limit ?? 'all']);
return WebPageCache::remember(
$cacheKey,
static fn (): Collection => self::query($portal, $language, $limit)
);
}
/**
* @return Collection<int, array{label:string, slug:string, href:string}>
*/
private static function query(Portal $portal, string $language, ?int $limit): Collection
{
$portalValues = [$portal->value, Portal::Both->value];
return Category::query()