Files
nexarch/mail/docs/SRC-09-PRUEFPROTOKOLL.md
T
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

73 lines
4.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SRC-09 Prüfprotokoll: Suchindex-Neuaufbau/Reindexierung
Voraussetzung SRC-01 (Fertig).
## Umsetzung
- `mail/internal/search/reindex.go``Reindexer.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-`RENAME`s 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.