chore: PROJ-29 + PROJ-30 als Deployed markiert
This commit is contained in:
+1
-1
@@ -44,7 +44,7 @@
|
|||||||
| PROJ-27 | Container-Ready (Dockerfile + Env-Vars) | In Review | [PROJ-27](PROJ-27-container-ready.md) | 2026-03-28 |
|
| PROJ-27 | Container-Ready (Dockerfile + Env-Vars) | In Review | [PROJ-27](PROJ-27-container-ready.md) | 2026-03-28 |
|
||||||
| PROJ-28 | Self-Service Onboarding (Sign-up, E-Mail-Verifikation, Passwort-Reset) | In Progress | [PROJ-28](PROJ-28-self-service-onboarding.md) | 2026-03-28 |
|
| PROJ-28 | Self-Service Onboarding (Sign-up, E-Mail-Verifikation, Passwort-Reset) | In Progress | [PROJ-28](PROJ-28-self-service-onboarding.md) | 2026-03-28 |
|
||||||
| PROJ-29 | Tenant-Quotas & Usage-Limits | Deployed | [PROJ-29](PROJ-29-tenant-quotas.md) | 2026-03-28 |
|
| PROJ-29 | Tenant-Quotas & Usage-Limits | Deployed | [PROJ-29](PROJ-29-tenant-quotas.md) | 2026-03-28 |
|
||||||
| PROJ-30 | Volltext-Index: Xapian → Manticore Search Migration | Planned | [PROJ-30](PROJ-30-bleve-migration.md) | 2026-03-28 |
|
| PROJ-30 | Volltext-Index: Xapian → Manticore Search Migration | Deployed | [PROJ-30](PROJ-30-bleve-migration.md) | 2026-03-28 |
|
||||||
| PROJ-31 | Billing & Subscriptions (Stripe) | Planned | [PROJ-31](PROJ-31-billing-subscriptions.md) | 2026-03-28 |
|
| PROJ-31 | Billing & Subscriptions (Stripe) | Planned | [PROJ-31](PROJ-31-billing-subscriptions.md) | 2026-03-28 |
|
||||||
|
|
||||||
| PROJ-32 | Message-ID-basierte Duplikatserkennung | Deployed | [PROJ-32](PROJ-32-message-id-dedup.md) | 2026-03-31 |
|
| PROJ-32 | Message-ID-basierte Duplikatserkennung | Deployed | [PROJ-32](PROJ-32-message-id-dedup.md) | 2026-03-31 |
|
||||||
|
|||||||
@@ -0,0 +1,132 @@
|
|||||||
|
# PROJ-30: Volltext-Index: Xapian → Manticore Search Migration
|
||||||
|
|
||||||
|
## Status: Deployed
|
||||||
|
**Created:** 2026-03-28
|
||||||
|
**Last Updated:** 2026-04-04
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
- Requires: PROJ-5 (Speicherung & Indexierung) — bestehende Index-Abstraktion
|
||||||
|
- Requires: PROJ-21 (Multi-Tenancy) — per-Tenant Index-Isolation
|
||||||
|
|
||||||
|
## Motivation
|
||||||
|
|
||||||
|
Xapian erfordert CGO und `libxapian-dev` als System-Dependency. Das verhindert:
|
||||||
|
- Docker-Images (CGO-Build in Containern komplex, Build-Image groß)
|
||||||
|
- Einfache Cross-Compilation
|
||||||
|
- Reproduzierbare Builds ohne native Abhängigkeiten
|
||||||
|
|
||||||
|
**Entscheidung: Manticore Search** statt ursprünglich geplantem Bleve.
|
||||||
|
|
||||||
|
### Warum Manticore statt Bleve
|
||||||
|
|
||||||
|
Das primäre Kriterium ist **Datenmenge und Performance**, nicht Einfachheit. Manticore ist eine in C++ geschriebene Such-Engine (Fork von SphinxSearch) mit MySQL-kompatiblem Protokoll:
|
||||||
|
|
||||||
|
| Metrik | Bleve | Manticore |
|
||||||
|
|---|---|---|
|
||||||
|
| Suchlatenz bei 1M Docs | 50–200ms | 5–20ms |
|
||||||
|
| Index-Durchsatz | ~5.000 Docs/s | ~50.000 Docs/s |
|
||||||
|
| RAM bei 10M Mails | 4–8 GB | 1–2 GB |
|
||||||
|
| Columnar Storage | Nein | Ja |
|
||||||
|
| Highlighting | Ja | Ja |
|
||||||
|
| Fuzzy-Search | Ja | Ja |
|
||||||
|
| CGO im Go-Code | Nein | Nein (MySQL-Protokoll) |
|
||||||
|
|
||||||
|
Manticore läuft als eigener Systemd-Service — kein embedded Mode. Der Trade-off (externer Dienst) ist bei Performance-Priorität gerechtfertigt.
|
||||||
|
|
||||||
|
Elasticsearch/OpenSearch wurden als Alternative geprüft — zu schwer, zu viel Infrastruktur für On-Premise.
|
||||||
|
|
||||||
|
## Architektur nach Migration
|
||||||
|
|
||||||
|
```
|
||||||
|
PostgreSQL
|
||||||
|
→ Metadaten: From, To, Subject, Date, message_id, tenant_id
|
||||||
|
→ Dedup, Audit-Log, User, Tenant, Labels
|
||||||
|
→ strukturierte Filter-Queries
|
||||||
|
|
||||||
|
Manticore Search (Port 9306, MySQL-Protokoll)
|
||||||
|
→ Volltext-Body + Anhang-Text
|
||||||
|
→ Ein Index pro Tenant (saubere Mandantentrennung)
|
||||||
|
→ Real-Time-Index (neue Mail sofort suchbar)
|
||||||
|
→ Highlighting in Suchergebnissen
|
||||||
|
→ BM25+ Relevanz-Ranking
|
||||||
|
|
||||||
|
Suchanfrage in Go:
|
||||||
|
→ PostgreSQL: filtert tenant_id, Datum, From/To → IDs
|
||||||
|
→ Manticore: Volltext-Relevanz über IDs → gerankte Ergebnisse
|
||||||
|
→ Merge in API-Handler
|
||||||
|
```
|
||||||
|
|
||||||
|
## User Stories
|
||||||
|
|
||||||
|
- Als Betreiber möchte ich archivmail ohne CGO kompilieren können (`CGO_ENABLED=0`).
|
||||||
|
- Als Nutzer möchte ich auch bei großen Archiven (>1M Mails) schnelle Suchergebnisse (<20ms).
|
||||||
|
- Als Nutzer möchte ich Treffer im Suchtext hervorgehoben sehen (Highlighting).
|
||||||
|
- Als Admin möchte ich nach einem Absturz den Index mit einem Kommando neu aufbauen können.
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
|
||||||
|
- [x] Manticore läuft als Systemd-Service auf dem Server (Port 9306, nur localhost)
|
||||||
|
- [x] `internal/index/manticore.go` ersetzt `xapian.go` und `xapian_stub.go`
|
||||||
|
- [x] Gleiche Interface-Signatur (`IndexMail`, `Search`, `Delete`, `Close`)
|
||||||
|
- [x] Go-Integration via `go-sql-driver/mysql` (kein CGO)
|
||||||
|
- [x] Pro Tenant ein Manticore Real-Time-Index: `emails_tenant_{id}`
|
||||||
|
- [x] Indizierte Felder: `id`, `subject`, `from_addr`, `to_addr`, `body`, `attachment_names`, `date_ts`
|
||||||
|
- [x] Suchanfragen: Volltext, FROM:, TO:, SUBJECT:, SINCE:, BEFORE:
|
||||||
|
- [x] Migration-Kommando: `archivmail reindex` baut alle Tenant-Indizes neu auf
|
||||||
|
- [x] `CGO_ENABLED=0 go build` funktioniert nach Migration
|
||||||
|
- [x] Manticore-Port 9306 nur auf localhost gebunden (kein externer Zugriff)
|
||||||
|
- [x] `update.sh` prüft ob Manticore installiert ist und installiert es bei Bedarf
|
||||||
|
|
||||||
|
## Edge Cases
|
||||||
|
|
||||||
|
- Bestehender Xapian-Index wird NICHT automatisch migriert — `reindex` liest Roh-Mails aus Storage neu ein
|
||||||
|
- Während `reindex` läuft: Suche liefert unvollständige Ergebnisse (Warnung im Log)
|
||||||
|
- Manticore-Dienst nicht erreichbar → Suche gibt Fehler zurück, Metadaten-Suche (PostgreSQL) bleibt verfügbar
|
||||||
|
- Index beschädigt → `reindex` behebt, kein Datenverlust (Roh-Mails in Storage sind Source of Truth)
|
||||||
|
- Neuer Tenant → Index wird beim ersten Mail-Import automatisch angelegt (`CREATE TABLE IF NOT EXISTS`)
|
||||||
|
|
||||||
|
## Technical Requirements
|
||||||
|
|
||||||
|
- **Engine:** Manticore Search (GPLv2)
|
||||||
|
- **Protokoll:** MySQL-kompatibel, Port 9306
|
||||||
|
- **Go-Treiber:** `github.com/go-sql-driver/mysql`
|
||||||
|
- **CGO:** Nicht erforderlich im Go-Code
|
||||||
|
- **Index-Typ:** Real-Time Index pro Tenant
|
||||||
|
- **Installation:** Offizielles Manticore APT-Repository — Paket bleibt über `apt upgrade` aktuell
|
||||||
|
- **Systemd:** `manticore.service` läuft parallel zu `archivmail.service`
|
||||||
|
- **Konfiguration:** Neuer Abschnitt `manticore:` in `/etc/archivmail/config.yml`
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
manticore:
|
||||||
|
dsn: "manticore@tcp(127.0.0.1:9306)/"
|
||||||
|
enabled: true
|
||||||
|
```
|
||||||
|
|
||||||
|
## Migration Path
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Manticore-APT-Repo einrichten + Paket installieren:
|
||||||
|
curl -s https://repo.manticoresearch.com/manticore-repo.noarch.deb -o /tmp/manticore-repo.deb
|
||||||
|
dpkg -i /tmp/manticore-repo.deb && apt update && apt install -y manticore
|
||||||
|
# danach: apt upgrade hält Manticore automatisch aktuell
|
||||||
|
2. manticore.go implementieren (gleiche Interface wie xapian.go)
|
||||||
|
3. Build-Tag in xapian.go anpassen (beide parallel lauffähig während Entwicklung)
|
||||||
|
4. Integrations-Tests gegen Manticore
|
||||||
|
5. xapian.go + xapian_stub.go entfernen
|
||||||
|
6. `archivmail reindex` auf Server ausführen
|
||||||
|
7. Alten Xapian-Index-Ordner löschen (/var/archivmail/xapian/)
|
||||||
|
8. update.sh: Manticore-Installations-Check hinzufügen
|
||||||
|
```
|
||||||
|
|
||||||
|
## Implementation Notes
|
||||||
|
- `internal/index/manticore.go` — vollständige Implementierung mit `ManticoreTenantManager` + `manticoreIndex`
|
||||||
|
- `TenantIndexer`-Interface in `index.go` abstrahiert Manticore und Legacy-Xapian-Pfad
|
||||||
|
- Morphologie: `lemmatize_de_all,stem_en` (Manticore 25.0.0 — `stem_de` nicht verfügbar via MySQL-Protokoll)
|
||||||
|
- fnv64a-Hash leitet uint64-Row-ID aus SHA-256-Mail-ID ab
|
||||||
|
- `escapeManticoreMatch()` schützt vor Injection in MATCH()-Ausdrücke
|
||||||
|
- `cmd import` und `cmd import-piler` ebenfalls auf Manticore-Backend umgestellt
|
||||||
|
- Deployed auf 131 (bookworm) und 132 (trixie) — Manticore 25.0.0 (bookworm-Paket)
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
- 192.168.1.131: Manticore 25.0.0, 65 Mails indiziert
|
||||||
|
- 192.168.1.132: Manticore 25.0.0, 14.160 Mails indiziert
|
||||||
Reference in New Issue
Block a user