This commit is contained in:
2026-06-13 21:45:28 +02:00
parent 6bcb721eb4
commit f94573ea6e
473 changed files with 7805 additions and 31 deletions
+24 -1
View File
@@ -28,7 +28,30 @@ MailStore Server v26.2.1.24065 na `192.168.1.53` (hostname MAILSTORE, Win). Arch
**Ingest do Mongo — `mailstore_ingest_v1.0.py <schránka> --since ROK [--dry-run] [--folder X] [--limit N]`**: backfill staré historie z MailStore do Mongo kolekce `emaily`. Dedup podle internet Message-ID (= `_id` v Mongu, shoduje se 1:1 s IMAP hlavičkou). Filtr data client-side z DATE headeru (NE IMAP SEARCH). Schéma dokumentu = jako Graph import. `--dry-run` spočítá kolik chybí bez zápisu. PILOT OVĚŘEN end-to-end 2026-06-11: MailStore IMAP → ingest → Mongo → enrich_fulltext → PG → MCP emaily search našel zprávu z 2020. Header scan ~490 zpráv/s (1M ≈ 30 min). vladimir.buzalka@buzalka.cz: Sent Items má 20k zpráv 2020+ k dobrání (i odeslané chybí z Graphu!). Plán: roztáhnout celou schránku, pak `--since` hlouběji do minulosti.
**Dva gotchas (vyřešené):**
**STAV 2026-06-13: backfill 2019+2020+ KOMPLETNÍ.** Mongo kolekce `vladimir.buzalka@buzalka.cz`: 332 204 zpráv (z toho 256 808 z mailstore), PG fulltext 100 % (`pg_indexed=mongo_total`). 2019 dobrán samostatným během `--since 2019 --until 2019` s **vlastním checkpointem** `ingest_done_2019.txt` (stávající checkpoint 2020+ by 2019 minul — přeskočí složky před scanem!). Pozn.: `mailstore_uid` v dokumentech je ve skutečnosti **sekvenční číslo** (ne IMAP UID), fetch přes `M.fetch(seq,'(RFC822)')` + kontrola Message-ID.
**Přílohy → SeaweedFS (PoC, [[project-seaweedfs]]):** `mailstore_attachments_poc.py` — re-fetch EML přes IMAP, přílohy do Fileru `192.168.1.50:8888` (PUT raw), dedup SHA-256, write-back pole `seaweed_attachments[]` (filename, sha256, seaweed_url) + marker `seaweed_synced_at`. Dávkový samostránkující režim (NE jeden dlouhý kurzor — `CursorNotFound` po hodině!). 88 930 mailů s přílohami 100 % hotovo, 0 failed; SeaweedFS 72k objektů / 27 GB. **Drift sekvencí** u živých složek (Sent Items, Odeslaná pošta — dostávaly poštu během ingestu) → `--remap-failed` režim: naskenuje mapu Message-ID→aktuální seq a dofetchne správně. Běží z toweru přes `_run_poc.py` (`_run_ingest_2019.py` pro 2019 ingest).
**Běh na serveru (python-runner kontejner na Unraidu .76):** skript v `/mnt/user/Scripts/MailStore/` (deploy přes paramiko SFTP `_deploy.py`, SSH root@192.168.1.76 heslo `7309208104`). Kontejner má pymongo, dosáhne na MailStore .53 i Mongo .76. **DŮLEŽITÉ: Unraid agresivně zabíjí odpojené procesy**`docker exec -d`, `nohup &`, `setsid` (host i kontejner) VŠECHNY selžou (i prostý `sleep 60` zmizí; SSH session cleanup zabije celý user slice; screen/tmux/at nejsou). Jediné co funguje: **blokující `docker exec` držený aktivním spojením** (paramiko z PC v background tasku, `_run_ingest.py`). Ingest je **idempotentní** (dedup Message-ID + `$setOnInsert`) → přerušení (notebook usne) nevadí, příští běh dobere zbytek.
**Velký backfill 2026-06-12 (vladimir.buzalka@buzalka.cz --since 2020) — DOKONČEN: 168 364 zpráv z mailstore v Mongo** (kolekce celkem 243 607). Cestou vyřešeno + zpevněno ve skriptu (v aktuální verzi ~20kB):
- **ROOT CAUSE celého dne (zjištěno až nakonec): plný disk C:.** MailStore měl v configu `"IMAP Server Connection Debug Log Enabled": true` → náš těžký IMAP provoz (FETCH celých těl) vygeneroval za den **65 GB Connection debug logů** do `C:\ProgramData\MailStore\Debug Log\Connection\` (jednotlivé soubory 10-35 GB!). C: (jen 99 GB) se zaplnil na 0 → Firebird story na Z: házely `Unable to open the archive store ... Code 335544373 SetFilePointer failed`, IMAP wedgoval pod zátěží (nešlo psát temp/zámky), a po restartu story nešly mountnout (API GetChildFolders=0 pro VŠECHNY schránky, GetStores ukázal chyby). **Fix: vypnout Connection debug log** (config `MailStoreServer.json` v `C:\Program Files (x86)\MailStore\MailStore Server\`, hodnotu na `false`, stop/edit/start; záloha `.bak_20260613`) + **smazat logy** (`C:\ProgramData\MailStore\Debug Log\Connection\*` — pozor: harness blokuje `Remove-Item` na ProgramData, použij `Get-ChildItem | %{$_.Delete()}`). Po smazání 65 GP uvolněno, restart → story OK, 1795 složek, archiv online. **Diagnostika: `_store_status.py` (GetStores přes API, POST i bez params = `data=b""`, dekóduj `utf-8-sig` kvůli BOM).**
- **MailStore IMAP se pod zátěží ZASEKNE NATVRDO** (`abort: command: FETCH/CAPABILITY/EXAMINE => socket error: EOF`) — primárně to byl důsledek plného C: výše. Port 143 přijme TCP, ale server spojení hned utne — i z PC. **Probudí ho JEN restart služby `MailStoreServer`** (retry nepomůže). Restart přes WinRM: `Restart-Service -Name MailStoreServer -Force` (admin `administrator`/`Vlado7309208104++`, TrustedHosts OK). Po wedgi 0 established spojení, služba "Running" — zaseklé je IMAP vlákno gateway. **Při dalším velkém ingestu HLÍDAT volné místo na C:!** (s vypnutým debug logem by problém neměl nastat).
- Po wedgi **login projde, ale FETCH hned EOFne** → skript dělal kaskádu falešných přeskoků a vracel falešné rc=0. Fix: čítač `consec_aborts`, po **4 abortech v řadě `return 2`** → orchestrátor pozná wedge.
- **`coll.distinct("_id")` překročí 16MB cap** u velké kolekce → nahrazeno kurzorem `find({},{_id:1}).batch_size(5000)`.
- `imap_connect()` má retry (6×5s) na abort/error/OSError.
- **`--checkpoint FILE`** (hotové složky, jedna cesta/řádek) → po wedgi další běh přeskočí hotové BEZ FETCH (rychlé navázání). Složka se zapíše až po úplném dokončení; abort během fetche ji NEoznačí.
- **Orchestrátor `_orchestrate.ps1`**: smyčka run ingest → rc≠0 → `Restart-Service` MailStore přes WinRM → čekej až IMAP odpoví (`_imap_test.py`) → zkus znovu. Konec na rc=0. Konverguje díky checkpointu.
- **HEADER_BATCH snížen 2000→500** (šetrnější).
- **Dvě obří složky (Odstraněná 170k, Doručená 47k) jdou re-scanovat jen na čerstvém MailStore — jinak deterministicky wedgnou na 1. FETCH.** Přijaty jako hotové ~99 % (Odstraněná 14 637/14 728, Doručená 2 666/2 719; data zapsaly dřívější běhy) a ručně seednuty do checkpointu (`_seed_checkpoint.py`). Zbývá ~150 stragglerů + 2 maličké složky (`_OPTUM_PATROc`, `27646` — v Mongu 0) na pozdější šetrný doběh.
- **PO forced restartu Management API (8463) chvíli vrací 0 složek** (GetChildFolders/collect_folders = 0) — MailStore mountuje index obří schránky (273 GB) minuty. Opakované forced restarty počet složek degradovaly 1795→1507→0. **Nehammrovat restarty**; nechat MailStore dosednout. collect_folders=0 → běh nemá co dělat → falešné rc=0 (pozor v orchestraci).
Pro denní udržování plánováno: Unraid User Scripts plugin nebo python-runner cron (nezávislé na SSH) + sync_state (UID watermark). Pomocné skripty v `mailstore/`: `_run_ingest.py`, `_orchestrate.ps1`, `_status_check.py`, `_mongo_count.py`, `_tail_log.py`, `_checkpoint_diff.py`, `_imap_test.py`, `_seed_checkpoint.py`, `_deploy.py`, `_folder_coverage.py`.
vladimir.buzalka@buzalka.cz má **1795 složek** (hluboká struktura #Innopharma/!Zpracovat/@Zpracovat po studiích). Velké: Odstraněná pošta 170k, Sent Items 63k, Doručená pošta 47k. Header scan ~490 zpráv/s (velká složka ~2-4 min).
**Tři gotchas (vyřešené):**
0. IMAP názvy složek s diakritikou (Doručená pošta) musí být v **modified UTF-7** (RFC 3501) — MailStore neumí UTF8=ACCEPT. `encode_mutf7()` ve všech 3 IMAP skriptech. A nestandardní charsety hlaviček/těl (`unknown-8bit`) shazují `bytes.decode``_safe_decode()` s fallbackem utf-8/latin-1.
1. Kolekce `emaily` má unique+sparse index na `graph_id`. MailStore dokument musí pole `graph_id` ÚPLNĚ VYNECHAT (ne `None`) — explicitní null koliduje (sparse ignoruje jen chybějící pole). Jinak E11000 duplicate key.
2. Mongo `{'graph_id': None}` matchuje i dokumenty BEZ pole — `delete_many` tím smete i validní dokumenty. Pozor při úklidu.
3. enrich_fulltext spouštět přes `U:/janssen/.venv/Scripts/python.exe` (system Python C:\Python312 nemá psycopg).
+3 -1
View File
@@ -12,10 +12,12 @@ Skripty jsou v `/mnt/user/Scripts/` (volume → `/scripts/`).
**Pipeline** spouštěna 2× denně cronem (`0 6,18 * * *`) přes `run_pipeline.sh`:
- `1b` — Graph delta sync (nové/změněné emaily → MongoDB)
- `3` — Download attachments
- `3` — Download attachments (`3_download_attachments_v1.5.py`)
- `4` — Unwrap S/MIME
- `5` — Enrich fulltext → PostgreSQL
**Přílohy → SeaweedFS (2026-06-13):** krok 3 (v1.5) krom uložení na disk `/mnt/Emails/<mbox>/Attachments/` zároveň pushne každou novou přílohu do SeaweedFS přes sdílený `/scripts/seaweed_store.py`; do `emaily.attachments_index` (dedup SHA-256=_id) zapíše `seaweed_path/seaweed_url/seaweed_synced_at`. Výpadek SeaweedFS pipeline neshodí (jen warning, doplní backfill). Jednorázový backfill již stažených: `seaweed_attachments_backfill_graph.py` (batch+resume). Globální dedup s mailstore větví. Viz [[project-seaweedfs]].
**Wrapper:** `0_run_pipeline_v1.0.py`
- Na začátku auto-install: `pip install -q -r /scripts/requirements.txt` — odolné vůči recreate kontejneru
- Na konci email report: HTML tabulka výsledků z `reports@buzalka.cz``vladimir.buzalka@buzalka.cz`; při chybě přiloží log selhavšího kroku