docs(kb): sesja 2026-06-25 — bulk import Gmail uruchomiony (225k kopert na PIHA)
This commit is contained in:
parent
1529911012
commit
7a95ab2fff
|
|
@ -131,13 +131,16 @@ Pierwszy job: `jobs/gmail-bulk-import/` — jednorazowy bulk importer Gmail Take
|
|||
- ✅ deploy na PIHA: kontener healthy, schemat `envelope` + extension `vector` zweryfikowane
|
||||
- ⏳ zostaje: transfer archiwum/.eml na PIHA NVMe (docelowo), poprawka `KB_TEST_DSN` (solaria→piha) w testach
|
||||
|
||||
~~Etap 2b: jednorazowy bulk importer Gmail (mbox/Takeout → archiwum).~~ **KOD GOTOWY** (2026-06-24) — nie uruchomiony.
|
||||
~~Etap 2b: jednorazowy bulk importer Gmail (mbox/Takeout → archiwum).~~ **URUCHOMIONY** (2026-06-25).
|
||||
|
||||
- ✅ `jobs/gmail-bulk-import/` — CLI importer bez Dockera (pip install -e na PIHA)
|
||||
- ✅ entities[]: manifest załączników (filename, content_type, size, sha256) od dnia zero
|
||||
- ✅ batch inserty, idempotentny, --limit, epoch_fallback, statystyki załączników
|
||||
- ✅ 24 testy jednostkowe, wszystkie zielone
|
||||
- ⏳ Google Takeout ~27 GB mbox — do transferu SOLARIA→PIHA + uruchomienia
|
||||
- ✅ Pełny import uruchomiony na PIHA (~29 min): **225 030 unikalnych kopert**, **27 GB archiwum .eml**, manifest **70 193 załączników**
|
||||
|
||||
**Następny krok**: transfer Takeout SOLARIA→PIHA (rsync Tailscale) → dry-run → próbka --limit 200 → pełny wlew `ionice -c 3 nice -n 19`.
|
||||
Szczegóły kolejności: `kb-01-email-design.md` §8.
|
||||
**Backlog / następne kroki**:
|
||||
- Faza 2 załączników: ekstrakcja/OCR (PDF/skany → Paperless lub dedykowany job)
|
||||
- Odzysk 2559 dat epoch-fallback z nagłówków `Received:`/`X-GM-RECEIVED`
|
||||
- Etap 3: Fastmail JMAP live ingest → `jobs/fastmail-poller/`
|
||||
- Etap 4: Gmail IMAP live sync → `jobs/gmail-imap-poller/`
|
||||
|
|
|
|||
144
docs/sessions/2026-06-25-kb-gmail-import-uruchomiony.md
Normal file
144
docs/sessions/2026-06-25-kb-gmail-import-uruchomiony.md
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
# Sesja 2026-06-25 — KB etap 2: bulk import Gmail uruchomiony
|
||||
|
||||
## Cel
|
||||
|
||||
Domknięcie etapu 2 bazy wiedzy. Poprzednia sesja (2026-06-24) zostawiła kod gotowy,
|
||||
ale dane na SOLARIA. Ta sesja = transfer + uruchomienie + weryfikacja na produkcji (PIHA).
|
||||
|
||||
---
|
||||
|
||||
## Co zrobione
|
||||
|
||||
### Relokacja kb-postgres SOLARIA→PIHA — domknięta i zweryfikowana
|
||||
|
||||
Baza stoi na PIHA (always-on); zapytania KB działają 24/7 niezależnie od SOLARIA.
|
||||
|
||||
### Przygotowanie PIHA pod import
|
||||
|
||||
- **cgroup memory enable**: `cgroup_enable=memory cgroup_memory=1` dopisane do
|
||||
`/boot/firmware/cmdline.txt` + reboot; backup w `cmdline.txt.bak`.
|
||||
- **Swap 4 GB**: wpisany do `/etc/fstab` (był już skonfigurowany wcześniej, weryfikacja).
|
||||
- **SSH key perms**: `chmod 600 ~/.ssh/id_rsa` — prawa `0640` blokowały `git fetch`
|
||||
(OpenSSH odrzuca klucze `group-readable`).
|
||||
|
||||
### Transfer Takeout SOLARIA→PIHA
|
||||
|
||||
`rsync` po LAN (nie Tailscale, oba dostępne): 15 GB zip → po rozpakowaniu
|
||||
**27 GB `allmail.mbox`** wylądowało w `~/kb/dropbox/`.
|
||||
`venv` pod PEP668 w `~/kb/venv` (Pi OS wymusza brak systemowych pip-instalacji).
|
||||
|
||||
### Walidacja przed pełnym wlewem
|
||||
|
||||
1. `--dry-run --limit 200` — parsowanie bez zapisów, weryfikacja nagłówków.
|
||||
2. `--limit 1000` z realnym zapisem — próbka; potwierdzono że RAM stoi płasko:
|
||||
zużycie to koszt zbudowania indeksu `mailbox.mbox` przy otwarciu, nie akumulacja
|
||||
per-mail w pętli.
|
||||
|
||||
### Pełny import
|
||||
|
||||
```bash
|
||||
nohup nice -n 15 ionice -c2 -n7 \
|
||||
gmail-bulk-import \
|
||||
--mbox ~/kb/dropbox/allmail.mbox \
|
||||
--archive ~/kb/mail/archive \
|
||||
--dsn postgresql://kb:<pw>@localhost:5433/kb \
|
||||
>> ~/kb/import.log 2>&1 &
|
||||
```
|
||||
|
||||
Czas: **~29 minut**. Brak OOM, swap stabilny przez cały przebieg.
|
||||
|
||||
---
|
||||
|
||||
## Wynik importu
|
||||
|
||||
| Metryka | Wartość |
|
||||
|---------|---------|
|
||||
| processed | 226 318 |
|
||||
| imported (pliki .eml) | 225 057 |
|
||||
| skipped (duplikaty Message-ID) | 1 260 |
|
||||
| errors (zepsute maile) | 1 |
|
||||
| epoch_fallback (brak daty) | 2 559 |
|
||||
| msgs_with_attachments | 32 495 |
|
||||
| total_attachments | 70 193 |
|
||||
| total_attachment_bytes | 15,4 GB |
|
||||
|
||||
**Baza (envelope):** `SELECT count(DISTINCT id) FROM envelope` → **225 030** unikalnych kopert.
|
||||
**Archiwum:** 225 057 plików `.eml`, **27 GB na NVMe PIHA** (`~/kb/mail/archive`).
|
||||
**Zakres dat:** 2002→2026-06-19; pik 2011–2012 (~23 k/rok); bez dziur.
|
||||
|
||||
---
|
||||
|
||||
## Lekcje
|
||||
|
||||
### `imported` ≠ wiersze w DB — NORMA, nie bug
|
||||
|
||||
Importer liczy `imported` jako zapisane pliki `.eml`.
|
||||
`count(DISTINCT id)` w `envelope` jest mniejsze o duplikaty Message-ID:
|
||||
`ON CONFLICT (id) DO NOTHING` je poprawnie odrzuca.
|
||||
|
||||
Różnica: 225 057 archiwum − 225 030 DB = **27 duplikatów klucza** — zero utraty danych.
|
||||
|
||||
Zmarnowano ~30 minut na re-run całego mboxa szukając tych „27", zanim przeczytano kod
|
||||
importera. **Reguła: verify-before-fix** — najpierw sprawdź co kod faktycznie robi,
|
||||
zanim zaczniesz pisać fixa.
|
||||
|
||||
### `mailbox.mbox` buduje indeks przy każdym otwarciu
|
||||
|
||||
`python mailbox.mbox` skanuje całe 27 GB przed pierwszą wiadomością.
|
||||
Na Pi5 to kilka minut startu — **nie zawis, nie błąd**. Re-run płaci ten koszt w całości
|
||||
(wszystkie 226 k wiadomości przelatują ponownie przez idempotencję).
|
||||
Jeśli trzeba dosłać kilka kopert, taniej będzie osobny skrypt niż re-run mboxa.
|
||||
|
||||
### RAM/swap stabilne
|
||||
|
||||
Swap ~47% podczas importu = stałe tło Home Assistant, nie skok od importera.
|
||||
Hard `mem_limit: 1g` na kb-postgres chronił HA przez cały przebieg.
|
||||
|
||||
---
|
||||
|
||||
## Sprzątanie po imporcie
|
||||
|
||||
- `allmail.mbox` + oryginalny zip skasowane z `~/kb/dropbox/` na PIHA → odzysk **~42 GB NVMe**.
|
||||
- Oryginalny zip Takeout (15 GB) przeniesiony na SOLARIA `~/kb/_cold/` jako cold backup
|
||||
(do końca fazy 2, potem do skasowania).
|
||||
|
||||
---
|
||||
|
||||
## Stan etapu 2
|
||||
|
||||
**ZAMKNIĘTY.**
|
||||
|
||||
Pełna historia Gmaila 2002→2026 w bazie wiedzy:
|
||||
- **225 030** unikalnych kopert w `kb-postgres` (PIHA)
|
||||
- **27 GB** archiwum `.eml` (PIHA NVMe)
|
||||
- manifest **70 193** załączników w `entities[]` (ekstrakcja/OCR = faza 2)
|
||||
|
||||
---
|
||||
|
||||
## Backlog / następne kroki
|
||||
|
||||
- **Faza 2 załączników**: ekstrakcja i OCR (PDF/skany → Paperless lub dedykowany job).
|
||||
- **Odzysk 2559 dat epoch-fallback**: nagłówki `Received:` / `X-GM-RECEIVED` mogą dać
|
||||
prawdziwe timestamps dla maili bez `Date:`.
|
||||
- **Etap 3**: Fastmail JMAP live ingest → `jobs/fastmail-poller/`.
|
||||
- **Etap 4**: Gmail IMAP live sync → `jobs/gmail-imap-poller/`.
|
||||
|
||||
---
|
||||
|
||||
## Higiena git
|
||||
|
||||
Praca w worktree `task/kb-session-0625`; główny checkout `~/homelab-codex-ws` czysty.
|
||||
|
||||
---
|
||||
|
||||
## Commits tej sesji
|
||||
|
||||
```
|
||||
c0ffb6a docs(kb): sesja 2026-06-22 — spine relokowany na PIHA + przygotowanie hosta
|
||||
c32e050 docs(kb): sesja 2026-06-24 — importer Gmail gotowy + konwencja jobs/
|
||||
254a680 fix(piha): capabilities — realny RAM/NVMe + gitignore build dirs
|
||||
f234280 refactor(kb-mail): importer Gmail — entities załączników, --limit, batch, bez Dockera, DSN→PIHA
|
||||
6dc1d32 feat(kb-mail): etap 2 — jednorazowy bulk importer Gmail (mbox → archiwum)
|
||||
```
|
||||
|
||||
(Commitów implementacyjnych w tej sesji brak — dokumentacja domknięcia etapu 2.)
|
||||
Loading…
Reference in a new issue