docs(kb): sesja 2026-06-24 — importer Gmail gotowy + konwencja jobs/
This commit is contained in:
parent
254a6808bc
commit
c32e050d56
|
|
@ -103,24 +103,35 @@ Hardening homelabu / stabilizacja control-plane — osobny wątek.
|
|||
|
||||
---
|
||||
|
||||
## Konwencja packages/
|
||||
## Konwencje katalogów Python
|
||||
|
||||
Reużywalne biblioteki Python (nie deploy-osobnych serwisów) żyją w `packages/<lib>/`.
|
||||
Instalacja w Dockerfile serwisu/joba: `pip install /repo/packages/<lib>/`.
|
||||
Biblioteki nie mają `docker-compose.yml` ani `service.yaml` — to nie są serwisy.
|
||||
| Katalog | Co tu trafia |
|
||||
|---------|-------------|
|
||||
| `packages/<lib>/` | Reużywalne biblioteki (nie deployowane samodzielnie). Instalacja: `pip install /repo/packages/<lib>/`. Nie mają `docker-compose.yml` ani `service.yaml`. |
|
||||
| `services/<svc>/` | Długo żyjące serwisy Docker z `docker-compose.yml` + `service.yaml`. |
|
||||
| `jobs/<job>/` | Jednorazowe i periodyczne joby CLI — bez Dockera, odpalane bezpośrednio na węźle (`pip install -e`). |
|
||||
|
||||
Pierwsza biblioteka: `packages/kb-mail/` — model koperty, helpery DB (asyncpg), helper archiwum.
|
||||
Pierwszy job: `jobs/gmail-bulk-import/` — jednorazowy bulk importer Gmail Takeout.
|
||||
|
||||
---
|
||||
|
||||
## Następny krok
|
||||
## Stan etapów
|
||||
|
||||
~~Etap 1 maili: zamroź kopertę + postaw Postgres+pgvector + szkielet repo.~~ **ZROBIONE** (2026-06-17).
|
||||
|
||||
- ✅ `services/kb-postgres` — pgvector/pgvector:pg16 na PIHA (:5433, always-on), `init/001_envelope.sql`
|
||||
- ✅ `services/kb-postgres` — pgvector/pgvector:pg16 na **PIHA** (:5433, always-on), `init/001_envelope.sql`
|
||||
- ✅ Zamrożona koperta — tabela `envelope` + `@dataclass Envelope` (tz-aware)
|
||||
- ✅ `packages/kb-mail` — `envelope` / `db` (asyncpg) / `archive` (append-only .eml)
|
||||
- ✅ 15 testów unit + 5 integration (mark `integration`, wymaga KB_TEST_DSN)
|
||||
- ✅ 15 testów unit + 5 integration (mark `integration`, wymaga `KB_TEST_DSN`)
|
||||
|
||||
**Etap 2: jednorazowy bulk importer Gmail** (mbox/Takeout → archiwum).
|
||||
~~Etap 2: jednorazowy bulk importer Gmail (mbox/Takeout → archiwum).~~ **KOD GOTOWY** (2026-06-24) — nie uruchomiony.
|
||||
|
||||
- ✅ `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
|
||||
|
||||
**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.
|
||||
|
|
|
|||
|
|
@ -79,8 +79,8 @@ Załączniki: **II tura** (MVP = czysty tekst + nagłówki).
|
|||
|
||||
## 8. Kolejność budowy (w obrębie projektu)
|
||||
|
||||
1. Zamroź kopertę + postaw Postgres+pgvector.
|
||||
2. **Bulk Gmail historyczny → archiwum** *(pierwsze, niezależne)*.
|
||||
1. ✅ Zamroź kopertę + postaw Postgres+pgvector. *(2026-06-17)*
|
||||
2. ✅ **Bulk Gmail historyczny → archiwum** — `jobs/gmail-bulk-import/` — **KOD GOTOWY** *(2026-06-24)*; nie uruchomiony (Takeout ~27 GB na SOLARIA, do transferu na PIHA).
|
||||
3. Fastmail JMAP live ingest → archiwum.
|
||||
4. Gmail IMAP live sync → archiwum.
|
||||
5. Filtr archiwum→indeks.
|
||||
|
|
|
|||
168
docs/sessions/2026-06-24-kb-gmail-importer.md
Normal file
168
docs/sessions/2026-06-24-kb-gmail-importer.md
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
# Sesja 2026-06-24 — KB etap 2: importer Gmail (kod gotowy)
|
||||
|
||||
## Cel
|
||||
|
||||
Zbudowanie jednorazowego bulk importera Gmail Takeout (`mbox → archiwum .eml + envelope DB`).
|
||||
Import nie uruchomiony w tej sesji — Takeout na SOLARIA, transfer+wlew = następny krok.
|
||||
|
||||
---
|
||||
|
||||
## Stan infrastruktury po sesji
|
||||
|
||||
### kb-postgres na PIHA (korekta z etapu 1)
|
||||
|
||||
Baza **przeniesiona na PIHA**, nie na SOLARIA jak zakładał pierwotny plan.
|
||||
- `Memory: hard=1g` zaaplikowany po reboocie (wymagał `cgroup_enable=memory` w cmdline + `docker-compose up --force-recreate`).
|
||||
- Status: `healthy`, port `5433`.
|
||||
|
||||
### Google Takeout (Gmail „All Mail")
|
||||
|
||||
- Pobrany: **~15 GB zip**, po rozpakowaniu **~27 GB mbox**, jeden plik.
|
||||
- Lokalizacja: `SOLARIA ~/Downloads` — jeszcze nie rozpakowany, nie zaimportowany.
|
||||
|
||||
---
|
||||
|
||||
## Etap 2 — ZBUDOWANY (kod gotowy)
|
||||
|
||||
### Nowa konwencja: `jobs/<name>/`
|
||||
|
||||
Jednorazowe i periodyczne joby (nie serwisy) żyją w `jobs/<name>/`.
|
||||
|
||||
| Katalog | Co tu trafia |
|
||||
|---------|-------------|
|
||||
| `packages/<lib>/` | reużywalne biblioteki Python (nie deployowane samodzielnie) |
|
||||
| `services/<svc>/` | długo żyjące serwisy Docker |
|
||||
| `jobs/<job>/` | one-shot i periodyczne joby CLI |
|
||||
|
||||
Instalacja lokalnie: `pip install -e packages/kb-mail/ && pip install -e jobs/gmail-bulk-import/`
|
||||
Bez Dockera — odpalany bezpośrednio na PIHA pod `nice`/`ionice`.
|
||||
|
||||
### jobs/gmail-bulk-import
|
||||
|
||||
Wejście: plik `.mbox` z Google Takeout.
|
||||
Wyjście: `.eml` w archiwum (append-only, PIHA NVMe) + wiersze `envelope` w kb-postgres.
|
||||
|
||||
Kluczowe decyzje implementacyjne:
|
||||
|
||||
| Kwestia | Decyzja |
|
||||
|---------|---------|
|
||||
| ID wiadomości | `Message-ID` header (stripped `<>`); fallback: `sha256-<32hex>` treści |
|
||||
| Timestamp | `Date` header → UTC; fallback epoch 1970-01-01 + licznik `epoch_fallback` |
|
||||
| Źródło | `source=gmail` |
|
||||
| Idempotencja | `FileExistsError` z archiwum → skip; `ON CONFLICT DO NOTHING` w DB |
|
||||
| Wznawialność | mbox iterowany od początku; już zarchiwizowane = skip; already in DB = noop |
|
||||
| Batch inserty | `executemany` co 500 wpisów (+ flush na końcu); `_eml_ref` rekonstruuje `raw_ref` dla skipped |
|
||||
| Docker | **brak** — CLI bez konteneryzacji |
|
||||
|
||||
### Załączniki → entities[]
|
||||
|
||||
W tym etapie bajty załączników **zostają w .eml** — nie są ekstrahowane ani OCR-owane.
|
||||
|
||||
Importer zapisuje **manifest** do `Envelope.entities[]`:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "attachment",
|
||||
"filename": "faktura.pdf",
|
||||
"content_type": "application/pdf",
|
||||
"size": 42387,
|
||||
"sha256": "a3f4..."
|
||||
}
|
||||
```
|
||||
|
||||
Powiązanie mail↔załącznik w bazie od dnia zero.
|
||||
Ekstrakcja/OCR = **faza 2** (możliwe przekierowanie faktur/umów do Paperless, filar dokumentów).
|
||||
|
||||
### CLI
|
||||
|
||||
```bash
|
||||
# Dry run — tylko liczenie i parsowanie, bez zapisów:
|
||||
gmail-bulk-import --mbox ~/takeout/allmail.mbox --archive /data/kb/archive --dry-run
|
||||
|
||||
# Próbka 200 wiadomości (przed pełnym wlewem):
|
||||
gmail-bulk-import --mbox ~/takeout/allmail.mbox --archive /data/kb/archive \
|
||||
--dsn postgresql://kb:<pw>@localhost:5433/kb --limit 200
|
||||
|
||||
# Pełny wlew na PIHA pod nice/ionice:
|
||||
ionice -c 3 nice -n 19 gmail-bulk-import \
|
||||
--mbox ~/takeout/allmail.mbox \
|
||||
--archive /data/kb/archive \
|
||||
--dsn postgresql://kb:<pw>@localhost:5433/kb
|
||||
```
|
||||
|
||||
### Statystyki zwracane przez importer
|
||||
|
||||
```
|
||||
processed, imported, skipped, errors,
|
||||
epoch_fallback, ← maile bez parsowalnej daty
|
||||
msgs_with_attachments, ← sizing fazy 2
|
||||
total_attachments,
|
||||
total_attachment_bytes
|
||||
```
|
||||
|
||||
### Testy
|
||||
|
||||
- 24 testy jednostkowe (bez DB, bez sieci) — wszystkie zielone.
|
||||
- Pokrycie: `_message_id`, `_parse_date`, `_parse_attachments`, `run_import`
|
||||
(dry-run, archiwum, idempotencja, --limit, epoch_fallback, statystyki załączników, batch).
|
||||
|
||||
---
|
||||
|
||||
## GOTCHA tej sesji
|
||||
|
||||
Pierwsza iteracja importera (commit 57a27af) celowała w `solaria:5433` zamiast PIHA,
|
||||
pominęła `entities[]` załączników, `--limit`, batch inserty i `epoch_fallback`.
|
||||
Złapane w review, poprawione w osobnym commicie.
|
||||
|
||||
**Lekcja**: prompt musi explicite podać host bazy = PIHA (nie SOLARIA).
|
||||
|
||||
---
|
||||
|
||||
## Następny krok
|
||||
|
||||
1. `rsync` Takeout SOLARIA → PIHA po Tailscale (27 GB mbox na NVMe PIHA).
|
||||
2. `gmail-bulk-import ... --dry-run` — weryfikacja liczby wiadomości.
|
||||
3. `gmail-bulk-import ... --limit 200` — próbka, weryfikacja jakości.
|
||||
4. Pełny wlew pod `ionice -c 3 nice -n 19`.
|
||||
5. Weryfikacja: `ls archive/gmail/ | wc` ≈ `SELECT count(*) FROM envelope WHERE source='gmail'` ≈ liczba wiadomości w mboxie.
|
||||
|
||||
---
|
||||
|
||||
## Backlog (osobne zadania)
|
||||
|
||||
- `packages/kb-mail/tests/test_db.py`: `KB_TEST_DSN` defaultuje do `localhost:5433/kb` — poprawne dla PIHA, ale warto sprawdzić wszystkie occurrences `solaria:5433` w testach.
|
||||
- Etap 3: Fastmail JMAP live ingest → `jobs/fastmail-poller/`.
|
||||
- Etap 4: Gmail IMAP live sync → `jobs/gmail-imap-poller/`.
|
||||
- Zapis deklaratywny `cgroup_enable=memory + swapaccount=1` dla PIHA (firmware/cmdline — poza GitOps, udokumentować w `hosts/piha/host.yaml` lub README).
|
||||
|
||||
---
|
||||
|
||||
## Higiena git
|
||||
|
||||
- Praca w worktree `task/kb-gmail-import`; master deploy-only, czysty przez cały czas.
|
||||
- 4 commity na branchu po zamknięciu sesji.
|
||||
|
||||
---
|
||||
|
||||
## Commits
|
||||
|
||||
```
|
||||
57a27af feat(kb-mail): etap 2 — jednorazowy bulk importer Gmail (mbox → archiwum)
|
||||
f0e4d90 refactor(kb-mail): importer Gmail — entities załączników, --limit, batch, bez Dockera, DSN→PIHA
|
||||
c5dd8f3 fix(piha): capabilities — realny RAM/NVMe + gitignore build dirs
|
||||
<docs> docs(kb): sesja 2026-06-24 — importer Gmail gotowy + konwencja jobs/
|
||||
```
|
||||
|
||||
## Files changed (etap 2)
|
||||
|
||||
```
|
||||
jobs/gmail-bulk-import/src/gmail_bulk_import/__init__.py
|
||||
jobs/gmail-bulk-import/src/gmail_bulk_import/importer.py
|
||||
jobs/gmail-bulk-import/pyproject.toml
|
||||
jobs/gmail-bulk-import/tests/test_importer.py
|
||||
hosts/piha/capabilities.yaml
|
||||
.gitignore
|
||||
docs/kb/kb-00-overview.md (etap 2 gotowy, konwencja jobs/)
|
||||
docs/kb/kb-01-email-design.md (§8 krok 2 = kod gotowy)
|
||||
docs/sessions/2026-06-24-kb-gmail-importer.md
|
||||
```
|
||||
Loading…
Reference in a new issue