homelab-codex-ws/docs/sessions/2026-06-25-kb-gmail-import-uruchomiony.md
oskar 510fe0b600 feat(kb): frontmatter OKF dla 39 session logow
Session logi zostaja w docs/sessions/ (decyzja z etapu 1). Dodany wylacznie
blok frontmattera: type: session-log, visibility: private, status: active,
updated = data ostatniego commita pliku.

Tresc nietknieta — kazdy plik to +9/-0 linii.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 16:58:04 +02:00

154 lines
5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
okf: "0.1"
type: session-log
visibility: private
status: active
updated: 2026-06-26
links: []
---
# 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 20112012 (~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.)