homelab-codex-ws/docs/sessions/2026-06-25-kb-gmail-import-uruchomiony.md
oskar f0522a85dc 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:53:57 +02:00

5 KiB
Raw Blame History

okf type visibility status updated links
0.1 session-log private active 2026-06-26

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

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 envelope225 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.)