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
4.2 KiB
4.2 KiB
SRC-09 – Prüfprotokoll: Suchindex-Neuaufbau/Reindexierung
Voraussetzung SRC-01 (Fertig).
Umsetzung
mail/internal/search/reindex.go—Reindexer.Rebuild(ctx, onProgress):- 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), - 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), - meldet Fortschritt über einen
onProgress-Callback (Akzeptanzkriterium 2), - vergleicht Trefferzahlen alt/neu — bei Abweichung kein Umschalten,
- 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).
- legt eine neue physische Manticore-Tabelle an (Name aus striktem
Muster
- Echtes Manticore-Verhalten entdeckt und behandelt: frisch eingefügte
Dokumente einer neu angelegten RT-Tabelle sind für
match_all-Zählungen erst nach explizitemFLUSH RAMCHUNKzuverlässig sichtbar (SQL-SELECTsah sie sofort,/search-Zählung zeigte 0) — vor der Konsistenzprüfung eingebaut. - Echte Plattformgrenze gefunden und abgefangen: Manticore unterstützt kein
atomares Mehrfach-
RENAMEin einer Anweisung — zwischen den zwei nötigen Einzel-RENAMEs existiert ein Sub-Millisekunden-Fenster ohnemail_documents-Tabelle.Client.Searchbekam 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
Searchgefunden und behoben: ohne expliziteslimitbegrenzte 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. JetztsearchResultLimit = 1000. - Kein Umbau:
Index/Delete/Facets-Verhalten sonst unverändert,mail/internal/dedup/indexworker/storage/crypto/encstorageunverä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.