# FDN-04 – Prüfprotokoll: Job-Queue & Worker-Runtime Welle 3. Voraussetzung: FDN-02 (Status "Fertig"). ## Umsetzung `internal/jobqueue`: - `migrations/tenant/0002_processing_jobs.up.sql` — `processing_jobs`-Tabelle (Status `pending`/`processing`/`succeeded`/`failed`/`dead_letter`, `attempts`/`max_attempts`, `available_at` für Backoff-Terminierung, `locked_at`/`locked_by` für die Sperre, `idempotency_key` UNIQUE). - `Queue.Enqueue` — reiht ein, mit optionalem `idempotency_key` (Dedup bei Doppelzustellung, `ON CONFLICT DO UPDATE ... RETURNING id`). - `Queue.Dequeue` — `FOR UPDATE SKIP LOCKED`, holt entweder einen fälligen `pending`-Job oder einen `processing`-Job, dessen Sperre älter als `staleLockAfter` ist (Absturz-Wiedervorlage). Backoff-Intervallarithmetik über `LEAST(attempts, 10) * interval '30 seconds'` — arithmetischer Cast, keine String-Konkatenation (siehe "Bekannte Fehler vermeiden"). - `Queue.Complete`/`Queue.Fail` — bei erschöpften Versuchen wandert der Job in `dead_letter`. - `Queue.RequeueDeadLetter` — manuelle Wiederholung eines DLQ-Eintrags. - `Queue.Status` — Job-Status abfragbar. - `Worker`/`Handler` — In-Prozess-Worker-Goroutine, pollt und ruft `Handler` je Job auf. ## Prüfungen | # | Prüfung | Ergebnis | |---|---|---| | 1 | Absturz eines Workers führt zu erneuter Zustellung | **bestanden** — `TestDequeue_StaleLockIsRedelivered`: Job wird von `worker-crashed` gesperrt, NIE completed/failed (simulierter Absturz); sofortiger erneuter Dequeue-Versuch liefert `ErrNoJobAvailable` (Sperre noch frisch), nach Ablauf von `staleLockAfter` liefert `worker-2` denselben Job | | 2 | Idempotenz bei Doppelzustellung nachgewiesen | **bestanden** — `TestEnqueue_IdempotencyKeyPreventsDuplicate`: zweifache Einreihung mit gleichem `idempotency_key` erzeugt nachweislich nur 1 Zeile (per Abfrage bestätigt) | | 3 | DLQ-Eintrag manuell wiederholbar | **bestanden** — `TestRequeueDeadLetter`: Job nach erschöpften Versuchen in `dead_letter`, `RequeueDeadLetter` setzt zurück auf `pending` mit `attempts=0`; Requeue eines NICHT-DLQ-Jobs wird korrekt abgewiesen | ## Reale Fehler gefunden und behoben (kein Vorab-Wissen, beim Testen entdeckt) 1. **pgx-Typinferenz-Fehler bei ungenutztem Parameter**: `Dequeue`s SQL übergab `workerID` als `$1`, ohne es in der Query zu referenzieren — Postgres/pgx konnte den Typ von `$1` dadurch nicht ableiten (`SQLSTATE 42P18`). Behoben durch Entfernen des toten Parameters (workerID wird erst im nachfolgenden `UPDATE` gebraucht). 2. **`$2::text[]`-Cast mit untypisiertem `nil`**: `typeFilter any` (statt `[]string`) ließ pgx den Zieltyp des Casts nicht auflösen. Behoben durch `[]string`-Typisierung der Variable. 3. **Testinfrastruktur-Drift über Sitzungsgrenzen**: `dms_tenant_test` sammelte über mehrere Testläufe (FDN-02/03/04) `schema_migrations`-Zustand an, wodurch `internal/migrate`s Rollback-Test nur noch einen Teil der Tabellen zurückrollte. Neues `scripts/reset-test-env.sh` (Datenbank droppen+neu anlegen, analog Core `scripts/reset-test-env.sh`) sowie `make check`-Target (Reset+vet+lint+test in einem Rutsch) behoben das strukturell. Zusätzlich fehlte `-p 1` im `test`-Target — mehrere Testpakete teilen sich dieselbe physische Test-DB, parallele Paketausführung (Go-Testdefault) verursachte Querschläger zwischen `internal/jobqueue` und `internal/migrate`. 4. **`internal/jobqueue`s Test-Fixture räumte nicht auf**: `TRUNCATE` statt `DROP TABLE` ließ die Tabelle `processing_jobs` stehen, wodurch `internal/migrate`s eigene, versionierte Migration mit `relation already exists` scheiterte. Behoben durch `DROP TABLE IF EXISTS` im Test-Cleanup. ## Build/Test-Ergebnis (192.168.1.131, `make check`) ``` go build ./... -> clean scripts/reset-test-env.sh -> dms_tenant_test leer neu angelegt go vet ./... -> clean golangci-lint run ./... -> 0 issues go test ./... -p 1 -count=1 -> 4/4 Pakete ok, 0 Fehlschläge (inkl. 8 jobqueue-Tests, 3 migrate-Tests, 6 storage-Tests real gegen MinIO) ``` ## Gesamtergebnis **Bestanden.** Alle drei Akzeptanzkriterien und alle drei Pflichtprüfungen erfüllt. Vier reale Fehler beim Testen gefunden und behoben (zwei Produktionscode-Bugs im SQL-Parameterhandling, zwei Testinfrastruktur-Bugs) — bestätigt erneut den Wert, jede Prüfung tatsächlich auf einem echten Testhost auszuführen statt nur zu behaupten.