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>
154 lines
5 KiB
Markdown
154 lines
5 KiB
Markdown
---
|
||
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 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.)
|