Scheduler für periodischen IMAP-Postfach-Abruf mit UID-basiertem Delta-Sync: neue Nachrichten erkennen, Zustandsänderungen abgleichen. - imap (ING-01) minimal erweitert: Message.UID, MailboxStore.FetchByUID (UID FETCH), SELECT meldet jetzt UIDVALIDITY (RFC-Pflichtbestandteil). Echten Bug behoben: UID FETCH n:* löste "*" fälschlich gegen die Nachrichtenanzahl statt die höchste UID auf. - imapimport/state.go: Store persistiert last_uidvalidity, last_synced_uid, interval_seconds je Mandant/Postfach (übersteht Neustarts). - imapimport/scheduler.go: RunOnce klassifiziert Nachrichten per UID-Vergleich, persistiert Fortschritt nach JEDER einzelnen neuen Nachricht (nicht erst am Ende), UIDVALIDITY-Änderung löst vollständigen Resync aus (archivmail-Fehler UIDVALIDITY=0 vermieden). - imapimport/client_real.go: echtes IMAP4rev1 über TCP (LOGIN/SELECT/UID FETCH/LOGOUT). Prüfungen (alle real durchgeführt, siehe mail/docs/IMP-01-PRUEFPROTOKOLL.md): 1. TestRunOnce_TwoConsecutiveRunsNoDuplicateImport: zweiter Lauf real 0 neue Nachrichten. 2. TestRunOnce_SimulatedRestartMidSyncConsistentEndState: Absturz nach 2 von 5 Nachrichten, Neustart verarbeitet real genau die restlichen 3, konsistenter Endzustand. 3. TestRunOnce_AgainstRealTestMailboxWithRealisticVolume: echter End-zu-Ende-IMAP-Lauf mit 30 Nachrichten gegen den echten ING-01-Server, alle real importiert. Kein Umbau: mail/internal/folderstate (ING-05) unverändert. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HhgFcLS8tYMhDJpP74C6AQ
64 lines
3.5 KiB
Markdown
64 lines
3.5 KiB
Markdown
# IMP-01 – Prüfprotokoll: IMAP-Postfach-Abruf & Scheduler
|
||
|
||
Voraussetzung ING-01, ING-05 (beide Fertig).
|
||
|
||
## Umsetzung
|
||
|
||
- `mail/internal/imap` (ING-01) minimal erweitert: `Message.UID`,
|
||
`MailboxStore.FetchByUID` (RFC 3501 §6.4.8, `UID FETCH`), `SELECT`
|
||
meldet jetzt `UIDVALIDITY` (RFC-Pflichtbestandteil, war zuvor nicht
|
||
Bestandteil der Antwort). Dabei einen echten Bug im selben Zug
|
||
gefunden und behoben: `UID FETCH n:*` löste `*` fälschlich gegen die
|
||
Nachrichten**anzahl** statt die höchste UID auf — mit
|
||
`maxOpenEndedUID`-Begrenzung (statt eines naiven 2³²-1-Sentinels, der
|
||
eine milliardenfache Schleife ausgelöst hätte) korrigiert.
|
||
- `mail/internal/imapimport/state.go` — `Store` (Postgres,
|
||
`mail_import_state`): persistiert `last_uidvalidity`,
|
||
`last_synced_uid`, `interval_seconds` je Mandant/Postfach
|
||
(Akzeptanzkriterium 3, übersteht Neustarts, da nie im
|
||
Prozessspeicher).
|
||
- `mail/internal/imapimport/scheduler.go` — `Scheduler.RunOnce`:
|
||
UID-Vergleich klassifiziert Nachrichten als neu vs. bestehend
|
||
(Akzeptanzkriterium 1), Fortschritt wird NACH JEDER einzelnen neuen
|
||
Nachricht persistiert (nicht erst am Ende), UIDVALIDITY-Änderung löst
|
||
vollständigen Resync aus (Akzeptanzkriterium 2, bekannten
|
||
archivmail-Fehler UIDVALIDITY=0 vermieden).
|
||
- `mail/internal/imapimport/client_real.go` — `RealClient`: echtes
|
||
IMAP4rev1 über TCP (LOGIN/SELECT/UID FETCH/LOGOUT), für den
|
||
realistischen Testpostfach-Nachweis UND als produktive Anbindung an
|
||
jeden RFC-3501-konformen Server nutzbar.
|
||
- Kein Umbau: `mail/internal/folderstate` (ING-05) unverändert — die
|
||
UIDVALIDITY-Erzeugung bei echtem Ordner-Neuaufbau bleibt dort, IMP-01
|
||
reagiert nur auf eine geänderte UIDVALIDITY, erzeugt selbst keine.
|
||
|
||
## Prüfungen
|
||
|
||
| # | Prüfung | Ergebnis |
|
||
|---|---|---|
|
||
| 1 | Test: zwei aufeinanderfolgende Läufe importieren keine Nachricht doppelt | **bestanden** – `TestRunOnce_TwoConsecutiveRunsNoDuplicateImport`: 3 Nachrichten im ersten Lauf real importiert, zweiter Lauf gegen unverändertes Postfach liefert real 0 neue, 3 bestehende |
|
||
| 2 | Test: simulierter Dienst-Neustart mitten im Abgleich führt zu konsistentem Endzustand | **bestanden** – `TestRunOnce_SimulatedRestartMidSyncConsistentEndState`: Handler schlägt real nach 2 von 5 Nachrichten fehl, neuer Scheduler auf demselben persistenten Store verarbeitet real GENAU die verbleibenden 3, keine der ersten 2 erneut, `last_synced_uid` real konsistent bei 5 |
|
||
| 3 | Test gegen Testpostfach mit realistischem Nachrichtenaufkommen | **bestanden** – `TestRunOnce_AgainstRealTestMailboxWithRealisticVolume`: echter End-zu-Ende-IMAP4rev1-Lauf (`RealClient` gegen echten laufenden ING-01-Server) mit 30 Nachrichten — alle 30 real importiert, zweiter Lauf real 0 neue/30 bestehende |
|
||
|
||
Zusätzlich (Akzeptanzkriterium 3, Intervallkonfiguration):
|
||
`TestSetInterval_ConfigurableAndSurvivesRestart` — konfiguriertes
|
||
Intervall bleibt nach simuliertem Neustart (neue Store-Instanz auf
|
||
demselben Postgres-Zustand) real erhalten.
|
||
|
||
## Build/Test-Ergebnis (192.168.1.131)
|
||
|
||
```
|
||
go build ./... -> clean
|
||
go vet ./... -> clean
|
||
golangci-lint run ./... -> 0 issues
|
||
TEST_TENANT_DSN=... go test ./internal/imapimport/... -v -timeout 60s -> 4/4 bestanden
|
||
TEST_TENANT_DSN=... TEST_MANTICORE_URL=... go test ./... -p 1
|
||
-> alle 15 Pakete bestanden, keine Regression (inkl. ING-01: 6/6 weiterhin grün
|
||
nach UID-FETCH-Erweiterung)
|
||
```
|
||
|
||
## Gesamtergebnis
|
||
|
||
**Bestanden.** Alle drei Akzeptanzkriterien und alle drei Pflichtprüfungen
|
||
real erfüllt. Entsperrt IMP-02, IMP-03, IMP-04, IMP-05, IMP-07, IMP-08,
|
||
IMP-09, INT-05, UX-01.
|