docs: Alicia-Aufgaben 21-25 (Integration & Pipeline)
This commit is contained in:
@@ -1,124 +1,113 @@
|
|||||||
# Alicia — Aufgaben 16–20: BSN-Livesystem Phase 3 (Live-Vorbereitung)
|
# Alicia — Aufgaben 21–25: Integration & Pipeline
|
||||||
|
|
||||||
> **Repo:** `git@git.datenhimmel.work:danielkrause/BSN-Livesystem.git`
|
> **Repo:** git@git.datenhimmel.work:danielkrause/BSN-Livesystem.git
|
||||||
> **Stand:** 15 Aufgaben fertig. Phase 2 abgeschlossen.
|
> **Branch:** main
|
||||||
> **Ziel:** Projekt live-fähig machen — Config, DB, Error-Handling, Service-Dateien.
|
> **Qualität:** `ruff check . && ruff format . && mypy --config-file pyproject.toml . && pytest -v` vor JEDEM Commit
|
||||||
|
> **Fehler?** Korrigieren, erneut prüfen. Nicht aufgeben.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Aufgabe 16 — Konfigurations-Management (pydantic-settings)
|
## Aufgabe 21 — WhatsApp-Webhook Queue-Integration
|
||||||
|
### Datei: `src/routes/whatsapp.py`
|
||||||
Ersetze hartcodierte Werte durch eine zentrale Config-Klasse.
|
|
||||||
|
|
||||||
### Datei 1: `src/config.py`
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from __future__ import annotations
|
# Aktuell ist nur ein Platzhalter:
|
||||||
from pydantic_settings import BaseSettings
|
# # Hier würde die Submission in die Queue eingereiht werden
|
||||||
|
# return jsonify({"status": "accepted"}), 200
|
||||||
|
#
|
||||||
class Settings(BaseSettings):
|
# → Muss wie Telegram-Webhook funktionieren:
|
||||||
"""Zentrale Anwendungskonfiguration. Werte aus .env oder Environment."""
|
# 1. WhatsApp-Payload parsen (entry[0].changes[0].value.messages[0])
|
||||||
|
# 2. Submission bauen (message_id, plattform="whatsapp", absender, text)
|
||||||
REDIS_HOST: str = "localhost"
|
# 3. current_app.queue_handler.enqueue(submission)
|
||||||
REDIS_PORT: int = 6379
|
|
||||||
WHATSAPP_APP_SECRET: str = ""
|
|
||||||
WHATSAPP_VERIFY_TOKEN: str = "bsn_verify_token"
|
|
||||||
TELEGRAM_BOT_TOKEN: str = ""
|
|
||||||
APP_HOST: str = "0.0.0.0"
|
|
||||||
APP_PORT: int = 5002
|
|
||||||
APP_DEBUG: bool = False
|
|
||||||
|
|
||||||
class Config:
|
|
||||||
env_file = ".env"
|
|
||||||
env_file_encoding = "utf-8"
|
|
||||||
|
|
||||||
|
|
||||||
settings = Settings()
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Datei 2: `.env.template`
|
### Test-Datei: `tests/routes/test_whatsapp_queue.py`
|
||||||
|
3 Tests: Enqueue, Invalid Body→400, Missing Text→400
|
||||||
|
|
||||||
```
|
**Commit:** `feat: WhatsApp-Webhook reiht Submissions in Queue ein`
|
||||||
REDIS_HOST=localhost
|
|
||||||
REDIS_PORT=6379
|
---
|
||||||
WHATSAPP_APP_SECRET=dein_secret_hier
|
|
||||||
WHATSAPP_VERIFY_TOKEN=bsn_verify_token
|
## Aufgabe 22 — Intake-Kommando-Engine ausbauen
|
||||||
TELEGRAM_BOT_TOKEN=dein_bot_token_hier
|
### Datei: `src/services/intake.py`
|
||||||
APP_DEBUG=false
|
```python
|
||||||
|
# erkenne_kommando() erweitern:
|
||||||
|
# "suche/finde <spiel>" → SPIEL_SUCHEN
|
||||||
|
# "bewerte <spiel> mit <note>" → SPIEL_BEWERTEN
|
||||||
|
# "neuheiten", "/neu" → SPIEL_NEUHEITEN
|
||||||
|
# "hilfe", "/help", "/start" → HILFE
|
||||||
|
# sonst → UNBEKANNT
|
||||||
|
|
||||||
|
# NEU: extrahiere_spielname(text) → str | None
|
||||||
|
# NEU: extrahiere_bewertung(text) → int | None (1–10)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Integration: `src/app.py` umbauen
|
### Test-Datei: `tests/services/test_intake_extended.py`
|
||||||
|
6 Tests: Kommando-Varianten, Spielname-Extraktion, Bewertungsextraktion
|
||||||
|
|
||||||
`from src.config import settings` — ersetze alle Hart-Konfigurationen.
|
**Commit:** `feat: Intake-Engine mit Regex-Patterns und Spielnamen-Extraktion`
|
||||||
|
|
||||||
### Test: `tests/test_config.py` — 4 Tests
|
|
||||||
|
|
||||||
**Commit:** `feat: Pydantic-Settings Konfiguration mit .env-Support`
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Aufgabe 17 — Einheitliche Fehlerbehandlung
|
## Aufgabe 23 — Worker mit Intake-Pipeline verbinden
|
||||||
|
### Datei: `src/queue/worker.py`
|
||||||
|
```python
|
||||||
|
# verarbeite_submission() ersetzen:
|
||||||
|
# 1. erkenne_kommando(submission.text)
|
||||||
|
# 2. Je nach Kommando: Spielname/Bewertung extrahieren
|
||||||
|
# 3. Game-Service aufrufen (game_service.suche_spiel / bewerte_spiel)
|
||||||
|
# 4. Ergebnis in submission.ergebnis speichern
|
||||||
|
# 5. Status auf "erledigt" oder bei Fehler "fehler"
|
||||||
|
|
||||||
Zentrale JSON-Error-Responses via Flask errorhandler.
|
# Submission-Modell: +ergebnis: dict | None
|
||||||
|
```
|
||||||
|
|
||||||
### Datei: `src/error_handler.py`
|
### Test-Datei: `tests/queue/test_worker_pipeline.py`
|
||||||
|
4 Tests: Suche, Hilfe, Unbekannt, Fehlerfall
|
||||||
|
|
||||||
Handler für 400, 401, 404, 422 (ValidationError), 500.
|
**Commit:** `feat: Worker durchläuft Intake-Pipeline mit Kommando-Erkennung`
|
||||||
Alle Responses im Format: `{"error": "...", "message": "...", "status": N}`
|
|
||||||
|
|
||||||
### Integration: `register_error_handlers(app)` in `create_app()`
|
|
||||||
|
|
||||||
### Test: `tests/test_error_handler.py` — 5 Tests
|
|
||||||
|
|
||||||
**Commit:** `feat: Einheitliche JSON-Error-Responses`
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Aufgabe 18 — systemd Service-Dateien
|
## Aufgabe 24 — Admin-Stats mit echten Daten
|
||||||
|
### Datei: `src/routes/admin.py`
|
||||||
|
```python
|
||||||
|
# queue_status(): +processed_total, +processed_errors, +oldest_pending
|
||||||
|
# stats(): +echte uptime (startzeit in app.config), +version, +error_rate
|
||||||
|
```
|
||||||
|
|
||||||
### Dateien:
|
### Datei: `src/queue/handler.py`
|
||||||
- `deploy/bsn-chatbot.service` — Flask-App als systemd-Service
|
```python
|
||||||
- `deploy/bsn-worker.service` — Queue-Worker als systemd-Service
|
# +processed_total Property
|
||||||
- `deploy/README.md` — Installationsanleitung
|
# +processed_errors Property
|
||||||
|
# +oldest_pending() → datetime | None
|
||||||
|
```
|
||||||
|
|
||||||
### Kein Test nötig (Konfigurationsdateien)
|
### Datei: `src/config.py`
|
||||||
|
```python
|
||||||
|
# VERSION: str = "0.2.0" # In Settings-Klasse
|
||||||
|
```
|
||||||
|
|
||||||
**Commit:** `feat: systemd-Service-Dateien für Chatbot + Queue-Worker`
|
### Test-Datei: `tests/routes/test_admin_stats.py`
|
||||||
|
3 Tests: Metriken, Uptime/Version, Error-Rate
|
||||||
|
|
||||||
|
**Commit:** `feat: Admin-Stats mit Uptime, Error-Rate und Worker-Status`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Aufgabe 19 — Health-Check erweitern
|
## Aufgabe 25 — E2E-Integrationstest
|
||||||
|
### Datei: `tests/integration/test_e2e_whatsapp_pipeline.py`
|
||||||
|
```python
|
||||||
|
# 1. Flask-Test-Client (App-Factory)
|
||||||
|
# 2. WhatsApp-POST → Queue → Worker (eine Submission) → erledigt
|
||||||
|
# 3. Admin-Stats prüfen (processed_total=1)
|
||||||
|
```
|
||||||
|
|
||||||
### Datei: `src/routes/health.py`
|
### Refactoring: `src/queue/worker.py`
|
||||||
|
```python
|
||||||
|
# verarbeite_eine_submission(qh) extrahieren (KEIN Loop)
|
||||||
|
# worker_loop() ruft dann verarbeite_eine_submission() auf
|
||||||
|
```
|
||||||
|
|
||||||
Blueprint mit:
|
3 Tests: Suche-Catan, Hilfe, Admin-Stats nach Verarbeitung
|
||||||
- `GET /health` — Status, queue_size, python_version, platform
|
|
||||||
- `GET /health/ready` — Readiness-Check (Redis-Verbindung)
|
|
||||||
|
|
||||||
### Integration: `app.py`: inline `/health` entfernen, `health_bp` registrieren
|
**Commit:** `test: E2E-Integrationstest WhatsApp→Queue→Worker→Intake`
|
||||||
|
|
||||||
### Test: `tests/test_health.py` — 4 Tests
|
|
||||||
|
|
||||||
**Commit:** `feat: Erweiterter Health-Check mit Readiness-Endpunkt`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Aufgabe 20 — SQLAlchemy-Persistenz
|
|
||||||
|
|
||||||
### Dateien:
|
|
||||||
- `src/database.py` — Engine, Session, Base
|
|
||||||
- `src/models/spiel.py` — SpielDB (SQLAlchemy-Modell)
|
|
||||||
- `src/services/game_service.py` — Umbau auf DB-Sessions
|
|
||||||
|
|
||||||
### Test: `tests/test_database.py` — 5 Tests
|
|
||||||
|
|
||||||
**Commit:** `feat: SQLAlchemy-Datenbank mit SQLite-Persistenz`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚠️ Wichtig
|
|
||||||
|
|
||||||
- `pip install pydantic-settings sqlalchemy`
|
|
||||||
- **Qualität:** `ruff check . && ruff format . && mypy --config-file pyproject.toml . && pytest -v`
|
|
||||||
- **Reihenfolge:** 16 → 17 → 18 → 19 → 20
|
|
||||||
|
|||||||
Reference in New Issue
Block a user