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
73 lines
4.2 KiB
Markdown
73 lines
4.2 KiB
Markdown
# 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.
|