From dfc7ed1001f771933c66511e2eb5aa554529ca6a Mon Sep 17 00:00:00 2001 From: Kevin Adametz Date: Tue, 6 Oct 2026 16:11:58 +0000 Subject: [PATCH] =?UTF-8?q?dev:=20Worker-Ausfall=2006.10.=20dokumentiert?= =?UTF-8?q?=20=E2=80=94=20Runbook=20ohne=20pauschales=20queue:retry=20all,?= =?UTF-8?q?=20Vorgehen=20bei=20stehendem=20Worker,=20externer=20Monitor=20?= =?UTF-8?q?erledigt=20(status.adametz.media)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- dev/betrieb/deploy-runbook.md | 12 +++++++++++- dev/betrieb/deploy-v1.1.0.md | 2 +- dev/betrieb/git-deploy.md | 2 ++ dev/betrieb/monitoring-plan.md | 20 +++++++++++++++++++- 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/dev/betrieb/deploy-runbook.md b/dev/betrieb/deploy-runbook.md index ea03c748..bc43b1ba 100644 --- a/dev/betrieb/deploy-runbook.md +++ b/dev/betrieb/deploy-runbook.md @@ -406,7 +406,17 @@ Doku archiviert unter `dev/archive/optimize/cutover-runbook.md`. (Abschnitt 4) — sonst bleiben die KI-Jobs liegen und eingereichte PMs hängen unbemerkt in der Prüfung. - **Nach MySQL-Neustarts** hängen Worker mitunter in kaputten Verbindungen → - Worker in Ploi neu starten, danach ggf. `php artisan queue:retry all`. + Worker in Ploi neu starten. Fehlgeschlagene Jobs danach **nicht pauschal** + mit `queue:retry all` wiederholen: erst `php artisan queue:failed` ansehen + und nur aktuelle Jobs gezielt per `queue:retry ` neu starten. Alte + Jobs tragen den Stand ihrer Klasse von damals — am 06.10.2026 scheiterten so + Veröffentlichungsmails vom 03./08.09. an einer seither erweiterten Vorlage + (GlitchTip #23), und erfolgreich wären sie als veraltete Mail rausgegangen. +- **Läuft kein Worker** (Systemstatus „Queue-Worker“ kritisch, `/health` 503, + Ende von `deploy.sh` mit Exit 3): `ps -eo pid,lstart,args | grep queue:work`. + Leer → in Ploi Supervisor und Site ▸ Queue neu starten. Notlösung ohne + sudo: `nohup php artisan queue:work database --queue=classification,default --tries=3 --max-time=3600 >> storage/logs/worker-manual.log 2>&1 &` + (endet nach einer Stunde von selbst). - **Öffentliche Seitendaten** laufen über Stale-while-revalidate-Caching (`App\Support\WebPageCache`, `Cache::flexible`) — nach `cache:clear` ist der jeweils erste Aufruf pro Seite langsam (Kaltaufbau), danach dauerhaft schnell. diff --git a/dev/betrieb/deploy-v1.1.0.md b/dev/betrieb/deploy-v1.1.0.md index 4d36f84f..8d5970ba 100644 --- a/dev/betrieb/deploy-v1.1.0.md +++ b/dev/betrieb/deploy-v1.1.0.md @@ -145,7 +145,7 @@ Schlägt `composer install` oder `migrate` fehl: **nicht** `up`, sondern Rollbac ## F — Danach -29. **Externer Monitor** (Uptime Kuma o. Ä.) auf `https://pressekonto.com/health`, +29. **Erledigt 06.10.2026 (status.adametz.media).** **Externer Monitor** (Uptime Kuma o. Ä.) auf `https://pressekonto.com/health`, Header `Authorization: Bearer …`, 60 s, 2 Wiederholungen, Benachrichtigung über ntfy (`push.adametz.media`, `pressekonto-ops`). (1.5) 30. ~~**KAS-Passwort rotieren**~~ (B9/10 Nr. 19) — erledigt 06.10.2026, SSH-Zugang deaktiviert. diff --git a/dev/betrieb/git-deploy.md b/dev/betrieb/git-deploy.md index ef3c0b0c..b91e5b77 100644 --- a/dev/betrieb/git-deploy.md +++ b/dev/betrieb/git-deploy.md @@ -154,6 +154,7 @@ Server vom Tag abweicht. - Es prüft, dass der Checkout sauber ist, und holt die Tags. - Es zeigt neue Migrationen an. Ohne `--migrations` bricht es dann ab, **bevor** etwas verändert ist. - Danach in dieser Reihenfolge: `down`, Checkout, `RELEASE`, `composer install`, gegebenenfalls `migrate`, Livewire-Assets, Caches, `queue:restart`, FPM, `up`, Version. + - Zum Schluss `php artisan monitoring:queue-probe --wait=60`: ein Test-Job muss innerhalb einer Minute von einem Worker abgeholt werden. Sonst endet das Skript mit **Exit 3** und dem Hinweis, Supervisor und den Worker in Ploi zu prüfen — die Seite ist dann schon live. (Seit `v1.3.2`; das Skript läuft aus der Kopie des *vorherigen* Stands, die Prüfung greift also ab dem Deploy nach `v1.3.2`. Beim Deploy von `v1.3.2` selbst danach von Hand `php artisan monitoring:queue-probe` aufrufen.) `--clear-schedule` setzt zusätzlich die `withoutOverlapping`-Sperren zurück. Das ist nur nötig, wenn sich Sperrdauern im Scheduler geändert haben. @@ -255,3 +256,4 @@ Ausfall des Anbieters keinen Deploy abbricht. | 06.10.2026 | `v1.1.3` | `.gitignore`-Muster `Icon` korrigiert, vier Icons versioniert. Erster Git-Deploy `v1.1.0` → `v1.1.3`: keine Migration, Composer „Nothing to install", Caches, Worker, FPM ohne Fehler, Version `v1.1.3`. Danach alte Build-Dateien entfernt. `v1.1.1` und `v1.1.2` waren nie einzeln live. | | 06.10.2026 | `v1.2.0` | Volt entfernt (Livewire-4-Single-File-Components). Erster Deploy, der nur noch `deploy.sh` brauchte: keine Migration, Composer entfernt `livewire/volt`. Vom Betreiber durchgeklickt (Login, Kundenbereich, Admin), unauffällig. | | 06.10.2026 | FPM und Nginx-Fehlerlog | `sudo -S service php8.4-fpm reload` ohne Passwort bestätigt (Master bleibt, Worker neu) — `deploy.sh` lädt FPM künftig selbst, `PK_FPM_RELOAD` bleibt ungesetzt. Nginx-Fehlerlog ausgewertet: Verbindungsabbrüche nur zu den Deploy-Zeitpunkten, `process_control_timeout` bewusst nicht gesetzt (siehe „Betrieb: PHP-FPM beim Deploy“). | +| 06.10.2026 | Worker-Ausfall nach `v1.3.0` | Supervisor lief nicht. `queue:restart` beim Deploy von `v1.3.0` (16:51) hat den Worker beendet, niemand startete ihn neu — KI-Prüfungen, Mails und eine Zahlungsbestätigung lagen über eine Stunde. Aufgefallen über die Systemstatus-Kachel. Supervisor in Ploi neu gestartet, Rückstau mit einem Ersatz-Worker (`nohup`) abgearbeitet. Ursache für den gestoppten Supervisor ohne root-Zugang nicht feststellbar. Folgen: Worker-Prüfung am Ende von `deploy.sh` (`v1.3.2`), externer Monitor auf `/health` (status.adametz.media). | diff --git a/dev/betrieb/monitoring-plan.md b/dev/betrieb/monitoring-plan.md index 6e27960d..8480219f 100644 --- a/dev/betrieb/monitoring-plan.md +++ b/dev/betrieb/monitoring-plan.md @@ -242,7 +242,7 @@ Danach entscheiden: überwiegend `fortify` → `POST /login` auf den Hub beschränken bzw. je IP drosseln (vorher klären, wer den JSON-Login nutzt); überwiegend `livewire` → Honeypot/Turnstile im Formular. -### Externer Monitor auf `/health` — Einrichtung (offen) +### Externer Monitor auf `/health` — Einrichtung (erledigt 06.10.2026, status.adametz.media) Ziel: Ausfälle melden, die die App selbst nicht melden kann (Server weg, PHP-FPM hängt, Scheduler steht, Platte voll). **Uptime Kuma** auf dem @@ -289,3 +289,21 @@ wie Uptime Kuma; fällt dieser aus, kommt kein Push (siehe Schritt 6). ausfällt oder beide Server gemeinsam nicht erreichbar sind. Nach der Einrichtung: Punkt 29 in `deploy-v1.1.0.md` und Phase 1 hier als erledigt eintragen. + +### 06.10.2026 — Worker-Ausfall und Folgen (v1.3.2) + +Nach dem Deploy von `v1.3.0` (16:51) lief über eine Stunde kein Queue-Worker: +Supervisor war gestoppt, `queue:restart` beendete den Worker, niemand startete +ihn neu. Sichtbar war es nur in der Systemstatus-Kachel; einen Alarm gab es +nicht — `/health` hätte 503 geliefert, der externe Monitor war noch nicht +eingerichtet. Beim Abarbeiten scheiterten drei Veröffentlichungsmails vom +03./08.09., die erneut eingestellt worden waren (GlitchTip #23, alte +Serialisierung ohne `$viaSyndication`) — entfernt, nicht nachgesendet. + +- **Externer Monitor** läuft seit 06.10.2026 (`status.adametz.media`, Uptime + Kuma). Er deckt einen stehenden Worker ab: `/health` meldet `queue` + kritisch ab 5 Minuten Wartezeit. Ein zusätzlicher Alarm aus dem Scheduler + wurde deshalb **bewusst nicht** gebaut (wäre doppelt). +- **Worker-Prüfung im Deploy** (`monitoring:queue-probe`, Ende von + `deploy.sh`, Exit 3 ohne Worker). +- **Runbook:** kein pauschales `queue:retry all` mehr; Vorgehen bei stehendem Worker.