From 39f91a2e3534234e93c6fffa1c80d2def1e83939 Mon Sep 17 00:00:00 2001 From: Sebastian Frank Date: Tue, 20 Oct 2026 14:28:25 +0000 Subject: [PATCH] Konfiguration: Such-Worker- und Import-Tuning dokumentieren Neue Server-Schalter aus tibi-server 3d052ae (Search-Worker): - server/konfiguration: neuer Abschnitt "Suche: Import-Tuning und Worker-Pool" mit search.vectorEmbedMaxTexts, workerWindowSize, workerConcurrency, writeConcurrency inkl. Env-Namen, Import-Empfehlung und Grenzen (gleiche Sammlung nie parallel, Werte nur beim Start). - server/betrieb: Stoerungstabelle um den Fall "Import laeuft zaeh" ergaenzt. - projekt/suche: Status-Endpunkt nennt jetzt alle laufenden Jobs (inFlightJobs) statt genau einem. Build und audit-docs.mjs gruen (0 Findings), Anker geprueft. --- plans/audit-report.json | 2 +- src/content/docs/projekt/suche.mdx | 4 ++-- src/content/docs/server/betrieb.mdx | 3 ++- src/content/docs/server/konfiguration.mdx | 26 ++++++++++++++++++++++- 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/plans/audit-report.json b/plans/audit-report.json index 6641e7c..923a1ca 100644 --- a/plans/audit-report.json +++ b/plans/audit-report.json @@ -1,5 +1,5 @@ { - "generatedAt": "2026-10-20T14:15:03.662Z", + "generatedAt": "2026-10-20T14:28:23.273Z", "stats": { "files": 70, "byDir": { diff --git a/src/content/docs/projekt/suche.mdx b/src/content/docs/projekt/suche.mdx index 27b4819..628bb62 100644 --- a/src/content/docs/projekt/suche.mdx +++ b/src/content/docs/projekt/suche.mdx @@ -102,7 +102,7 @@ Alle Modi aus `collection.go:314` — `fields` gilt für `regex` und `ngram`, `v 2. Beobachte im tibi-admin den Hinweis `SearchIndexBuildNotice`: Er erscheint im Projekt-Header (Summe offener `_queue`-Einträge aller `ngram`-/`vector`-Sammlungen) und im Sammlungs-Header der betroffenen Sammlung. 3. Warte, bis der Hinweis nach dem nächsten Polling von selbst verschwindet (`_queue` = 0). Der `regex`-Modus (`default`) hat keine Queue und keinen Hinweis. 4. Bleibt die Queue stehen oder hast du die Config geändert: `POST /_/:project/_/admin/regenerate-search` aufrufen — optional mit Body `{ collection, modes, names, ids, filter, force }` (`admin_regenerate_search.go:17-25`). Mit `?async=1` nur einreihen und sofort antworten (`{"message": "queued", …}`), ohne `filter` auch synchron möglich. Ungültige IDs ohne einzige gültige Hex-ID brechen mit `400 no valid document IDs in request` ab. -5. Status prüfen: `GET /_/:project/_/admin/search-worker/status` zeigt pro Provider Aktiv-Flag, Queue-Tiefe, laufenden Job und Fortschrittszähler (`admin_search_status.go:10-15`). Auth jeweils: Scope `project.regenerate-search` plus Token-Flag `AllowRegenerateSearch`. +5. Status prüfen: `GET /_/:project/_/admin/search-worker/status` zeigt pro Provider Aktiv-Flag, Queue-Tiefe, alle laufenden Jobs (`inFlightJobs`, bei parallelen Workern mehr als einer) und Fortschrittszähler (`admin_search_status.go:10-15`). Auth jeweils: Scope `project.regenerate-search` plus Token-Flag `AllowRegenerateSearch`. @@ -247,4 +247,4 @@ Zwei Dense-Speicherformen sind im Umlauf: BSON-Binary (aktuell) und ein Legacy-B Weiter: [Lesen und suchen](/projekt/abfragen-lesen/), [Sammlungen anlegen](/projekt/sammlungen-anlegen/), [Felder und Widgets](/projekt/felder-widgets/). -Verifiziert am e3f92eb 2026-10-14 (tibi-svelte-starter), am 68b4278 2026-10-15 (tibi-server, rankfusion), am 2b091d8 2026-10-13 (tibi-admin-nova, Test-Plan 41-search-index-status), am 63a2848 2026-10-19 (tibi-server: combinedCache, ngram.inMemory, _count-Fast-Path, Restore-Rebuild), am 76f1336 2026-10-19 (tibi-server: ngram.stopwords, Regenerate-Endpunkt, mongo(no-terms)); am 92c3ad74 2026-10-20 (tibi-server: kompakter ngramindex, collection_ngram_search.go, Hook-Pipeline-Klassifikation, X-Search-Memory), am 654b568 2026-10-19 (tibi-server: kompakter Sparse-Vektorindex, Legacy-Dense-Format, MemoryEstimate, vectormigrate, paralleler Range-Loader inkl. Retry/Semaphore), am 9e12a8e 2026-10-19 (tibi-types: ngram.stopwords/queryFilter/inMemory im Schema), am 21472bd 2026-10-19 (tibi-types: ngram.sizes 2–10, combinedCache im Schema), am cf44cd7 2026-10-19 (tibi-svelte-starter: tibi-types-Submodul auf 21472bd), am d0d699d 2026-10-20 (tibi-server: collection_facet_search.go, rrf.topK-Default 500, qLimit) +Verifiziert am e3f92eb 2026-10-14 (tibi-svelte-starter), am 68b4278 2026-10-15 (tibi-server, rankfusion), am 2b091d8 2026-10-13 (tibi-admin-nova, Test-Plan 41-search-index-status), am 63a2848 2026-10-19 (tibi-server: combinedCache, ngram.inMemory, _count-Fast-Path, Restore-Rebuild), am 76f1336 2026-10-19 (tibi-server: ngram.stopwords, Regenerate-Endpunkt, mongo(no-terms)); am 92c3ad74 2026-10-20 (tibi-server: kompakter ngramindex, collection_ngram_search.go, Hook-Pipeline-Klassifikation, X-Search-Memory), am 654b568 2026-10-19 (tibi-server: kompakter Sparse-Vektorindex, Legacy-Dense-Format, MemoryEstimate, vectormigrate, paralleler Range-Loader inkl. Retry/Semaphore), am 9e12a8e 2026-10-19 (tibi-types: ngram.stopwords/queryFilter/inMemory im Schema), am 21472bd 2026-10-19 (tibi-types: ngram.sizes 2–10, combinedCache im Schema), am cf44cd7 2026-10-19 (tibi-svelte-starter: tibi-types-Submodul auf 21472bd), am d0d699d 2026-10-20 (tibi-server: collection_facet_search.go, rrf.topK-Default 500, qLimit), am 3d052ae 2026-10-20 (tibi-server: searchWorker-Status mit inFlightJobs, parallele Worker/Write-Stage) diff --git a/src/content/docs/server/betrieb.mdx b/src/content/docs/server/betrieb.mdx index 2b18e68..f8a9150 100644 --- a/src/content/docs/server/betrieb.mdx +++ b/src/content/docs/server/betrieb.mdx @@ -110,10 +110,11 @@ Waisen findest du per Dateisuche im Upload-Pfad (`media/` bzw. `uploadPath` der | `version` antwortet nicht | Container down, falscher Port | `docker compose ps`, Logs prüfen | | Login wird immer langsamer | Ratelimit-Backoff nach Fehlversuchen | Warten (Retry-After), Zugangsdaten prüfen | | Suche findet nichts Neues | Worker hängt oder Index alt | Worker-Status abfragen, `regenerate-search` | +| Import/Vektorisierung läuft zäh | Ein Endpoint trägt die ganze Arbeit: Fenster zu klein, Range zu groß, zu wenig parallele Schreibvorgänge | `search.workerWindowSize`/`vectorEmbedMaxTexts`/`writeConcurrency` setzen, siehe [Server-Konfiguration](/server/konfiguration/#suche-import-tuning-und-worker-pool-search) | | 413 bei Upload | Body-Limit erreicht (Server → Projekt → Collection) | `API_UPLOAD_MAX_BODY_SIZE` bzw. Collection-Limit erhöhen | | `warning: Document deleted, but file cleanup …` | Upload-Verzeichnis ließ sich nicht entfernen (Rechte, Pfad) | Log-Zeile `delete cleanup failed …` prüfen, Rest per Dateisuche im Upload-Pfad entfernen | | Leere Seite trotz Daten | CORS blockt den Browser | Origins in der Collection-Config prüfen | Begriffe wie Collection, Hook oder Namespace klärt [Begriffe](/einstieg/begriffe/). Zum Einrichten siehe [Schnellstart](/einstieg/schnellstart/). -Verifiziert am d272041 2026-10-17 (tibi-server); Compose-Profile am e3f92eb 2026-10-14 (tibi-svelte-starter). Datei-Cleanup aus `internal/filecleanup/cleanup.go` und Aufrufern (`collection_delete.go`, `collection_bulk_delete.go`, `collection_put.go`, `hook/context_db.go`). Embedding-Status aus `internal/controller/admin_embedding_status.go` und `internal/embedding/registry.go` (Snapshot/Health-Loop). +Verifiziert am d272041 2026-10-17 (tibi-server); Compose-Profile am e3f92eb 2026-10-14 (tibi-svelte-starter). Datei-Cleanup aus `internal/filecleanup/cleanup.go` und Aufrufern (`collection_delete.go`, `collection_bulk_delete.go`, `collection_put.go`, `hook/context_db.go`). Embedding-Status aus `internal/controller/admin_embedding_status.go` und `internal/embedding/registry.go` (Snapshot/Health-Loop). Import-Tuning der Such-Worker am 3d052ae 2026-10-20 (tibi-server: `search.*`, `internal/models/search_worker.go`). diff --git a/src/content/docs/server/konfiguration.mdx b/src/content/docs/server/konfiguration.mdx index 068a633..dd1c7e8 100644 --- a/src/content/docs/server/konfiguration.mdx +++ b/src/content/docs/server/konfiguration.mdx @@ -186,6 +186,30 @@ search: - Änderungen an `enabled`/`maxMemoryMB` wirken erst nach einem Projekt-Reload (`POST /_/:project/_/admin/reload` bzw. Serverneustart). - Snapshot- und Backup-Restore verwerfen und laden alle In-Memory-Zustände (N-Gram-Indizes, Vektor-Indizes, Combined-Cache) neu — bis der Neuaufbau fertig ist, laufen die betroffenen Suchen über MongoDB. +## Suche: Import-Tuning und Worker-Pool (`search.*`) + +Die vier Schalter darunter steuern, wie viel ein großer Import (Zehntausende Dokumente) parallel arbeitet. Alle sind optional; ohne Angabe bleibt alles beim bisherigen Verhalten. + +```yaml +search: + vectorEmbedMaxTexts: 25 # Texte pro Embedding-Anfrage = Größe einer Bulk-Range (Default: 25) + workerWindowSize: 25 # Gelesene Dokumente pro Worker-Fenster (Default: 25, max. 1000) + workerConcurrency: 1 # Parallele Worker-Jobs je Provider/Gruppe (Default: 1, max. 8) + writeConcurrency: 4 # Parallele Dokument-Updates je Fenster (Default: 4, max. 32) +``` + +| Env | Config-Pfad | Wirkung | +|---|---|---| +| `SEARCH_VECTOR_EMBED_MAX_TEXTS` | `search.vectorEmbedMaxTexts` | Texte pro Embedding-Anfrage; kleinere Werte ergeben mehr Ranges pro Fenster | +| `SEARCH_WORKER_WINDOW_SIZE` | `search.workerWindowSize` | Gelesene Dokumente pro Fenster; Ranges pro Durchlauf ≈ Fenster / Range-Größe | +| `SEARCH_WORKER_CONCURRENCY` | `search.workerConcurrency` | Parallele Jobs je Gruppe — ein Job ist eine Sammlung, dieselbe Sammlung läuft nie doppelt | +| `SEARCH_WRITE_CONCURRENCY` | `search.writeConcurrency` | Parallele Mongo-Updates im Schreibschritt; der In-Memory-Index bleibt ein einzelner Schreiber | + +- **Warum das zusammenspielt.** Ein Fenster wird in Ranges zerlegt (eine Range = ein Embedding-Aufruf); die Ranges gehen per Work Sharing an die Mitglieder der Embedding-Gruppe. Fenster 100 + `vectorEmbedMaxTexts: 10` ergeben also ~10 Ranges und füllen auch vier parallele Endpoint-Slots, statt dass ein Mitglied die Arbeit allein macht. +- **Empfehlung für einen Massenimport:** `workerWindowSize: 100`, `vectorEmbedMaxTexts: 10`, `writeConcurrency: 8`; `workerConcurrency` nur erhöhen (2–4), wenn der Import mehrere Sammlungen betrifft. Zusätzlich `EMBEDDING_GROUP__MAX_CONCURRENT_PER_ENDPOINT` (Default 2) anheben, wenn die Gegenstelle mehr parallele Anfragen wirklich schneller beantwortet — lokale `native`-Mitglieder bleiben bewusst bei 1. +- **Grenzen.** Dieselbe (Namespace, Sammlung) läuft nie parallel, weil jeder Provider das ganze `_search`-Objekt schreibt; mehrere Sammlungen derselben Gruppe schon. Die Werte werden beim Start gelesen, nicht zur Laufzeit. +- **Prüfen:** `GET /_/:project/_/admin/search-worker/status` zeigt Queue-Tiefe, alle laufenden Jobs (`inFlightJobs`) und die Fortschrittszähler; `GET /api/v1/admin/embedding/status` zeigt die Treffer je Gruppen-Mitglied. + ## Admin-Tokens Server-Admin-Tokens stehen unter `api.adminTokens`. Jedes Token hat `token`, `label` und `permissions`: @@ -217,4 +241,4 @@ api: Weiter: [Betrieb und Beobachtung](/server/betrieb/) zeigt Profile und Metriken. [Sicherheit](/server/sicherheit/) erklärt Token-Arten und Ratelimit. -Verifiziert am d272041 2026-10-17 (tibi-server); Starter-Compose am e3f92eb 2026-10-14 (tibi-svelte-starter); Go-Version aus `go.mod`. Upload-Kaskade aus `internal/controller/collection.go` (resolveAllowedMimeTypes), Provider-/Gruppen-Env und `goldenPath` aus `internal/config/server.go`, Gruppen-Regeln aus `internal/config/embedding_group.go`, Prüfung/Quarantäne/Rückkehr/Timeouts aus `internal/embedding/{registry,probe,group}.go`, Pending-Verhalten aus `internal/utils/search.go`. +Verifiziert am d272041 2026-10-17 (tibi-server); Starter-Compose am e3f92eb 2026-10-14 (tibi-svelte-starter); Go-Version aus `go.mod`. Upload-Kaskade aus `internal/controller/collection.go` (resolveAllowedMimeTypes), Provider-/Gruppen-Env und `goldenPath` aus `internal/config/server.go`, Gruppen-Regeln aus `internal/config/embedding_group.go`, Prüfung/Quarantäne/Rückkehr/Timeouts aus `internal/embedding/{registry,probe,group}.go`, Pending-Verhalten aus `internal/utils/search.go`. Import-/Worker-Tuning am 3d052ae 2026-10-20 (tibi-server: `search.{vectorEmbedMaxTexts,workerWindowSize,workerConcurrency,writeConcurrency}` in `internal/config/server.go`, Verdrahtung in `cmd/server/main.go`, Sharding in `internal/utils/search.go`, Worker-Pool in `internal/models/search_worker.go`).