feat(PROJ-17): Admin Dashboard Systemauslastung immer anzeigen
- Systemauslastungs-Sektion wird immer gerendert (nicht nur bei Erfolg) - Fehlermeldung wenn /api/admin/system/stats nicht erreichbar ist - Feature-Status auf In Review gesetzt Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
# PROJ-8: Automatischer IMAP-Sync (Cron-Job)
|
||||
|
||||
## Status: In Progress
|
||||
**Created:** 2026-03-12
|
||||
**Last Updated:** 2026-03-12
|
||||
|
||||
## Dependencies
|
||||
- Requires: PROJ-3 (IMAP-Import) – IMAP-Verbindungen müssen konfiguriert sein
|
||||
- Requires: PROJ-5 (Speicherung & Indexierung)
|
||||
|
||||
## User Stories
|
||||
- Als Admin möchte ich ein Sync-Intervall konfigurieren (z.B. alle 15 Minuten), damit neue E-Mails automatisch archiviert werden.
|
||||
- Als Admin möchte ich den letzten Sync-Zeitpunkt und -Status pro IMAP-Verbindung sehen.
|
||||
- Als Admin möchte ich den Sync manuell auslösen können, damit ich nicht auf den nächsten Intervall warten muss.
|
||||
- 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
|
||||
|
||||
## Edge Cases
|
||||
- IMAP-Server temporär nicht erreichbar → Retry ohne Abbruch des gesamten Sync-Jobs
|
||||
- Sync läuft noch wenn neuer Intervall beginnt → kein paralleler Sync für dieselbe Verbindung
|
||||
- E-Mails auf dem Server wurden gelöscht → im Archiv behalten (Archiv ist immutable)
|
||||
- Zeitzonenprobleme beim Datum-Vergleich → immer UTC intern verwenden
|
||||
|
||||
## Technical Requirements
|
||||
- Cron-Scheduler eingebettet (z.B. robfig/cron für Go)
|
||||
- Sync-Status persistent in DB gespeichert (überlebt Server-Neustart)
|
||||
|
||||
---
|
||||
## Tech Design (Solution Architect)
|
||||
|
||||
### Komponentenstruktur
|
||||
|
||||
**Next.js Frontend (Admin-Bereich):**
|
||||
```
|
||||
/admin/imap (integriert in IMAP-Verbindungsliste aus PROJ-3)
|
||||
└── VerbindungsCard (pro Konto)
|
||||
├── Sync-Intervall (Dropdown: 5min / 15min / 1h / 6h / 24h)
|
||||
├── Letzter Sync: Zeitpunkt + Status (✓ OK / ✗ Fehler)
|
||||
├── Anzahl importierter Mails beim letzten Sync
|
||||
├── Fehlermeldung (wenn letzter Sync fehlgeschlagen)
|
||||
└── [Sync jetzt] Button
|
||||
```
|
||||
|
||||
**Go Backend:**
|
||||
```
|
||||
Sync-Scheduler (startet beim Binary-Start)
|
||||
├── Cron-Loop ← prüft jede Minute alle IMAP-Accounts
|
||||
│ └── Für jeden Account:
|
||||
│ ├── Intervall abgelaufen? → Sync-Worker starten
|
||||
│ └── Sync läuft bereits? → überspringen (kein Parallel-Sync)
|
||||
│
|
||||
├── Sync-Worker (pro Account, Goroutine)
|
||||
│ ├── IMAP verbinden (gleicher Client wie PROJ-3)
|
||||
│ ├── Letzte bekannte UID aus DB laden
|
||||
│ ├── UID SEARCH UID <last_uid>:* → nur neue Mails
|
||||
│ ├── FETCH neue Mails
|
||||
│ ├── → Storage Coordinator (PROJ-5)
|
||||
│ ├── Letzte UID + Zeitstempel in DB speichern
|
||||
│ └── Bei Fehler: Retry mit Exponential Backoff
|
||||
│ (1. Versuch: sofort, 2.: +1min, 3.: +5min → dann Fehler)
|
||||
│
|
||||
└── POST /api/admin/imap/{id}/sync ← manueller Trigger
|
||||
└── Sync-Worker sofort starten (ignoriert Intervall)
|
||||
```
|
||||
|
||||
### Sync-Fluss
|
||||
|
||||
```
|
||||
Cron-Loop (jede Minute)
|
||||
│
|
||||
└── Account "Firmen-Postfach" – Intervall: 15 min
|
||||
last_sync_at = vor 16 Minuten → fällig
|
||||
sync_running = false → starten
|
||||
│
|
||||
▼
|
||||
IMAP verbinden
|
||||
│
|
||||
▼
|
||||
last_uid = 4821 (aus DB)
|
||||
UID SEARCH UID 4822:*
|
||||
→ [4822, 4823, 4830, 4831] (4 neue Mails)
|
||||
│
|
||||
▼
|
||||
FETCH 4822:4831 RFC822
|
||||
│
|
||||
▼
|
||||
Für jede Mail:
|
||||
Duplikat? → überspringen
|
||||
→ Storage Coordinator
|
||||
│
|
||||
▼
|
||||
last_uid = 4831 in DB speichern
|
||||
last_sync_at = NOW() (UTC)
|
||||
sync_status = "ok"
|
||||
sync_count = 4
|
||||
```
|
||||
|
||||
### Exponential Backoff bei Fehlern
|
||||
|
||||
```
|
||||
Sync-Fehler (z.B. IMAP nicht erreichbar)
|
||||
│
|
||||
├── Versuch 1: sofort → Fehler
|
||||
├── Versuch 2: +1 Minute → Fehler
|
||||
├── Versuch 3: +5 Minuten → Fehler
|
||||
└── Aufgeben:
|
||||
sync_status = "error"
|
||||
error_msg = "Connection refused after 3 attempts"
|
||||
→ Admin-Dashboard zeigt Fehler
|
||||
→ nächster regulärer Intervall versucht es erneut
|
||||
```
|
||||
|
||||
### Datenmodell (Ergänzung zu `imap_accounts`)
|
||||
|
||||
| Feld | Beschreibung |
|
||||
|------|-------------|
|
||||
| `sync_interval_min` | Sync-Intervall in Minuten (5–1440) |
|
||||
| `last_sync_at` | Zeitpunkt des letzten Syncs (UTC) |
|
||||
| `last_sync_count` | Anzahl importierter Mails beim letzten Sync |
|
||||
| `last_uid` | Höchste bekannte IMAP-UID (Startpunkt für nächsten Sync) |
|
||||
| `sync_running` | `true` wenn Sync gerade läuft (verhindert parallelen Sync) |
|
||||
| `sync_status` | `ok` / `error` / `running` |
|
||||
| `sync_error_msg` | Letzte Fehlermeldung |
|
||||
|
||||
### Technische Entscheidungen
|
||||
|
||||
| Entscheidung | Begründung |
|
||||
|---|---|
|
||||
| **UID-basierter inkrementeller Sync** | Nur neue Mails seit letzter bekannter UID werden abgeholt – minimaler Traffic, kein Re-Download |
|
||||
| **`sync_running`-Flag in DB** | Verhindert parallelen Sync derselben Verbindung auch nach Server-Neustart |
|
||||
| **Cron-Loop jede Minute** | Einfacher als individuelle Timer pro Account – skaliert auf viele Accounts ohne Overhead |
|
||||
| **Exponential Backoff** | Temporäre Ausfälle (Netz, Server-Neustart) werden automatisch überbrückt ohne Admin-Eingriff |
|
||||
| **Status persistent in DB** | Server-Neustart verliert keinen Sync-Fortschritt – Scheduler macht nahtlos weiter |
|
||||
| **Manueller Trigger** | Admin kann sofortigen Sync anstoßen ohne auf Intervall zu warten |
|
||||
|
||||
### Abhängigkeiten
|
||||
|
||||
| Paket | Zweck |
|
||||
|---|---|
|
||||
| `github.com/robfig/cron` | Eingebetteter Cron-Scheduler |
|
||||
| `github.com/emersion/go-imap` | IMAP-Client (bereits PROJ-3) |
|
||||
|
||||
## QA Test Results
|
||||
_To be added by /qa_
|
||||
|
||||
## Deployment
|
||||
_To be added by /deploy_
|
||||
Reference in New Issue
Block a user