diff --git a/app/Console/Commands/AssignCanonicalPressReleases.php b/app/Console/Commands/AssignCanonicalPressReleases.php index 25d6707b..9adfd1bd 100644 --- a/app/Console/Commands/AssignCanonicalPressReleases.php +++ b/app/Console/Commands/AssignCanonicalPressReleases.php @@ -3,6 +3,7 @@ namespace App\Console\Commands; use App\Services\PressRelease\CanonicalAssigner; +use App\Support\WebCaches; use Illuminate\Console\Command; /** @@ -44,6 +45,14 @@ class AssignCanonicalPressReleases extends Command $dryRun ? 'würden geändert' : 'geändert', )); + // rel=canonical steckt in den gecachten Meldungsseiten, die Sitemaps + // (1 h) nennen nur die Erstquelle — nach einer Zuordnung über den + // Bestand sollen beide sofort den neuen Stand zeigen. + if (! $dryRun && $result['changed'] > 0) { + WebCaches::forgetPublicPages(); + $this->line('Seiten- und Sitemap-Caches geleert.'); + } + return self::SUCCESS; } } diff --git a/dev/2026-09-01/basiswerte-block0.md b/dev/2026-09-01/basiswerte-block0.md index 0dc7e1df..07b395e3 100644 --- a/dev/2026-09-01/basiswerte-block0.md +++ b/dev/2026-09-01/basiswerte-block0.md @@ -68,6 +68,11 @@ erheben. > nachgerüstet, aber die Zahlen oben stammen aus dem Lauf davor. Vor dem > Livegang von Block 1 einmal nachziehen: > `php artisan press-releases:view-distribution --json > basiswert-0.1.json` +> +> **21.09.2026:** Lauf mit `--from=2026-06-01 --to=2026-09-01 --json` auf +> dem Live-Server erfolgt, Datei liegt dort unter +> `dev/2026-09-01/basiswert-0.1.json`. Sobald sie im Repo ist, wird die +> Zeile „28–55 Tage" je Portal hier eingetragen. --- diff --git a/dev/2026-09-01/roadmap-anhang2-2026.md b/dev/2026-09-01/roadmap-anhang2-2026.md index 903bdf5e..e69ac717 100644 --- a/dev/2026-09-01/roadmap-anhang2-2026.md +++ b/dev/2026-09-01/roadmap-anhang2-2026.md @@ -40,8 +40,8 @@ Schneller als über die API geht es zunächst über eine Bestandsabfrage nach id | Nr. | Arbeitspaket | Aufwand | Abhängigkeit | |---|---|---|---| -| ~~1c.7~~ | Doppelveröffentlichung erheben — **gebaut 17.09.2026**: `content_hash`, `press-releases:hash-content`, `press-releases:duplicates-report`. Befund: 9.092 Paare = 53 % des Archivs (Protokoll Teil 9) | S | keine | -| ~~1c.8~~ | Kanonische Zuordnung — **gebaut 17.09.2026, ausgeschaltet bis E9**: `CanonicalAssigner`, `canonical_press_release_id`, Zuordnung bei Veröffentlichung + `press-releases:assign-canonicals`; rel=canonical, mainEntityOfPage, Sitemaps nur Erstquelle. Schalter `CANONICAL_ASSIGNMENT_ENABLED` | M | 1c.7 | +| ~~1c.7~~ | Doppelveröffentlichung erheben — **gebaut 17.09.2026**: `content_hash`, `press-releases:hash-content`, `press-releases:duplicates-report`. Befund Dev: 9.092 Paare = 53 % des Archivs (Protokoll Teil 9); **Live 21.09.2026: 9.221 Paare = 18.442 URLs, 1.468 davon seit 07/2026** | S | keine | +| ~~1c.8~~ | Kanonische Zuordnung — **gebaut 17.09.2026, seit E9 aktiv, Bestand live zugeordnet 21.09.2026 (9.221 Paare; Protokoll Teil 11, Nachtrag Live-Deploy)**: `CanonicalAssigner`, `canonical_press_release_id`, Zuordnung bei Veröffentlichung + `press-releases:assign-canonicals`; rel=canonical, mainEntityOfPage, Sitemaps nur Erstquelle. Schalter `CANONICAL_ASSIGNMENT_ENABLED` | M | 1c.7 | | ~~1c.9~~ | Quellenauskunft — **gebaut 17.09.2026, hinter `GSC_CUSTOMER_VISIBLE`**: `user_canonical` gespeichert, `sourceVerdict()` (eigene / andere eigene Fassung / fremdes Portal), Text im Block „Google-Index" | S | 1c.4, 1c.8 | ### Zur Auswahl in 1c.8 diff --git a/dev/2026-09-01/umsetzung-protokoll.md b/dev/2026-09-01/umsetzung-protokoll.md index acdd7bf5..29276ec4 100644 --- a/dev/2026-09-01/umsetzung-protokoll.md +++ b/dev/2026-09-01/umsetzung-protokoll.md @@ -2149,7 +2149,11 @@ Befunde und was daraus wurde: Konversionsschritte; keine IP, lit. f) plus Frist 395 Tage in Abschnitt 13, auf Hub und beiden Portalen (eine Datei). Text vom Betreiber abgenommen. - 0.1: Kohortenwerte „28–55 Tage" vom Live-System (Fenster 01.06.–01.09.) - einmal erheben und ablegen: `php artisan press-releases:view-distribution --from=2026-06-01 --to=2026-09-01 --json > dev/2026-09-01/basiswert-0.1.json`. + einmal erheben und ablegen: `php artisan press-releases:view-distribution --from=2026-06-01 --to=2026-09-01 --json > dev/2026-09-01/basiswert-0.1.json` + — **am 21.09.2026 auf dem Live-Server erzeugt**, liegt dort unter + `~/pressekonto.com/dev/2026-09-01/basiswert-0.1.json`; ins Repo + übernehmen und in `basiswerte-block0.md` eintragen (siehe Nachtrag + Live-Deploy unten). - Abbruchbedingungen der Blöcke 1–3 tragen weiter Platzhalter für Zeitraum und Schwellwert; Block 1 läuft seit 17.09. ohne festen Vergleichspunkt. - 2.2 Publisher Center (Betreiber), Ergebnis nach 4–6 Wochen in der Search @@ -2284,3 +2288,60 @@ Cache-Treffer, Report je Reader/Feed, Panel, Bereinigung), `config:cache`. 0.7 (Datenschutzerklärung) ist seit dem 21.09.2026 erledigt, siehe oben. +### Nachtrag 21.09.2026 — Live-Deploy des Branches, Zuordnung über den Bestand + +Der Branch `technik/betriebsfixes-2026-09` (Block 1c/1d-Reste, Block 2, +Anhang 1, Anhang 2, E9/E10, 3.1 mit Newsroom-Feeds, RSS-Seite und +Abruf-Protokoll, 0.7, Audit-Blöcke 1–7) ist am 21.09.2026 auf dem +Live-Server. Läufe nach der Migration, in dieser Reihenfolge: + +| Schritt | Ergebnis | +|---|---| +| `press-releases:hash-content` | 179.619 Meldungen geprüft, 179.619 Prüfsummen ergänzt (ganzer Bestand inkl. Altbestand offline) | +| `press-releases:duplicates-report` (13:19) | sichtbar: presseecho 12.753, businessportal24 22.181, both 0; **9.221 Paare = 18.442 URLs**, davon 1.468 Paare seit 07/2026; Zuordnung vorher 0; keine Meldung ohne Prüfsumme | +| `press-releases:assign-canonicals --dry-run` | 9.221 Paare, 9.221 würden geändert | +| `press-releases:assign-canonicals` | **9.223 Paare, 9.221 geändert** | +| `press-releases:view-distribution --from=2026-06-01 --to=2026-09-01 --json` | `basiswert-0.1.json` auf dem Server geschrieben (0.1, siehe oben) | + +Lesart der Zahlen: + +- Live liegen 129 Paare mehr als auf der Dev-Kopie vom 17.09. (9.092) — + die Kopie war älter, seither sind neue Doppelveröffentlichungen + dazugekommen. 1.468 Paare seit Juli bei rund 2.900 Meldungen im + Quartal heißt: **etwa jede zweite neue Meldung erscheint auf beiden + Portalen.** Das ist der Befund aus Anhang 2, jetzt am Bestand belegt. +- Zwischen Dry-Run und scharfem Lauf kamen zwei Paare dazu (9.221 → 9.223), + die der Lauf **nicht** mehr ändern musste: die Zuordnung bei + Veröffentlichung (`CanonicalAssigner::assignFor`) hatte sie bereits + gesetzt. Damit ist der laufende Mechanismus live nachgewiesen, nicht nur + der Nachlauf über den Bestand. +- Erstquelle je Hauptkategorie wie in E9 konfiguriert: sonstiges (3.126 + Paare), politik, haus, reisen, kultur, sport, mode, medizin → presseecho; + it (1.214), handel, motor-verkehr, finanzen, wissenschaft-forschung, + recht → businessportal24. Größter Einzelposten ist `sonstiges` — ein + Drittel aller Paare hat keine fachliche Zuordnung; das ist eher ein + Klassifikations- als ein Kanonisierungsthema. +- Die Sitemaps beider Portale tragen ab jetzt je Paar nur noch die + Erstquelle, die Kopie verweist per rel=canonical dorthin. In der Search + Console zeigt sich das über die nächsten Wochen als Rückgang bei + „Duplikat — Google hat eine andere Seite als kanonisch gewählt" bzw. + „Duplikat — vom Nutzer als kanonisch festgelegt" (1c.5/E8 lesen das aus + `press-releases:check-index-status` ab). + +**Befund aus der Prüfung des Laufs, behoben:** `assign-canonicals` hat die +gecachten Meldungsseiten (rel=canonical, 5 min frisch / 1 h stale) und die +Sitemap-Caches (1 h) nicht geleert — nach dem Nachlauf über den Bestand +zeigten beide bis zu einer Stunde den alten Stand. Der Befehl ruft jetzt +nach einem Lauf mit Änderungen `WebCaches::forgetPublicPages()` auf und +meldet „Seiten- und Sitemap-Caches geleert." (`CanonicalAssignmentTest` +prüft das über den vorher gecachten Sitemap-Stand). Für den Live-Lauf vom +21.09. ist das inzwischen durch die TTL erledigt. + +**Noch zu prüfen auf dem Server** (nicht Teil der Ausgabe oben): +`FEED_FETCHES_RECORDED_SINCE=2026-09-21` und +`CRAWLER_HITS_RECORDED_SINCE=2026-09-21` in der `.env` + `config:cache`; +`categories:seed-descriptions` (2.3); `livewire:publish --assets`; +`queue:restart` und FPM-Neustart; Audit-Plan „Live-Schritte nach dem +Deploy" (`company-memberships:audit`, `--classify --before=`, +`schedule:list` auf `billing:expire-grandfathering`); Rechnungs-Paket +`legacy:settle-unpaid --dry-run` → scharf. diff --git a/tests/Feature/CanonicalAssignmentTest.php b/tests/Feature/CanonicalAssignmentTest.php index f7f82465..80350268 100644 --- a/tests/Feature/CanonicalAssignmentTest.php +++ b/tests/Feature/CanonicalAssignmentTest.php @@ -84,18 +84,28 @@ test('assigning the backlog links the duplicate to the source and the sitemaps l [$pe, $b24] = duplicatePair('it'); + // Vor der Zuordnung nennt jedes Portal seine eigene Fassung — und cached die Sitemap eine Stunde. + $this->get('https://presseecho.test/sitemap.xml')->assertSuccessful() + ->assertSee('https://presseecho.test/de/press-release/doppel-standort', false); + $this->artisan(AssignCanonicalPressReleases::class, ['--dry-run' => true]) ->expectsOutputToContain('[Dry-Run] 1 Paare, 1 würden geändert.') ->assertSuccessful(); expect($b24->fresh()->canonical_press_release_id)->toBeNull(); - $this->artisan(AssignCanonicalPressReleases::class)->expectsOutputToContain('1 Paare, 1 geändert.')->assertSuccessful(); + $this->artisan(AssignCanonicalPressReleases::class) + ->expectsOutputToContain('1 Paare, 1 geändert.') + ->expectsOutputToContain('Seiten- und Sitemap-Caches geleert.') + ->assertSuccessful(); expect($pe->fresh()->canonical_press_release_id)->toBe($b24->id) ->and($b24->fresh()->canonical_press_release_id)->toBeNull(); // Zweiter Lauf ändert nichts mehr. - $this->artisan(AssignCanonicalPressReleases::class)->expectsOutputToContain('1 Paare, 0 geändert.')->assertSuccessful(); + $this->artisan(AssignCanonicalPressReleases::class) + ->expectsOutputToContain('1 Paare, 0 geändert.') + ->doesntExpectOutputToContain('Caches geleert') + ->assertSuccessful(); // Detailseite: die Kopie zeigt per rel=canonical auf die Erstquelle, die Erstquelle auf sich selbst. $this->get('https://presseecho.test/de/press-release/doppel-standort')->assertSuccessful() @@ -104,7 +114,7 @@ test('assigning the backlog links the duplicate to the source and the sitemaps l $this->get('https://businessportal24.test/de/press-release/doppel-standort')->assertSuccessful() ->assertSee('', false); - // Sitemaps: nur die Erstquelle. + // Sitemaps: nur die Erstquelle — der Lauf hat den 1-h-Cache von oben geleert. $this->get('https://presseecho.test/sitemap.xml')->assertSuccessful() ->assertDontSee('https://presseecho.test/de/press-release/doppel-standort', false); $this->get('https://businessportal24.test/sitemap.xml')->assertSuccessful()