docs: Migrationsausfall nachgestellt und Notfallweg dokumentiert

Marcs Sorge ernst genommen und geprüft statt behauptet: eine
absichtlich kaputte Migration in einer Wegwerf-Datenbank laufen lassen.
Ergebnis: schema_migrations bleibt auf dirty=true stehen, und main.go
bricht bei jedem weiteren Start mit log.Fatal ab – das gilt für jede
Migration, nicht nur die des Kalenders, und stand schon vorher so im
Code.

Drei Sicherungen vor der ersten Kalendermigration: nur CREATE TABLE IF
NOT EXISTS (idempotent, nie ALTER an Fremdem), erst auf der Dev-Instanz
hoch und runter, ein pg_dump vor dem ersten produktiven Ausrollen.

Die Notfallzeile (UPDATE schema_migrations SET dirty=false) steht jetzt
ganz oben in TESTING.md – nicht nur für den Kalender, für jede künftige
Migration.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
marcandClaude Sonnet 5 committed 2026-09-03 22:08:09 +02:00
1 parent 0cea81978f
commit e44bed0a34
2 files changed
+64

No files matched your search

+23
View File
@@ -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
+41
View File
@@ -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 <version>` 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,