GZip, Cache-Dauer fuer statische Dateien, Sicherungsskript

GZip: Die Startseite ging unkomprimiert raus - 9725 Byte, jetzt 1900.
Zuletzt angemeldet heisst zuerst ausgefuehrt, die Komprimierung liegt damit
aussen.

Statische Dateien: StaticFiles kennt keine Cache-Dauer, per Unterklasse
nachgeruestet. Bewusst nur eine Stunde - die Dateien tragen keinen
Versionsanhaenger, eine lange Dauer wuerde nach einem Update die alte
Fassung festhalten. (Die hochgeladenen Bilder hatten ihre Header laengst;
der Plan behauptete faelschlich das Gegenteil, korrigiert.)

Sicherung: sicherung.sh sichert Datenbank UND Bilder - eine Datenbank ohne
die Fotos ist wertlos. Pfade werden aus der Anwendung gelesen statt geraten.
Die Pruefung oeffnet die Kopie, nicht das Original. Erprobt: 4 Eintraege,
4 Bilder, vollstaendig; ein entferntes Bild wird erkannt.

81 Tests weiterhin gruen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GR4bNaj9GtRu57J4Niii8o
This commit is contained in:
2026-09-13 21:08:44 +02:00
co-authored by Claude Opus 5
parent c748013e4a
commit c9861613cc
3 changed files with 136 additions and 6 deletions
+24 -5
View File
@@ -29,7 +29,7 @@ Die Punkte unten sind Ergänzungen, keine Korrekturen.
---
## P1 — Keine Sicherung der Datenbank
## P1 — Keine Sicherung der Datenbank ✅ ERLEDIGT 13.09.2026
Der wichtigste offene Punkt, und hier wiegt er schwerer als bei der
Kantone-App: In `kleiderboerse.sqlite` stecken Einträge und in `uploads/`
@@ -53,7 +53,7 @@ Punkt 3 ist kein Formalismus: Am 13.09.2026 ist Jellyfin auf demselben
Netzwerk an einer Datenbank-Migration hängengeblieben. Dass es dort
Sicherungen gab, war der einzige Grund, warum die Lage beherrschbar blieb.
## P2 — Antworten werden nicht komprimiert
## P2 — Antworten werden nicht komprimiert ✅ ERLEDIGT 13.09.2026
`app/main.py` bindet keine `GZipMiddleware` ein. Jede HTML- und
HTMX-Antwort geht unkomprimiert über die Leitung — bei einer Galerie mit
@@ -64,7 +64,7 @@ from fastapi.middleware.gzip import GZipMiddleware
app.add_middleware(GZipMiddleware, minimum_size=1000)
```
## P2 — Statische Dateien ohne Cache-Dauer
## P2 — Statische Dateien ohne Cache-Dauer ✅ ERLEDIGT 13.09.2026
```python
app.mount("/static", StaticFiles(directory=...), name="static")
@@ -74,8 +74,10 @@ Ohne `max_age` werden `htmx.min.js`, `theme.js` und die beiden
Swagger-Dateien bei jedem Aufruf neu verhandelt. Eine lange Cache-Dauer
setzen und bei Änderungen einen Versionsanhänger an die URL hängen.
Für die hochgeladenen Bilder gilt dasselbe — die Dateinamen sind zufällig
erzeugt und ändern sich nie, die dürfen dauerhaft im Cache bleiben.
**Korrektur:** Für die hochgeladenen Bilder galt das *nicht* — die haben
ihre Cache-Header längst (`app/routers/images.py` setzt
`max-age=31536000, immutable`). Das war eine Fehlannahme beim Erstellen
dieses Plans.
## P4 — Zwei Filterspalten ohne Index
@@ -93,3 +95,20 @@ Vollständigkeit halber notiert, nicht als Handlungsbedarf.
1. Sicherungen einrichten, inklusive Bilder, mit einer echten Rückspielprobe
2. GZip und Cache-Dauer — zusammen wenige Zeilen
3. Rest nach Bedarf
---
## Umsetzung am 13.09.2026 (Branch `verbesserungen`)
| Punkt | Ergebnis |
|---|---|
| Sicherung | `sicherung.sh`, Datenbank **und** Bilder, geprüft |
| GZip | Startseite 9725 → 1900 Byte (80 %) |
| Statische Dateien | `Cache-Control: public, max-age=3600` |
| Tests | 81 grün, unverändert |
Die Sicherung wurde gegen den laufenden Container erprobt: 4 Einträge,
4 Bilder, alle in der Datenbank verzeichneten Bilder auch wirklich im
Sicherungsordner. Gegenprobe mit entferntem Bild wird erkannt.
Offen bleibt P4 (Indizes auf `gender`/`season`) — ohne praktische Bedeutung.