This commit is contained in:
2026-06-10 11:59:19 +02:00
parent a41f97b86b
commit 7b2f69ad85
275 changed files with 16726 additions and 0 deletions
@@ -0,0 +1,83 @@
# jnj_tower_ingest v1.0.0
**Soubor:** `jnj_tower_ingest_v1.0.py`
**Datum:** 2026-06-10
**Autor:** vladimir.buzalka
**Běží:** Docker kontejner `python-runner` na Unraid Tower (192.168.1.76), u MongoDB.
## Co to je
Sjednocený **Tower-side ingest** JNJ e-mailů — spojuje dvě dříve oddělené poloviny
do jednoho běhu:
| Fáze | Dříve samostatně | Co dělá |
|---|---|---|
| **1. PARSE** | `parse_emails_tower_v1.3.py` | `.msg` z `/mnt/JNJEMAILS` → bohatý dokument v Mongo `emaily."vbuzalka@its.jnj.com"` (tělo, přílohy, hlavičky, MAPI props). `_id` = Internet Message-ID. |
| **2. SYNC** | `sync_jnj_state_v1.0.py` | nejnovější `/mnt/JNJEMAILS/db/jnjemails_*.db` (SQLite, **jen čtení** `mode=ro`) → zrcadlo do `jnj_messages` + doplnění `jnj_folder`/stavu do `emaily`. |
**Pořadí: parse BĚŽÍ PŘED sync.** Tím čerstvě naparsované maily dostanou cestu hned ve
stejném běhu (dřív: když sync předběhl parse, nový mail neměl co matchnout — sync
nezakládá stuby). Spojovací klíč všude = **Internet Message-ID = Mongo `_id`**.
## Inkrementálnost (vhodné pro cron každých 5 min)
- **PARSE** — parsuje jen `.msg` s `mtime` novějším než watermark
(`jnj_sync_state` / `_id="parse_state"``last_parse_mtime`).
- **První běh = seed:** watermark chybí → kandidáti = soubory, jejichž `filename`
ještě není v Mongu (jednorázový `distinct("filename")`); poté se watermark
nastaví na nejnovější soubor.
- **Další běhy = incremental:** jen `mtime > watermark`. Žádný sken Monga.
- `--full` reparsuje vše (upsert, idempotentní).
- **Indexy** se vytvářejí jen při `full`/`seed`/`--reindex` (v incremental už existují).
- **SYNC** — watermark `updated_at` (`jnj_sync_state` / `_id="watermark"`) + zkratka
`last_db` (stejná SQLite jako minule → okamžitý no-op, nesahá na Mongo data).
Dvě nezávislé události (nová `.msg` / nová `.db`) → skript udělá jen tu fázi, co má
práci; jinak levný no-op.
## Argumenty
| Argument | Význam |
|---|---|
| `--dry-run` | nic nezapíše, jen plán obou fází |
| `--full` | parse: reparsuj vše; sync: ignoruj watermark |
| `--limit N` | max N souborů (parse) / řádků (sync) — test |
| `--reindex` | vynutí indexy po parse fázi |
| `--force` | sync: ignoruj zkratku `last_db` |
| `--parse-only` | jen fáze PARSE |
| `--sync-only` | jen fáze SYNC |
## Spouštění
```bash
# Test:
docker exec -it python-runner python3 /scripts/jnj_tower_ingest_v1.0.py --dry-run
# Ostrý inkrementální běh (volá ho cron):
docker exec python-runner python3 /scripts/jnj_tower_ingest_v1.0.py
# Plný reparse + reindex:
docker exec -it python-runner python3 /scripts/jnj_tower_ingest_v1.0.py --full --reindex
```
## Plánování (HOTOVO)
Unraid User Scripts úloha `jnj_state_sync` (cron `*/5 * * * *`) — wrapper s `flock`
volá `docker exec python-runner python3 /scripts/jnj_tower_ingest_v1.0.py`.
Loguje jen reálnou práci/chyby do `/mnt/user/Scripts/logs/jnj_tower_ingest.log`
(grep `Zapisuji|PARSE hotovo|SYNC hotovo|CHYBA|Traceback`). Cron řádek/rozvrh se při
přepnutí ze `sync_jnj_state` neměnil — jen obsah wrapperu.
## Revert
Staré skripty `parse_emails_tower_v1.3.py` a `sync_jnj_state_v1.0.py` zůstávají v
`/scripts/` jako pojistka. Návrat = přepsat wrapper zpět na `sync_jnj_state_v1.0.py`.
## Závislosti
`extract-msg==0.55.0`, `olefile`, `pymongo`, `python-dateutil`, `sqlite3` (stdlib).
Python 3.10+.
## Historie verzí
- **1.0.0** 2026-06-10 — sjednocení `parse_emails_tower_v1.3` + `sync_jnj_state_v1.0`;
parse zinkrementálněn přes mtime watermark; indexy jen při full/seed/`--reindex`;
pořadí parse→sync.