diff --git a/TESTING.md b/TESTING.md index 89b990b..449aa31 100644 --- a/TESTING.md +++ b/TESTING.md @@ -9,6 +9,29 @@ Manuelle Test-Checkliste für die fertigen Phasen. Abhaken beim Durchtesten. --- +## Notfall: Migration hängt fest ("Dirty database version") + +Betrifft jede künftige Migration, nicht nur eine bestimmte. Nachgestellt und +bestätigt (siehe kalender-plan.md, Abschnitt „Migrationen"): Scheitert eine +Migration, bleibt `schema_migrations.dirty` auf `true` stehen, und **jeder** +weitere Start von Aether bricht ab – die ganze Cloud, nicht nur der neue Teil. + +Kein Datenverlust dabei: Die Migration lief in einer Transaktion und wurde +zurückgerollt, bevor der Fehler kam. `dirty=true` ist nur eine Sperre, keine +Aussage über beschädigte Daten. + +Beheben: + + docker exec aether-db psql -U aether -d aether \ + -c "UPDATE schema_migrations SET dirty=false;" + +Danach Aether neu starten. Lief die Migrationsdatei nur teilweise (z. B. zwei +`CREATE TABLE` in einer Datei, das erste gelang), vorher prüfen, was bereits +existiert, bevor man einen erneuten Lauf zulässt – sonst scheitert der zweite +Versuch am selben Fehler wie der erste. + +--- + ## Phase 3 – Admin, Gruppen, Theming, Profil ### Admin-Panel: Zugriff & Sicherheit diff --git a/kalender-plan.md b/kalender-plan.md index 25b3dbc..092067b 100644 --- a/kalender-plan.md +++ b/kalender-plan.md @@ -242,6 +242,47 @@ Zwei verschiedene Dinge, die man leicht verwechselt: **Emojis im Kalendernamen** sind kein Protokollthema – der Name ist Text. „🏠 Haushalt" kommt überall an. +## Migrationen: geprüft, was bei einem Fehler wirklich passiert + +Nicht angenommen, sondern nachgestellt: eine absichtlich kaputte Migration in +einer Wegwerf-Datenbank laufen lassen. Ergebnis, damit hier niemand rät: + + 1/u ok + error: relation "cal_calendars" already exists + → schema_migrations steht auf version=2, dirty=true + → jeder weitere Start: "Dirty database version 2. Fix and force version." + +**Der zweite Teil ist der eigentliche Befund:** Die eine kaputte Datei bleibt +nicht lokal begrenzt. `main.go` bricht bei einem Migrationsfehler mit +`log.Fatal` ab – das gilt für **jede** Migration, nicht nur für die des +Kalenders, und stand schon vor diesem Vorhaben so im Code. Eine hängende +Migration verhindert also den Start der ganzen Cloud, bis jemand von Hand +`migrate force ` ausführt. Genau das darf einem „Extra" nicht +passieren – deshalb drei Sicherungen, bevor die erste Kalendermigration +überhaupt geschrieben wird: + +1. **Nur `CREATE TABLE IF NOT EXISTS`, nie `ALTER` an Fremdem.** Idempotent: + Selbst wenn eine Datei mitten in einem Mehr-Tabellen-Schritt abbricht, ist + ein erneuter Lauf nach `migrate force` ein Nichts-tun statt eines zweiten + Fehlers. +2. **Erst auf der Dev-Instanz, hoch und runter**, mit denselben 40 + bestehenden Migrationen davor – nicht in einer leeren Testdatenbank wie + beim Nachstellen hier. +3. **Ein `pg_dump` vor dem ersten produktiven Ausrollen.** Sekundensache, + und die Rückversicherung für den Fall, den die ersten beiden Punkte + eigentlich schon ausschließen sollen. + +Und für den Fall, dass es trotzdem einmal passiert – nicht nur beim +Kalender, bei jeder künftigen Migration –, gehört die Notfallzeile in +`TESTING.md`: + + docker exec aether-db psql -U aether -d aether \ + -c "UPDATE schema_migrations SET dirty=false;" + +Kein Datenverlust dabei: Die fehlgeschlagene Migration lief in einer +Transaktion und wurde zurückgerollt (im Test oben existierte `cal_calendars` +danach nicht) – die Zeile hebt nur die Sperre auf, nichts sonst. + ## Die Notausfahrt Ein Kalender, der lautlos einen Termin verschluckt, ist schlimmer als einer,