Modul-14 Notification als FREIGEGEBEN dokumentiert (E2E Punkte 1-7 gruen, 20.08.2026)
This commit is contained in:
parent
7e9d076fb8
commit
4fc967835a
2 changed files with 150 additions and 3 deletions
11
README.md
11
README.md
|
|
@ -41,10 +41,11 @@ Jede Änderung folgt dem **Notation-Format**: Autor (`Alice` / `Rain Ocampo`) +
|
|||
| 11 | Analytics | ✅ FREIGEGEBEN (analytics-service:0.1.0) | 55011 (intern) |
|
||||
| 12 | Backtesting | ✅ FREIGEGEBEN (backtesting:0.1.2) | 55012 (intern) |
|
||||
| 13 | Optimization | ✅ FREIGEGEBEN (optimization:0.1.0) | 55013 (intern) |
|
||||
| 14–17 | … | ⬜ Platzhalter (alpine) | 55014–55017 |
|
||||
| 14 | Notification | ✅ FREIGEGEBEN (notification:0.1.0) | 55014 (intern) |
|
||||
| 15–17 | … | ⬜ Platzhalter (alpine) | 55015–55017 |
|
||||
|
||||
Details: siehe `modul-03-market-data.md` … `modul-13-optimization.md` (Module 03–13
|
||||
vollständig implementiert und freigegeben). Modul-14 ff. folgen.
|
||||
Details: siehe `modul-03-market-data.md` … `modul-14-notification.md` (Module 03–14
|
||||
vollständig implementiert und freigegeben). Modul-15 ff. folgen.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -85,3 +86,7 @@ Grund: README-Modultabelle aktualisiert — Modul-12 auf backtesting:0.1.2 (V1.1
|
|||
Geändert von: Rain Ocampo
|
||||
Datum: 20.08.2026
|
||||
Grund: README-Modultabelle aktualisiert — Modul-13 Optimization als FREIGEGEBEN markiert (Freigabe durch Nutzer 20.08.2026).
|
||||
|
||||
Geändert von: Rain Ocampo
|
||||
Datum: 20.08.2026
|
||||
Grund: README-Modultabelle aktualisiert — Modul-14 Notification als FREIGEGEBEN eingetragen; Details-Link auf modul-14-notification.md erweitert.
|
||||
|
|
|
|||
142
modul-14-notification.md
Normal file
142
modul-14-notification.md
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
# Modul-14: Notification-Service
|
||||
|
||||
**Status: FREIGEGEBEN ✅** · Container `Modul-14-Notification` · Image `notification:0.1.0`
|
||||
|
||||
## Zweck
|
||||
Zentrale **Benachrichtigungen für Trading- und Systemereignisse**. Konsumiert relevante
|
||||
Events aus den RabbitMQ-Exchanges der Module 05–10 und liefert kompakte, strukturierte
|
||||
Meldungen — **V1 primär über Telegram** (`TelegramProvider`), provider-neutral angelegt.
|
||||
|
||||
**Restriktionen (Nutzer-Vorgabe):**
|
||||
- **keine KI/ML**, **keine Trading-Entscheidungen**, **keine Orders**.
|
||||
- **FAIL-SAFE:** Ein Notification-Ausfall darf die Trading-Pipeline **NIEMALS blockieren**.
|
||||
|
||||
## Architektur / Datenfluss
|
||||
```
|
||||
RabbitMQ (market.signals/.rankings/.risk/.portfolio/.execution/.journal)
|
||||
│ NotificationConsumer (notification.input)
|
||||
▼
|
||||
Modul-14-Notification ── NotificationService ──> RulesEngine + DedupGuard
|
||||
│ │ Spam-Schutz
|
||||
├── providers/ NotificationProvider-ABC → Telegram / Fake
|
||||
├── rules/ RulesEngine (Regeln) + DedupGuard (Dedup/Cooldown/Rate-Limit)
|
||||
├── storage/ Persistenz notification_log (PostgreSQL, Modul-01)
|
||||
├── core/ formatter (kompakte Nachricht) + service (Retry/Backoff)
|
||||
└── api/main.py REST-API (intern, Port 55014)
|
||||
|
||||
Event → RabbitMQ → Modul-14 → notification_log → Provider (Telegram) → Chat
|
||||
```
|
||||
|
||||
## API (Docker-intern, Port 55014, kein öffentliches Port-Mapping)
|
||||
```
|
||||
GET /health liveness
|
||||
GET /health/ready readiness (postgresql, consumer_ready, provider_configured)
|
||||
GET /notifications/recent letzte Notifications
|
||||
GET /notifications/{id} einzelne Notification
|
||||
POST /notifications/test Test-Sendung (nur konfigurierte Destinationen)
|
||||
```
|
||||
|
||||
## Konsumierte Events & Routing-Keys
|
||||
| Event-Typ | Exchange | Routing-Key | Default-Severity | Default aktiv |
|
||||
|-----------|----------|-------------|------------------|---------------|
|
||||
| `SIGNAL_DETECTED` | `market.signals` | `strategy.signal.detected` | INFO | ❌ (deaktiviert) |
|
||||
| `SIGNAL_RANKED` | `market.rankings` | `signal.ranked` | INFO | ❌ (deaktiviert) |
|
||||
| `RISK_APPROVED` | `market.risk` | `risk.approved` | INFO | ❌ (deaktiviert) |
|
||||
| `RISK_REJECTED` | `market.risk` | `risk.rejected` | WARNING | ❌ (deaktiviert) |
|
||||
| `TRADE_APPROVED` | `market.portfolio` | `trade.approved` | INFO | ✅ |
|
||||
| `PORTFOLIO_REJECTED` | `market.portfolio` | `portfolio.rejected` | WARNING | ✅ |
|
||||
| `ORDER_SUBMITTED` | `market.execution` | `order.submitted` | INFO | ❌ (deaktiviert) |
|
||||
| `ORDER_FILLED` | `market.execution` | `order.filled` | INFO | ✅ |
|
||||
| `ORDER_REJECTED` | `market.execution` | `order.rejected` | CRITICAL | ✅ |
|
||||
| `ORDER_FAILED` | `market.execution` | `order.failed` | CRITICAL | ✅ |
|
||||
| `TRADE_RECORDED` | `market.journal` | `trade.recorded` | INFO | ✅ |
|
||||
|
||||
Die Regeln sind **pro Event-Typ konfigurierbar** (aktiv/inaktiv, Severity, Provider,
|
||||
Destination, Cooldown, Rate-Limit). **Unbekannte Event-Typen werden sicher ignoriert**
|
||||
(kein Crash). V1 sind die rauschigen Events (SIGNAL_*, RISK_*, ORDER_SUBMITTED)
|
||||
standardmäßig deaktiviert.
|
||||
|
||||
## Severity-Hierarchie
|
||||
```
|
||||
INFO < WARNING < CRITICAL
|
||||
```
|
||||
Regel-Severity überschreibt den Event-Standard. V1: alle über Telegram.
|
||||
|
||||
## Spam-Schutz (DedupGuard)
|
||||
Mehrstufig, thread-sicher (Lock):
|
||||
1. **Idempotenz** — gleiche `event_id`/`source_event_id` erzeugt nie eine zweite Notification (DB-unique über `source_event_id` + `event_processed`-Check).
|
||||
2. **Dedup** — identische Meldungen (gleicher Text/Event-Typ) in kurzem Fenster werden zusammengefasst.
|
||||
3. **Cooldown** — pro Event-Typ ein Mindestabstand (`cooldown_seconds`, Default 60s).
|
||||
4. **Rate-Limit** — maximale Notifications pro Minute (`rate_limit_per_minute`, Default 30).
|
||||
5. **Burst-Schutz** — Ansturm vieler Events wird aufs Limit begrenzt.
|
||||
|
||||
## Retry / Dead (FAIL-SAFE)
|
||||
- Provider nicht erreichbar → `RETRY_PENDING` mit **begrenzten Retries** (exponentielles Backoff).
|
||||
- `max_attempts` (Default 5) erreicht → **DEAD** (keine Endlosschleife).
|
||||
- **Provider nicht konfiguriert** (fehlender Token/Chat-ID) → **sofort DEAD** mit
|
||||
`error_code=NOT_CONFIGURED` (keine sinnlosen Retries).
|
||||
- Nach Provider-Recovery werden **neue Events wieder normal gesendet** (Retry betrifft nur die jeweilige Notification).
|
||||
|
||||
## Eigene Tabelle (Migration)
|
||||
`notification_log`:
|
||||
`notification_id` (PK), `source_event_id`, `event_type`, `severity`, `provider`,
|
||||
`destination`, `status` (`SENT`/`FAILED`/`RETRY_PENDING`/`DEAD`), `attempts`,
|
||||
`created_at`, `sent_at`, `error_code`, `error_message`.
|
||||
|
||||
## Sicherheit
|
||||
- **KEINE Secrets in DB/Logs/Doku/Commits.** Telegram-Bot-Token/Chat-ID ausschließlich
|
||||
über Environment (Compose `TELEGRAM_BOT_TOKEN`, `TELEGRAM_CHAT_ID`), nie hart kodiert.
|
||||
- `/notifications/test` sendet **nur an konfigurierte Destinationen**.
|
||||
|
||||
## Tests
|
||||
- `tests/test_notification.py`: **14/14 grün** (Event→Notification, Idempotenz, Dedup,
|
||||
Cooldown, Rate-Limit, Telegram-Ausfall blockiert nicht, Retry+Backoff, Max→DEAD,
|
||||
keine Secrets, unbekannter Typ ignoriert, Severity/Regeln, FakeProvider, Reconnect).
|
||||
|
||||
## E2E-Verifikation (VPS, 20.08.2026) — alle 7 Punkte grün
|
||||
1. **Fake-Telegram-E2E** (Modul-14 auf `http://fake-telegram:55000`, Test-Token/Chat-ID
|
||||
nur als ENV): echtes `TRADE_RECORDED` publiziert → **Event → RabbitMQ → Modul-14 →
|
||||
notification_log → Fake-Telegram** komplett durchlaufen. DB: `status=SENT`,
|
||||
`sent_at` gesetzt, `attempts=0`, **genau 1 Zustellung, kein Duplikat**. Fake-Telegram
|
||||
RAW: `{"chat_id": "E2E_TEST_CHAT_114", "text": "TRADE RECORDED | NVDA | LONG | OPEN"}`.
|
||||
2. **NO_CONFIG-Fix**: Container ohne Token → Event → `status=DEAD, attempts=1,
|
||||
error_code=NOT_CONFIGURED` (sofortiges DEAD, keine 5 sinnlosen Retries).
|
||||
3. **Fehlerfall-E2E**: Fake-Telegram gestoppt → Notification `RETRY_PENDING` mit
|
||||
Backoff (attempts 2→4, `NETWORK_ERROR`), **Trading-Pipeline unbeeinflusst**,
|
||||
Max-Retries (`attempts=5`) → `DEAD`. Nach Fake-Telegram-Recovery → neues Event
|
||||
wieder `SENT`.
|
||||
4. **RabbitMQ-Reconnect**: kontrollierter Restart → Modul-14 reconnectet automatisch
|
||||
(Backoff 4s→8s→16s, „Consumer verbunden"), **genau 1 Consumer** an `notification.input`,
|
||||
keine Zombies, keine verlorenen/duplizierten Notifications (nach Reconnect: 1 Zustellung, 0 Duplikate).
|
||||
5. **Spam-/Sicherheitschecks** (praktisch): unbekannter Typ `UNKNOWN_EVENT_XYZ` → ignoriert;
|
||||
gleiche `event_id` 2× → nur 1 Notification (Idempotenz); gleicher Event-Typ 2×
|
||||
→ Cooldown greift; deaktivierter `SIGNAL_DETECTED` → keine Notification. **Keine
|
||||
Tokens/Chat-IDs in Logs/API/Doku/DB** (0 Token-Leaks).
|
||||
6. **Health/Readiness**: `/health` + `/health/ready` → 200
|
||||
(`postgresql=true, consumer_ready=true, provider_configured=…`). Keine
|
||||
Applikations-Tracebacks im Normalbetrieb (nur erwartete Reconnect-Logs beim Test).
|
||||
Port 55014 nur intern (`expose`, kein Host-Port).
|
||||
7. **Forgejo-Doku + Commit-ID** (siehe Freigabe unten), temporäre Test-Credentials
|
||||
entfernt, Remote token-/key-frei.
|
||||
|
||||
## Freigabe
|
||||
- **20.08.2026: Modul-14-Notification-Service vom Nutzer FREIGEGEBEN ✅**
|
||||
(nach vollständiger E2E-Verifikation der Punkte 1–7, alle grün).
|
||||
- Keine weiteren technischen Änderungen an Modul-14.
|
||||
|
||||
## Compose / Betrieb
|
||||
- Netzwerk `trading-modules`, DB-Host `Modul-01-PostgreSQL`, RabbitMQ `Modul-02-RabbitMQ`.
|
||||
- Port 55014 nur intern (`expose`), `restart: unless-stopped`, non-root (uid 1001).
|
||||
- Token/Chat-ID via ENV (`TELEGRAM_BOT_TOKEN`, `TELEGRAM_CHAT_ID`, `TELEGRAM_API_BASE`).
|
||||
|
||||
## Nächste Module
|
||||
- **Modul-15 ff.** — noch Platzhalter (alpine), NICHT gestartet.
|
||||
|
||||
---
|
||||
## Geändert
|
||||
```
|
||||
Geändert von: Rain Ocampo
|
||||
Datum: 20.08.2026
|
||||
Grund: Modul-14-Notification-Service dokumentiert — E2E-verifiziert (Punkte 1–7 grün),
|
||||
API/Events/Severity/Retry-Dead/Spam-Schutz/Fake-E2E dokumentiert, Status FREIGEGEBEN.
|
||||
```
|
||||
Loading…
Reference in a new issue