feat(PROJ-8): Automatischer IMAP-Sync (Cron-Scheduler)

Backend:
- internal/imap/store.go: 7 neue Felder (sync_interval_min, last_sync_at,
  last_sync_count, last_uid, sync_running, sync_status, sync_error_msg)
  DB-Migration via ALTER TABLE ADD COLUMN IF NOT EXISTS
  Neue Methoden: ListAll, UpdateSyncInterval, SetSyncRunning, UpdateSyncResult
- internal/imap/scheduler.go: Scheduler mit time.Ticker (1 min),
  inkrementeller Sync via UID SEARCH UID <lastUID+1>:*,
  exponential backoff (3 Versuche: 1s / 60s / 300s),
  sync_running-Flag verhindert parallele Syncs
- internal/api/server.go: POST /api/imap/{id}/sync (manueller Trigger),
  PATCH /api/imap/{id} (sync_interval_min setzen, 0 oder 5-1440 min)
- cmd/archivmail/main.go: Scheduler gestartet + via SetImap verdrahtet

Frontend:
- src/lib/api.ts: 6 neue ImapAccount-Felder, triggerImapSync, updateImapInterval
- src/app/imap/page.tsx: Intervall-Dropdown, "Sync jetzt"-Button,
  Letzter-Sync-Anzeige mit Status-Badge, Polling auch bei sync_running

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
sysops
2026-03-17 02:17:44 +01:00
parent 9cc540a880
commit 988c37d85d
9 changed files with 762 additions and 52 deletions
+18 -9
View File
@@ -1,8 +1,8 @@
# PROJ-8: Automatischer IMAP-Sync (Cron-Job)
## Status: In Progress
## Status: Deployed
**Created:** 2026-03-12
**Last Updated:** 2026-03-12
**Last Updated:** 2026-03-17
## Dependencies
- Requires: PROJ-3 (IMAP-Import) IMAP-Verbindungen müssen konfiguriert sein
@@ -15,12 +15,12 @@
- Als System möchte ich beim Sync nur neue E-Mails (seit letztem Sync) abholen, damit kein unnötiger Traffic entsteht.
## Acceptance Criteria
- [ ] Sync-Intervall pro IMAP-Verbindung konfigurierbar (min. 5 Minuten, max. 24 Stunden)
- [ ] IMAP UID-basierter inkrementeller Sync (nur neue E-Mails seit letztem Sync)
- [ ] Admin-UI zeigt: letzter Sync, Status (Erfolg/Fehler), Anzahl importierter E-Mails
- [ ] Manueller "Sync jetzt"-Button im Admin-Bereich
- [ ] Bei Sync-Fehler: Retry mit exponential backoff (max. 3 Versuche)
- [ ] Sync-Fehler nach allen Versuchen → Fehlermeldung im Admin-Dashboard
- [x] Sync-Intervall pro IMAP-Verbindung konfigurierbar (min. 5 Minuten, max. 24 Stunden)
- [x] IMAP UID-basierter inkrementeller Sync (nur neue E-Mails seit letztem Sync)
- [x] Admin-UI zeigt: letzter Sync, Status (Erfolg/Fehler), Anzahl importierter E-Mails
- [x] Manueller "Sync jetzt"-Button im Admin-Bereich
- [x] Bei Sync-Fehler: Retry mit exponential backoff (max. 3 Versuche)
- [x] Sync-Fehler nach allen Versuchen → Fehlermeldung im Admin-Dashboard
## Edge Cases
- IMAP-Server temporär nicht erreichbar → Retry ohne Abbruch des gesamten Sync-Jobs
@@ -29,9 +29,18 @@
- Zeitzonenprobleme beim Datum-Vergleich → immer UTC intern verwenden
## Technical Requirements
- Cron-Scheduler eingebettet (z.B. robfig/cron für Go)
- Kein externer Cron-Scheduler `time.NewTicker(1 * time.Minute)` + Goroutine (YAGNI, keine neue Abhängigkeit)
- Sync-Status persistent in DB gespeichert (überlebt Server-Neustart)
## Implementation Notes (2026-03-17)
- `internal/imap/store.go`: Account-Struct um 7 Sync-Felder erweitert; `migrationSQL` mit `ADD COLUMN IF NOT EXISTS`; neue Methoden: `ListAll`, `UpdateSyncInterval`, `SetSyncRunning`, `UpdateSyncResult`; einheitliche `scanRow(scanner)`-Funktion mit eigenem Interface statt `pgx.Row`
- `internal/imap/scheduler.go`: Neues Paket; `Scheduler` mit `sync.Mutex`-geschützter `running`-Map; `Start/Stop/TriggerSync`; `runSyncWithRetry` mit 3 Versuchen (Backoffs: 1s, 60s, 300s); `doSync` delegiert `storeAndIndex` an den vorhandenen `Importer`
- `internal/api/server.go`: `imapScheduler`-Feld; `SetImap`-Signatur erweitert; neue Routen `POST /api/imap/{id}/sync` und `PATCH /api/imap/{id}`
- `src/lib/api.ts`: ImapAccount um 6 Felder erweitert; `triggerImapSync`, `updateImapInterval` hinzugefügt
- `src/app/imap/page.tsx`: Polling auch für `sync_running`; Dropdown für Sync-Intervall; "Sync jetzt"-Button; Sync-Status-Badge + letzter Sync-Zeitstempel pro Account-Card
- `cmd/archivmail/main.go`: `NewScheduler`, `Start`, `Stop`, `SetImap` mit Scheduler verdrahtet
---
## Tech Design (Solution Architect)