SRC-02: indexierungs-worker-synchronisierung

Indexierungs-Worker, der neu archivierte Mails asynchron in den
Manticore-Index (SRC-01) einpflegt und Löschungen nachzieht.

- indexworker/queue.go: Postgres-Jobqueue (mail_index_jobs), FOR UPDATE
  SKIP LOCKED, Stale-Lock-Wiedervorlage bei Worker-Absturz, arithmetischer
  Backoff bei Fail (kein String-Concat für Intervalle) — Konvention aus
  dms/internal/jobqueue (FDN-04), hier bewusst ohne DLQ (nicht Bestandteil
  der Akzeptanzkriterien dieser Kachel).
- indexworker/worker.go: RunOnce verarbeitet index-/delete-Jobs über
  search.Client.
- search: minimale Erweiterung um Client.Delete und deterministisches
  DocumentID(tenantSlug, messageID), damit Index/Delete für dieselbe Mail
  immer dasselbe Dokument treffen.

Prüfungen (alle real durchgeführt, siehe mail/docs/SRC-02-PRUEFPROTOKOLL.md):
1. TestDequeue_WorkerCrashMidRunLosesNoJob: simulierter Worker-Absturz,
   Job wird nach Ablauf der Stale-Lock-Frist real erneut zugestellt.
2. TestDeleteJob_RemovesMailFromSearchResults: Lösch-Job entfernt Mail
   nachweislich aus Suchtreffern.
3. TestConsistency_DatabaseAndIndexMatchOnSample: DB-Job-Status und
   Index-Inhalt stichprobenartig real abgeglichen.
Zusätzlich TestIndexJob_MakesMailSearchable für Akzeptanzkriterium 1.

Kein Umbau: storage/crypto/encstorage/dedup unverändert, bestehendes
SRC-01-Verhalten unverändert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HhgFcLS8tYMhDJpP74C6AQ
This commit is contained in:
sysops
2026-08-31 09:47:50 +02:00
co-authored by Claude Sonnet 5
parent c3bf8100b1
commit c5bdde0cc8
8 changed files with 685 additions and 0 deletions
+58
View File
@@ -0,0 +1,58 @@
# SRC-02 Prüfprotokoll: Indexierungs-Worker & Synchronisierung
Voraussetzung SRC-01, ARC-03 (beide Fertig).
## Umsetzung
- `mail/internal/indexworker/migrations/0001_mail_index_jobs.sql`
statisches, versioniertes Schema (`go:embed`) für `mail_index_jobs`
(`job_type` index/delete, `status` pending/processing/succeeded/failed,
`attempts`/`max_attempts`, `available_at`, `locked_at`/`locked_by`).
- `mail/internal/indexworker/queue.go``Queue`: `EnqueueIndex`/
`EnqueueDelete`, `dequeue` (Postgres `FOR UPDATE SKIP LOCKED` +
Stale-Lock-Wiedervorlage, gleiche Konvention wie
`dms/internal/jobqueue` aus FDN-04 — bewusst schlanker, keine DLQ, da
nicht Bestandteil der Akzeptanzkriterien dieser Kachel), `complete`/
`fail` (arithmetischer Backoff, kein String-Concat für Intervalle),
`Status` (Akzeptanzkriterium 3 als Go-API).
- `mail/internal/indexworker/worker.go``Worker.RunOnce`: holt einen
Job, ruft je nach `job_type` `search.Client.Index`/`search.Client.Delete`
auf, markiert abschließend `complete`/`fail`.
- `mail/internal/search`: minimale Erweiterung um `Client.Delete` und
`DocumentID(tenantSlug, messageID)` (deterministische FNV-1a-ID, damit
Index und Delete für dieselbe Mail immer dasselbe Dokument referenzieren,
ohne zusätzlichen Zustand im Worker).
- Kein Umbau: `mail/internal/storage`/`mail/internal/crypto`/
`mail/internal/encstorage`/`mail/internal/dedup` unverändert;
bestehende `search`-Tests/-Verhalten (SRC-01) unverändert.
## Prüfungen
| # | Prüfung | Ergebnis |
|---|---|---|
| 1 | Test: Worker-Neustart mitten im Lauf verliert keinen offenen Auftrag | **bestanden** `TestDequeue_WorkerCrashMidRunLosesNoJob`: Job wird geholt und NICHT abgeschlossen (simulierter Absturz), vor Ablauf der Stale-Lock-Frist real kein zweiter Job verfügbar, nach Ablauf real erneut derselbe Job an einen zweiten Worker zugestellt |
| 2 | Test: Löschung einer Mail entfernt sie zuverlässig aus Suchtreffern | **bestanden** `TestDeleteJob_RemovesMailFromSearchResults`: Mail indexiert und Auffindbarkeit real bestätigt, danach Lösch-Job verarbeitet, anschließende Suche liefert real keinen Treffer mehr |
| 3 | Konsistenztest vergleicht Datenbankbestand mit Indexbestand stichprobenartig | **bestanden** `TestConsistency_DatabaseAndIndexMatchOnSample`: 3 Index-Jobs verarbeitet, je Stichprobe real geprüft, dass der DB-Job-Status `succeeded` UND das zugehörige Dokument tatsächlich im Manticore-Index auffindbar sind |
Zusätzlich (Akzeptanzkriterium 1, Funktionsnachweis): `TestIndexJob_MakesMailSearchable`
— eingereihte Indexierungsaufgabe macht die Mail nach Worker-Verarbeitung
real durchsuchbar.
## Build/Test-Ergebnis (192.168.1.131)
```
go build ./... -> clean
go vet ./... -> clean
golangci-lint run ./... -> 0 issues
TEST_TENANT_DSN=postgresql://nexarch_test:***@localhost:5432/tenant_acme?sslmode=disable \
TEST_MANTICORE_URL=http://127.0.0.1:9308 \
go test ./... -v -p 1 -> alle Pakete bestanden, inkl. internal/indexworker (5 Tests)
```
## Gesamtergebnis
**Bestanden.** Alle drei Akzeptanzkriterien und alle drei Pflichtprüfungen
real erfüllt. SRC-02 ist der nächste Schritt in der Suche-Foundation-Kette
(Manticore-Schema → Schreib-/Suchzugriff → asynchrone Synchronisierung),
nicht nur eine nette Ergänzung — ohne ihn bliebe SRC-01 ein Index ohne
Befüllungspfad. Entsperrt QA-03.