Warum eine angeklickte Artikelseite nur zur Haelfte lud: Die Bild-Route wird je
Tabellenzeile einmal aufgerufen, und ein Browser haelt je Host nur rund sechs
Verbindungen offen. Was diese Route aufhaelt, legt die ganze Oberflaeche lahm.
Sie hielt gleich dreifach auf:
1. Fehlte die lokale Kopie, holte ``images.ensure`` das Bild MITTEN in der
Anfrage von der fremden Adresse - bis zu 15 Sekunden, je Zeile, und bei
jedem Aufruf erneut, weil ein Fehlschlag nirgends vermerkt wurde. Artikel
aus einem Backup-Import haben genau diese Ausgangslage. Gemessen: 2,01 s
je Aufruf, dreimal hintereinander. Jetzt: 0,01 s, das Nachholen laeuft nach
der Antwort im Hintergrund und ein toter Link wird eine Stunde gesperrt.
2. Ein Vorschaubild ist 34x34 Pixel gross - ausgeliefert wurde das Original.
Gemessen: 2530 KB je Briefmarke, bei 40 Zeilen 99 MB fuer eine Liste. Neu
erzeugt die Bild-Route (Pillow) eine Vorschau und legt sie daneben ab;
``?thumb=1`` liefert sie aus. Gemessen: 0,6 KB.
3. If-None-Match wurde ignoriert. Nach den 5 Minuten Cache-Frist lud der
Browser jedes Bild komplett neu - das erklaert, warum es "alle 20 Minuten"
wieder losging. Jetzt 304 ohne Daten.
Dazu im Web: laufende Bildabrufe werden beim Seitenwechsel abgebrochen (sonst
steht die neue Seite hinter Bildern Schlange, die niemand mehr sieht), und wo
``image_version`` bekannt ist, entfaellt die Anfrage fuer bildlose Artikel ganz.
Und der Verbindungsvorrat der Datenbank: 5 (+10) gegen 40 Arbeits-Threads von
FastAPI. Ab der 16. gleichzeitigen Anfrage wartete eine Route stillschweigend
30 Sekunden - von aussen ein haengender Server. Jetzt 10 (+20) mit 10 Sekunden
Frist: lieber ein Fehler als eine halbe Minute Stille.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Item: price_cents + currency (Kaufpreis rappen-/centgenau). Migration ergaenzt.
- Neue Tabelle item_documents (mehrere Belege je Stueck, PDF oder Bild); Blob
wird verzoegert geladen, damit Item-Listen leicht bleiben.
- Endpunkte: Upload (POST), Ansehen/Download (GET), Loeschen (DELETE) je Stueck.
Dateiname beim Download gehaertet (keine Header-Injektion).
- services/warranty.py: schaetzt aus PDF-Text lokal ein Garantieende
(Zeitraum + Kaufdatum, oder Datum nahe Garantie-Stichwort); pypdf ergaenzt.
Der Upload liefert den Vorschlag zurueck. 10 neue Tests, Suite 136 gruen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der Login-Endpunkt nutzt OAuth2PasswordRequestForm (Form-Data); FastAPI
benoetigt dafuer python-multipart. Fehlte in requirements.txt -> RuntimeError
beim Import von auth.py -> Backend-Restart-Loop -> 502.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
passlib 1.7.4 vertraegt sich schlecht mit bcrypt 4.x und kann beim Hashen des
Admin-Passworts im Startup (ensure_first_admin) crashen -> Backend-Container in
Restart-Loop -> 502 in der Web-UI. hash_password/verify_password nutzen jetzt
bcrypt direkt (mit 72-Byte-Grenze). passlib aus requirements entfernt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>