# Übersicht - Ripster
Halbautomatische Disc-Ripping-Plattform für DVDs & Blu-rays mit HandBrake-Encoding
Author: Michael

Zum Inhalt

# 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:

    {
      "type": "PIPELINE_STATE_CHANGED",
      "payload": {
        "state": "ENCODING",
        "activeJobId": 42,
        "progress": 73.5,
        "eta": "00:12:34"
      }
    }

Nachrichtentypen:

Typ | Beschreibung
--- | ---
`PIPELINE_STATE_CHANGED` | Pipeline-Zustand hat gewechselt
`PIPELINE_PROGRESS` | Fortschritt (% und ETA)
`PIPELINE_QUEUE_CHANGED` | Queue-Status geändert
`DISC_DETECTED` | Disc wurde erkannt
`DISC_REMOVED` | Disc wurde entfernt
`PIPELINE_ERROR` | Pipeline-Fehler aufgetreten
`DISK_DETECTION_ERROR` | Laufwerkserkennung-Fehler

### Reconnect-Logik

Der Frontend-Hook `useWebSocket.js` implementiert automatisches Reconnect mit festem Intervall von 1500ms bei Verbindungsabbrüchen.

## Prozess-Management

### processRunner.js

Externe Tools (MakeMKV, HandBrake, MediaInfo) werden als Child Processes gestartet:

    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:

    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

    CORS_ORIGIN=http://localhost:5173

In Produktion sollte dieser Wert auf die tatsächliche Frontend-URL gesetzt werden.