Files
ripster/docs/architecture/overview.md

145 lines
3.7 KiB
Markdown

# Architektur-Übersicht
---
## Kern-Designprinzipien
### Event-Driven Pipeline
Der gesamte Ripping-Workflow ist als **State Machine** implementiert. Der `pipelineService` verwaltet den aktuellen Zustand und emittiert Ereignisse bei jedem Zustandswechsel. Der WebSocket-Service überträgt diese Ereignisse sofort an alle verbundenen Clients.
```
Zustandswechsel → Event → WebSocket → Frontend-Update
```
### Service-Layer-Muster
```
HTTP-Route → Service → Datenbank
```
Routes delegieren die gesamte Business-Logik an Services. Services sind voneinander unabhängig und können einzeln getestet werden.
### Schema-getriebene Einstellungen
Die Settings-Konfiguration definiert **sowohl** die Validierungsregeln als auch die UI-Struktur in einer einzigen Quelle (`settings_schema`-Tabelle). Die `DynamicSettingsForm`-Komponente rendert das Formular dynamisch aus dem Schema.
---
## Echtzeit-Kommunikation
### WebSocket-Protokoll
Der WebSocket-Server läuft unter dem Pfad `/ws`. Nachrichten werden als JSON übertragen:
```json
{
"type": "PIPELINE_STATE_CHANGE",
"data": {
"state": "ENCODING",
"jobId": 42,
"progress": 73.5,
"eta": "00:12:34"
}
}
```
**Nachrichtentypen:**
| Typ | Beschreibung |
|----|-------------|
| `PIPELINE_STATE_CHANGE` | Pipeline-Zustand hat gewechselt |
| `PROGRESS_UPDATE` | Fortschritt (% und ETA) |
| `DISC_DETECTED` | Disc wurde erkannt |
| `DISC_REMOVED` | Disc wurde entfernt |
| `ERROR` | Fehler aufgetreten |
| `JOB_COMPLETE` | Job abgeschlossen |
### Reconnect-Logik
Der Frontend-Hook `useWebSocket.js` implementiert automatisches Reconnect mit exponential backoff bei Verbindungsabbrüchen.
---
## Prozess-Management
### processRunner.js
Externe Tools (MakeMKV, HandBrake, MediaInfo) werden als **Child Processes** gestartet:
```js
spawn(command, args, { stdio: ['ignore', 'pipe', 'pipe'] })
```
- **stdout/stderr** werden zeilenweise gelesen und in Echtzeit verarbeitet
- **Progress-Parsing** erfolgt über reguläre Ausdrücke in `progressParsers.js`
- **Graceful Shutdown**: SIGINT → Timeout → SIGKILL
- **Prozess-Tracking**: Aktive Prozesse werden registriert für sauberes Beenden
---
## Datenpersistenz
### SQLite-Datenbank
Ripster verwendet eine **einzige SQLite-Datei** für alle persistenten Daten:
```
backend/data/ripster.db
```
**Tabellen:**
| Tabelle | Inhalt |
|---------|--------|
| `jobs` | Alle Rip-Jobs mit Status, Logs, Metadaten |
| `pipeline_state` | Aktueller Pipeline-Zustand (Singleton) |
| `settings_schema` | Schema aller verfügbaren Einstellungen |
| `settings_values` | Benutzer-konfigurierte Werte |
### Migrations-Strategie
Beim Start prüft `database.js` automatisch, ob das Schema aktuell ist, und führt fehlende Migrationen aus. Korrupte Datenbankdateien werden in ein Quarantäne-Verzeichnis verschoben und eine neue Datenbank erstellt.
---
## Fehlerbehandlung
### Strukturierte Fehler
Alle Fehler werden mit Kontext-Metadaten protokolliert:
```js
logger.error('Encoding fehlgeschlagen', {
jobId: job.id,
command: cmd,
exitCode: code,
stderr: lastLines
});
```
### Job-Fehler-Recovery
- Fehlgeschlagene Jobs bleiben in der Datenbank (Status `ERROR`)
- Vollständige Fehler-Logs werden im Job-Datensatz gespeichert
- **Retry-Funktion** ermöglicht Neustart von einem Fehler-Zustand
- **Re-Encode** erlaubt erneutes Encodieren ohne neu zu rippen
---
## Sicherheit
### Eingabe-Validierung
- Alle Benutzer-Eingaben werden in `validators.js` validiert
- CLI-Argumente werden sicher über `commandLine.js` konstruiert (kein Shell-Injection-Risiko)
- Pfade werden sanitisiert bevor sie an externe Prozesse übergeben werden
### CORS-Konfiguration
```env
CORS_ORIGIN=http://localhost:5173
```
In Produktion sollte dieser Wert auf die tatsächliche Frontend-URL gesetzt werden.