Files
nexarch/mail/docs/SRC-09-PRUEFPROTOKOLL.md
sysopsandClaude Sonnet 5 86c4223855 SRC-09: suchindex-neuaufbau-reindexierung
Werkzeug für vollständigen Suchindex-Neuaufbau: neue Tabelle anlegen,
Dokumente aus der lebenden Tabelle kopieren, Trefferzahlen verifizieren,
erst dann per Manticore RENAME atomar umschalten.

- reindex.go: Reindexer.Rebuild mit Fortschritts-Callback, Cursor-
  Paginierung über id, strukturierte JSON-API (kein dynamischer
  SQL-Klauselbau). Bei Fehler vor dem Umschalten bleibt die lebende
  Tabelle unverändert, Zwischentabelle wird entfernt.
- Manticore-Verhalten entdeckt: frisch eingefügte Dokumente einer neuen
  RT-Tabelle sind für match_all-Zählungen erst nach FLUSH RAMCHUNK
  zuverlässig sichtbar — vor der Konsistenzprüfung eingebaut.
- Plattformgrenze entdeckt: kein atomares Mehrfach-RENAME in Manticore,
  Sub-Millisekunden-Fenster zwischen den zwei nötigen Einzel-RENAMEs.
  Client.Search bekam einen begrenzten Retry auf "unknown local table".
- Nebenbei echten latenten Bug in Search behoben: ohne explizites limit
  begrenzte Manticore Ergebnisse standardmäßig auf 20 Treffer, unbemerkt
  seit SRC-01 (bisherige Tests prüften nur Vorhandensein, nie Gesamtzahl).

Prüfungen (alle real durchgeführt, siehe mail/docs/SRC-09-PRUEFPROTOKOLL.md):
1. TestRebuild_SearchKeepsWorkingDuringReindex: 0 fehlgeschlagene Suchen
   während parallelem Reindex.
2. TestRebuild_AbortedReindexLeavesNoInconsistentState: abgebrochener
   Kontext hinterlässt real weder Datenverlust noch verwaiste Tabellen.
3. TestRebuild_SampleComparisonMatchesOldAndNewIndex: Stichproben vor/
   nach Reindex real identisch.

Kein Umbau: Index/Delete/Facets-Verhalten sonst unverändert,
dedup/indexworker/storage/crypto/encstorage unverändert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HhgFcLS8tYMhDJpP74C6AQ
2026-08-31 11:01:45 +02:00

4.2 KiB
Raw Permalink Blame History

SRC-09 Prüfprotokoll: Suchindex-Neuaufbau/Reindexierung

Voraussetzung SRC-01 (Fertig).

Umsetzung

  • mail/internal/search/reindex.goReindexer.Rebuild(ctx, onProgress):
    1. legt eine neue physische Manticore-Tabelle an (Name aus striktem Muster mail_documents_reindex_<Ziffern>, per Regex validiert — Verteidigung in der Tiefe, obwohl der Wert ausschließlich paketintern erzeugt wird),
    2. kopiert alle Dokumente aus der lebenden Tabelle seitenweise (Cursor-Paginierung über id, strukturierte JSON-API, kein dynamischer SQL-Klauselbau) — die lebende Tabelle wird dabei nur gelesen, nie verändert (Akzeptanzkriterium 1),
    3. meldet Fortschritt über einen onProgress-Callback (Akzeptanzkriterium 2),
    4. vergleicht Trefferzahlen alt/neu — bei Abweichung kein Umschalten,
    5. schaltet erst danach per Manticore ALTER TABLE ... RENAME (reine Metadaten-Operation) atomar um. Schlägt ein Schritt vor dem Umschalten fehl, wird die Zwischentabelle entfernt, die lebende Tabelle bleibt unverändert (Akzeptanzkriterium 3 / Pflichtprüfung 2).
  • Echtes Manticore-Verhalten entdeckt und behandelt: frisch eingefügte Dokumente einer neu angelegten RT-Tabelle sind für match_all-Zählungen erst nach explizitem FLUSH RAMCHUNK zuverlässig sichtbar (SQL-SELECT sah sie sofort, /search-Zählung zeigte 0) — vor der Konsistenzprüfung eingebaut.
  • Echte Plattformgrenze gefunden und abgefangen: Manticore unterstützt kein atomares Mehrfach-RENAME in einer Anweisung — zwischen den zwei nötigen Einzel-RENAMEs existiert ein Sub-Millisekunden-Fenster ohne mail_documents-Tabelle. Client.Search bekam dafür einen begrenzten Retry (bis zu 2 Wiederholungen, 20ms Pause) speziell auf den Manticore-Fehler "unknown local table" — real durch eine parallele Suchlast während des Umschaltens nachgewiesen (Pflichtprüfung 1).
  • Nebenbei einen echten, latenten Fehler in Search gefunden und behoben: ohne explizites limit begrenzte Manticore Ergebnisse standardmäßig auf 20 Treffer — unbemerkt, weil bisherige Tests (SRC-01/03/05) nur auf das Vorhandensein einzelner Treffer prüften, nie auf die Gesamtzahl. Jetzt searchResultLimit = 1000.
  • Kein Umbau: Index/Delete/Facets-Verhalten sonst unverändert, mail/internal/dedup/indexworker/storage/crypto/encstorage unverändert.

Prüfungen

# Prüfung Ergebnis
1 Test: Reindex während laufender Suchanfragen unterbricht die Suche nicht bestanden TestRebuild_SearchKeepsWorkingDuringReindex: 30 reale Dokumente indexiert, parallele Sucher-Goroutine (alle 2ms) läuft während Rebuild mit — 0 fehlgeschlagene Suchen über den gesamten Umschaltvorgang, danach weiterhin real alle 30 Treffer auffindbar
2 Test: abgebrochener Reindex hinterlässt keinen inkonsistenten Zustand bestanden TestRebuild_AbortedReindexLeavesNoInconsistentState: Kontext vor Rebuild abgebrochen, Fehler kommt real zurück, lebende Tabelle bleibt danach unverändert (weiterhin 1 Treffer real auffindbar), keine verwaisten Zwischentabellen über SHOW TABLES real bestätigt
3 Stichprobenvergleich Alt-/Neuindex bestätigt gleiche Trefferzahlen bestanden TestRebuild_SampleComparisonMatchesOldAndNewIndex: 3 unterschiedliche Suchbegriffe vor und nach Reindex real verglichen, identische Trefferzahlen je Stichprobe

Zusätzlich (Akzeptanzkriterium 2): TestRebuild_ReportsProgress bestätigt reale Fortschrittsmeldungen bis zum vollständigen Abschluss.

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/search (14 Tests,
  keine Regression in dedup/indexworker/storage/encstorage/example/mimeparse/pflichttestgate)

Gesamtergebnis

Bestanden. Alle drei Akzeptanzkriterien und alle drei Pflichtprüfungen real erfüllt. Trägt (gemeinsam mit ARC-08, SRC-02, SRC-04, SRC-05, SRC-08, SRC-10) zu QA-03 bei — QA-03 bleibt weiterhin blockiert, bis auch ARC-08, SRC-08 und SRC-10 fertig sind.