7.7 KiB
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):
- Idempotenz — gleiche
event_id/source_event_iderzeugt nie eine zweite Notification (DB-unique übersource_event_id+event_processed-Check). - Dedup — identische Meldungen (gleicher Text/Event-Typ) in kurzem Fenster werden zusammengefasst.
- Cooldown — pro Event-Typ ein Mindestabstand (
cooldown_seconds, Default 60s). - Rate-Limit — maximale Notifications pro Minute (
rate_limit_per_minute, Default 30). - Burst-Schutz — Ansturm vieler Events wird aufs Limit begrenzt.
Retry / Dead (FAIL-SAFE)
- Provider nicht erreichbar →
RETRY_PENDINGmit 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/testsendet 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
- Fake-Telegram-E2E (Modul-14 auf
http://fake-telegram:55000, Test-Token/Chat-ID nur als ENV): echtesTRADE_RECORDEDpubliziert → Event → RabbitMQ → Modul-14 → notification_log → Fake-Telegram komplett durchlaufen. DB:status=SENT,sent_atgesetzt,attempts=0, genau 1 Zustellung, kein Duplikat. Fake-Telegram RAW:{"chat_id": "E2E_TEST_CHAT_114", "text": "TRADE RECORDED | NVDA | LONG | OPEN"}. - NO_CONFIG-Fix: Container ohne Token → Event →
status=DEAD, attempts=1, error_code=NOT_CONFIGURED(sofortiges DEAD, keine 5 sinnlosen Retries). - Fehlerfall-E2E: Fake-Telegram gestoppt → Notification
RETRY_PENDINGmit Backoff (attempts 2→4,NETWORK_ERROR), Trading-Pipeline unbeeinflusst, Max-Retries (attempts=5) →DEAD. Nach Fake-Telegram-Recovery → neues Event wiederSENT. - 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). - Spam-/Sicherheitschecks (praktisch): unbekannter Typ
UNKNOWN_EVENT_XYZ→ ignoriert; gleicheevent_id2× → nur 1 Notification (Idempotenz); gleicher Event-Typ 2× → Cooldown greift; deaktivierterSIGNAL_DETECTED→ keine Notification. Keine Tokens/Chat-IDs in Logs/API/Doku/DB (0 Token-Leaks). - 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). - 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-HostModul-01-PostgreSQL, RabbitMQModul-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.