From 6b2a39ce7af63973087f2054c449dad16c0669f9 Mon Sep 17 00:00:00 2001 From: Silberengel Date: Wed, 27 May 2026 19:39:22 +0200 Subject: [PATCH] correct prewarm --- src/Command/PrewarmCommand.php | 14 ++- src/Service/MagazineContentService.php | 132 ++++++++++++++----------- 2 files changed, 83 insertions(+), 63 deletions(-) diff --git a/src/Command/PrewarmCommand.php b/src/Command/PrewarmCommand.php index 5d2242e..b3b229b 100644 --- a/src/Command/PrewarmCommand.php +++ b/src/Command/PrewarmCommand.php @@ -168,13 +168,17 @@ final class PrewarmCommand extends Command // any later Nostr phase (long-form can exceed that old cap and was causing max-time fatals). $this->disableCliExecutionTimeLimit(); - $io->section('Long-form in DB (category `a` tags — refresh from Nostr)'); + $io->section('Long-form in DB (magazine root + category `a` tags — refresh from Nostr)'); try { + $nRoot = $this->magazineContent->ingestLongformForMagazineRootHeadline(); + if ($nRoot > 0) { + $io->writeln(sprintf('Magazine root headline strip: refreshed %d long-form coordinate(s).', $nRoot)); + } $n = $this->magazineContent->ingestLongformForAllMagazineCategories(); - if ($n === 0) { - $io->note('No category `a` coordinates in the magazine store (or empty category indices).'); - } else { - $io->writeln(sprintf('Fetched latest long-form for %d coordinate(s) (new rows + NIP-33 updates).', $n)); + if ($n === 0 && $nRoot === 0) { + $io->note('No root or category `a` long-form coordinates in the magazine store (or empty indices).'); + } elseif ($n > 0) { + $io->writeln(sprintf('Category indices: fetched latest long-form for %d coordinate(s) (new rows + NIP-33 updates).', $n)); } $report = $this->magazineContent->buildCategoryArticleDbCoverageReport(); $missingCoords = $this->magazineContent->missingInDbCoordinatesFromCoverageReport($report); diff --git a/src/Service/MagazineContentService.php b/src/Service/MagazineContentService.php index 7887187..b94814f 100644 --- a/src/Service/MagazineContentService.php +++ b/src/Service/MagazineContentService.php @@ -360,6 +360,74 @@ final class MagazineContentService return $n; } + /** + * Kind **30023** / **30024** / **30817** `a` tags on the magazine **root** index (home headline strip). + * Unlike {@see ingestLongformForAllMagazineCategories}, category nested indices are not walked here. + * Nostr I/O — for {@see PrewarmCommand} / cron and optional refresh before rendering the home strip. + */ + public function ingestLongformForMagazineRootHeadline(): int + { + $coords = $this->collectRootHeadlineLongformCoordinates(); + if ($coords === []) { + return 0; + } + $this->nostrClient->ingestLongformForCategoryCoordinates($coords); + + return \count($coords); + } + + /** + * @return list kind:pubkey:d-tag addresses in root `a` tag order (long-form kinds only) + */ + public function collectRootHeadlineLongformCoordinates(): array + { + $npub = (string) $this->params->get('npub'); + $dTag = (string) $this->params->get('d_tag'); + $mag = $this->store->getRoot($npub, $dTag); + if ($mag === null) { + $this->ensureRoot30040FromRelays($npub, $dTag); + $mag = $this->store->getRoot($npub, $dTag); + } + if ($mag === null) { + return []; + } + + $orderedCoords = []; + $seenAddr = []; + foreach ($mag->getTags() as $tagRow) { + $seq = NostrEventTags::rowToStringList($tagRow); + if ($seq === null) { + continue; + } + $name = strtolower((string) ($seq[0] ?? '')); + if ($name !== 'a' || !isset($seq[1]) || (string) $seq[1] === '') { + continue; + } + $coord = trim((string) $seq[1]); + $parts = explode(':', $coord, 3); + if (\count($parts) < 3) { + continue; + } + $kind = (int) $parts[0]; + if (!\in_array($kind, KindsEnum::longformKindValues(), true)) { + continue; + } + $pk = strtolower(trim((string) $parts[1])); + $slug = trim((string) $parts[2]); + if (64 !== \strlen($pk) || !ctype_xdigit($pk) || $slug === '') { + continue; + } + $dedupe = $pk."\0".$slug; + if (isset($seenAddr[$dedupe])) { + continue; + } + $seenAddr[$dedupe] = true; + $orderedCoords[] = $kind.':'.$pk.':'.$slug; + } + + return $orderedCoords; + } + /** * Human-readable prewarm/audit data: what each cached category index (30040) lists and which * coordinates are unresolved in local MySQL `article`. @@ -733,50 +801,7 @@ final class MagazineContentService */ public function buildHomeMagazineRootHeadlineStripData(): array { - $npub = (string) $this->params->get('npub'); - $dTag = (string) $this->params->get('d_tag'); - $mag = $this->store->getRoot($npub, $dTag); - if ($mag === null) { - $this->ensureRoot30040FromRelays($npub, $dTag); - $mag = $this->store->getRoot($npub, $dTag); - } - if ($mag === null) { - return ['tiles' => []]; - } - - $orderedCoords = []; - $seenAddr = []; - foreach ($mag->getTags() as $tagRow) { - $seq = NostrEventTags::rowToStringList($tagRow); - if ($seq === null) { - continue; - } - $name = strtolower((string) ($seq[0] ?? '')); - if ($name !== 'a' || !isset($seq[1]) || (string) $seq[1] === '') { - continue; - } - $coord = trim((string) $seq[1]); - $parts = explode(':', $coord, 3); - if (\count($parts) < 3) { - continue; - } - $kind = (int) $parts[0]; - if (!\in_array($kind, KindsEnum::longformKindValues(), true)) { - continue; - } - $pk = strtolower(trim((string) $parts[1])); - $slug = trim((string) $parts[2]); - if (64 !== \strlen($pk) || !ctype_xdigit($pk) || $slug === '') { - continue; - } - $dedupe = $pk."\0".$slug; - if (isset($seenAddr[$dedupe])) { - continue; - } - $seenAddr[$dedupe] = true; - $orderedCoords[] = $kind.':'.$pk.':'.$slug; - } - + $orderedCoords = $this->collectRootHeadlineLongformCoordinates(); if ($orderedCoords === []) { return ['tiles' => []]; } @@ -786,21 +811,12 @@ final class MagazineContentService $parts = explode(':', $coord, 3); $pairsArg[] = ['pubkey' => strtolower((string) $parts[1]), 'slug' => trim((string) $parts[2])]; } - $indexed = $this->articleRepository->findByAuthorAndSlugIndexed($pairsArg); - $missingCoords = []; - foreach ($pairsArg as $i => $pair) { - $k = strtolower((string) $pair['pubkey'])."\0".trim((string) $pair['slug']); - if (!isset($indexed[$k])) { - $missingCoords[] = $orderedCoords[$i]; - } - } - if ($missingCoords !== []) { - try { - $this->nostrClient->ingestLongformForCategoryCoordinates(array_values(array_unique($missingCoords))); - } catch (\Throwable) { - } - $indexed = $this->articleRepository->findByAuthorAndSlugIndexed($pairsArg); + // Always refresh from relays so NIP-33 updates to root headline articles are not stuck on a stale DB row. + try { + $this->nostrClient->ingestLongformForCategoryCoordinates(array_values(array_unique($orderedCoords))); + } catch (\Throwable) { } + $indexed = $this->articleRepository->findByAuthorAndSlugIndexed($pairsArg); $tiles = []; foreach ($pairsArg as $pair) {