Neues Paket mail/internal/protoguard kapselt die für IMAP- und POP3-Sessions gemeinsam benötigte Timeout- und Backoff-Logik einer einzelnen Verbindung: - Pro Protokollphase konfigurierbarer Idle-Read-Timeout (POP3: Authorization/Transaction, IMAP: NotAuthenticated/Selected), vor jedem Lesevorgang neu gesetzt. - Sich verdoppelnder Backoff bei wiederholten Anmeldefehlversuchen einer Verbindung (BackoffBase bis BackoffMax), Verbindungstrennung nach konfigurierbarer Höchstzahl statt Dauerschleife. Server.NewServer bleibt unverändert (Standardkonfiguration); NewServerWithGuardConfig erlaubt abweichende Werte. Ressourcenaufräumung bei Verbindungsabbruch war bereits durch defer conn.Close() strukturell gegeben — der Timeout sorgt dafür, dass dieser Pfad auch bei hängenden oder böswilligen Gegenstellen zuverlässig erreicht wird. Alle drei Pflichtprüfungen mit echten Nachweisen durchgeführt: Chaos-Test mit 30 hart gekappten Verbindungen während aktiver Übertragung (kein Goroutine-Leck), Timeout-Auslösung in jeder Protokollphase beider Server, steigender Backoff mit definierter Verbindungstrennung nach Höchstzahl an Fehlversuchen. go build/go vet/golangci-lint clean, gesamtes Mail-Modul (~24 Pakete) regressionsfrei getestet.
101 lines
4.4 KiB
Markdown
101 lines
4.4 KiB
Markdown
# ING-07 — Protokoll-Fehlerbehandlung & Wiederverbindung: Prüfprotokoll
|
||
|
||
Datum: 2026-09-01
|
||
Host: 192.168.1.131 (Build/Test/Lint), rsync + ssh
|
||
Pakete: `mail/internal/protoguard` (neu, gemeinsam genutzt), `mail/internal/imap`, `mail/internal/pop3`
|
||
|
||
## Umsetzung
|
||
|
||
Neues Paket `protoguard` kapselt Timeout- und Backoff-Logik EINER
|
||
Verbindung (`Guard`), von IMAP- und POP3-Session gleichermaßen genutzt:
|
||
|
||
- `ApplyReadDeadline(conn, phase)` setzt vor jedem Lesevorgang die
|
||
Lese-Deadline passend zur aktuellen Protokollphase (POP3:
|
||
Authorization/Transaction, IMAP: NotAuthenticated/Selected).
|
||
- `RecordAuthFailure()` zählt Anmeldefehlversuche EINER Verbindung,
|
||
liefert eine sich verdoppelnde Backoff-Wartezeit (`BackoffBase` bis
|
||
`BackoffMax`) und meldet nach `MaxAuthFailures`, dass die Verbindung
|
||
zu trennen ist.
|
||
|
||
`Server.NewServer` verwendet `protoguard.DefaultConfig()` (5 Minuten
|
||
Timeout, max. 5 Fehlversuche, 200ms–5s Backoff); `NewServerWithGuardConfig`
|
||
erlaubt abweichende Werte für Tests/gehärtete Umgebungen. Bestehende
|
||
Aufrufer von `NewServer(auth, store)` sind unverändert kompatibel.
|
||
|
||
Ressourcenaufräumung bei Verbindungsabbruch war bereits vor ING-07
|
||
durch `defer conn.Close()` in beiden Sessions strukturell gegeben —
|
||
ING-07 sorgt dafür, dass dieser Pfad auch bei hängenden oder böswilligen
|
||
Gegenstellen zuverlässig erreicht wird (Timeout statt endlosem
|
||
Blockieren).
|
||
|
||
## Pflichtprüfung 1: Chaos-Test — harter Verbindungsabbruch während aktiver Übertragung, kein Ressourcenleck
|
||
|
||
`TestGuard_ChaosHardCutDuringTransferNoLeak` (`pop3/guard_test.go`,
|
||
`imap/guard_test.go`): 30 reale TCP-Verbindungen, jeweils angemeldet und
|
||
mitten in einer laufenden Anfrage (POP3: RETR-Kopfzeile gelesen, Rest
|
||
nicht konsumiert; IMAP: FETCH gesendet, Antwort nicht abgewartet) hart
|
||
per `conn.Close()` gekappt. `runtime.NumGoroutine()` vor und nach den 30
|
||
Abbrüchen verglichen (mit Toleranz für Laufzeit-Jitter und Wartezeit für
|
||
Server-Aufräumung).
|
||
|
||
Ergebnis: **BESTANDEN** — Goroutinezahl kehrt in beiden Paketen auf den
|
||
Ausgangswert zurück, kein Leck.
|
||
|
||
## Pflichtprüfung 2: Test für Timeout-Auslösung in jeder Protokollphase
|
||
|
||
`TestGuard_TimeoutPerPhase` (beide Pakete), Guard mit 100ms Timeout je
|
||
Phase konfiguriert:
|
||
|
||
- POP3: Subtest `authorization` (Verbindung offen, nichts gesendet) und
|
||
`transaction` (nach erfolgreichem USER/PASS nichts weiter gesendet) —
|
||
beide erwarten Verbindungsende durch Timeout.
|
||
- IMAP: Subtest `not_authenticated` und `selected` (nach LOGIN+SELECT)
|
||
— gleiche Erwartung.
|
||
|
||
Ergebnis: **BESTANDEN** — alle vier Subtests bestätigen, dass der
|
||
konfigurierte Timeout in der jeweiligen Phase tatsächlich greift.
|
||
|
||
## Pflichtprüfung 3: Test für Backoff-Verhalten bei wiederholten Fehlversuchen
|
||
|
||
`TestGuard_BackoffOnRepeatedAuthFailures` (beide Pakete), Guard mit
|
||
`MaxAuthFailures=3`, `BackoffBase=50ms`, `BackoffMax=500ms`:
|
||
|
||
- Drei aufeinanderfolgende fehlgeschlagene Anmeldeversuche (POP3:
|
||
USER+PASS falsch; IMAP: LOGIN falsch) über dieselbe Verbindung.
|
||
Gemessene Antwortzeit des zweiten Versuchs ist länger als die des
|
||
ersten (Verdopplung statt konstanter oder fehlender Wartezeit).
|
||
- Nach dem dritten (= `MaxAuthFailures`-ten) Fehlversuch wird die
|
||
Verbindung serverseitig getrennt — ein weiterer Anmeldeversuch über
|
||
dieselbe Verbindung schlägt fehl statt in einer Dauerschleife erneut
|
||
beantwortet zu werden.
|
||
|
||
Ergebnis: **BESTANDEN**.
|
||
|
||
## Akzeptanzkriterien
|
||
|
||
1. **Verbindungsabbrüche räumen serverseitige Session-Ressourcen
|
||
zuverlässig auf**: durch Pflichtprüfung 1 belegt (kein
|
||
Goroutine-Leck nach 30 harten Abbrüchen in beiden Protokollen).
|
||
2. **Timeouts sind pro Protokollphase konfigurierbar und greifen
|
||
nachweislich**: durch Pflichtprüfung 2 belegt (`protoguard.Config.
|
||
PhaseTimeout` je Phase, vier bestandene Subtests).
|
||
3. **Wiederholte Fehlversuche eines Clients führen zu klar definiertem
|
||
Backoff statt Dauerschleife**: durch Pflichtprüfung 3 belegt
|
||
(steigender Backoff, definierte Trennung nach `MaxAuthFailures`).
|
||
|
||
## Build/Vet/Lint/Test — Gesamtmodul
|
||
|
||
```
|
||
go build ./... → OK
|
||
go vet ./... → OK
|
||
golangci-lint run ./... → 0 issues
|
||
go test ./... -p 1 (TEST_TENANT_DSN, TEST_MANTICORE_URL gesetzt) → alle Pakete ok, inkl. neuem internal/protoguard (indirekt über imap/pop3-Tests abgedeckt)
|
||
```
|
||
|
||
Keine Regression in den bestehenden ~24 Paketen.
|
||
|
||
## Ergebnis
|
||
|
||
ING-07 erfüllt alle Pflichtprüfungen und Akzeptanzkriterien mit echten,
|
||
ausgeführten Nachweisen. Freigeschaltet: QA-02.
|