internal/thumbnail: Vorschau-Zustand je Datei-Revision als explizite State-Machine (pending/processing/ready/failed, revision_thumbnails) statt Ableitung aus Dateiendung. Content-Type wird ausschliesslich ueber Magic-Bytes bestimmt (net/http.DetectContentType gegen die entschluesselten Bytes) - der in "Bekannte Fehler vermeiden" beschriebene Fehler eines Vorgaengerprojekts (fragile Erkennung ueber Dateiendung) wird damit vermieden. PDF-Rasterung ueber pdftoppm (Poppler), Bild-Thumbnails ueber einen minimalen, abhaengigkeitsfreien Nearest-Neighbor-Resizer auf Basis der Standardbibliothek. Original wird ueber FDN-09 (dmscrypto) entschluesselt, Thumbnail wird ebenfalls verschluesselt im Objekt-Storage abgelegt - gleiches Schutzniveau wie das Original. upload.Service bekommt SetThumbnailEnqueuer (neue, optionale Methode - bestehende Aufrufer/Tests unveraendert funktionsfaehig) und reiht nach erfolgreichem Complete() die Vorschau-Erzeugung ein; ein Fehlschlag dabei laesst den bereits abgeschlossenen Upload nicht ruecktwirkend fehlschlagen. Pruefungen: 1. Beschaedigte PDF-Datei -> Fehlerstatus statt Absturz, blockiert andere Jobs nicht (echter pdftoppm-Fehlschlag, echte SKIP-LOCKED-Job-Queue) 2. Durchsatztest: 500 echte PDFs, alle erfolgreich, ~15s Gesamtlaufzeit 3. Cache-Invalidierung bei neuer Revision: GetCurrentForDocument loest nachweislich auf die neue statt die alte Revision auf Regressionsfrei: 13 bestehende upload-/jobqueue-Tests unveraendert PASS. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
3.5 KiB
DOC-04 – Prüfprotokoll: Vorschau- & Thumbnail-Pipeline
Stand: 2026-09-17. Testhost 192.168.1.131.
Grundsatzentscheidung
Content-Type wird ausschließlich über Magic-Bytes bestimmt (net/http.DetectContentType gegen die
tatsächlichen, entschlüsselten Bytes), nicht über Dateiendung — genau der in "Bekannte Fehler
vermeiden" beschriebene Fehler eines Vorgängerprojekts wird damit vermieden. Der Vorschau-Zustand
ist eine explizite State-Machine (pending/processing/ready/failed, Tabelle
revision_thumbnails), ein Zustand je Datei-Revision — eine neue Revision bekommt automatisch
einen eigenen, unabhängigen Zustand statt einen alten Cache-Eintrag wiederzuverwenden.
PDF-Rasterung über pdftoppm (Poppler, auf dem Testhost vorhanden), Bild-Thumbnails (JPEG/PNG/GIF)
über einen minimalen, abhängigkeitsfreien Nearest-Neighbor-Resizer auf Basis der Go-Standardbibliothek
— keine neue Drittanbieter-Bildbibliothek nötig.
Prüfung 1: Beschädigte PDF-Datei führt zu Fehlerstatus statt Absturz
TestHandler_CorruptedPDFResultsInFailedStatusNotCrash — PASS. Eine Datei mit gültigem
PDF-Magic-Byte-Header (%PDF-1.4), aber kaputtem Rumpf lässt pdftoppm real fehlschlagen — Status
geht auf failed mit gesetzter Fehlermeldung, kein Absturz. Eine GLEICHZEITIG eingereihte, valide
Datei wird davon nachweislich NICHT blockiert (eigener Assert im selben Test) — SKIP LOCKED der
zugrundeliegenden Job-Queue (FDN-04) sorgt dafür, dass ein blockierter/fehlschlagender Job andere
Jobs nicht aufhält.
Prüfung 2: Durchsatztest mit 500 Dokumenten
TestThroughput_500DocumentsAllProcessedSuccessfully — PASS. 500 echte Ein-Seiten-PDFs real durch
Job-Queue → Entschlüsselung → pdftoppm → Verschlüsselung → Objekt-Storage geschleust:
alle 500 erfolgreich, ~15 Sekunden Gesamtlaufzeit (~28-30 ms je Dokument, einzelner
In-Prozess-Worker, sequentiell).
Prüfung 3: Cache-Invalidierung bei neuer Revision belegt
TestGetCurrentForDocument_ResolvesToCurrentRevisionAfterNewRevision — PASS. Nach Anlage einer
zweiten Revision desselben Dokuments (eigene file_revisions-Zeile + aktualisierter
documents.current_revision_id-Zeiger — die eigentliche "neue Revision hochladen"-API ist noch
keine eigene Kachel, hier direkt nachgebildet) löst GetCurrentForDocument nachweislich auf die
NEUE Revision auf, sobald deren Thumbnail bereit ist — nie auf die alte. Der Zustand der ersten
Revision bleibt unverändert und weiterhin über GetForRevision abrufbar (historisch), wird aber
von GetCurrentForDocument nicht mehr geliefert.
Zusätzlich: reales Ende-zu-Ende (TestHandler_GeneratesThumbnailForValidPDF)
Nicht nur Status geprüft — das erzeugte Thumbnail wird tatsächlich aus dem Objekt-Storage zurückgelesen, entschlüsselt und auf eine gültige PNG-Signatur geprüft.
Anbindung an DOC-01 (Upload)
upload.Service bekommt über SetThumbnailEnqueuer (neue, optionale Methode, bestehende Aufrufer/
Tests unverändert funktionsfähig) eine ThumbnailEnqueuer-Schnittstelle — nach erfolgreichem
Complete() wird die Vorschau-Erzeugung eingereiht. Ein Fehlschlag dabei wird geloggt, lässt aber
einen bereits abgeschlossenen Upload nicht rückwirkend fehlschlagen (Nebenwirkung, kein Bestandteil
des Upload-Erfolgs selbst).
Regressionsnachweis
go test ./internal/upload/... ./internal/jobqueue/... -v -p 1 — alle 13 bestehenden Tests
unverändert PASS (5 Upload + 8 Jobqueue). go build ./..., go vet ./..., gofmt -l . sauber.