232 lines
5.9 KiB
Markdown
232 lines
5.9 KiB
Markdown
# Backend-Services
|
||
|
||
Das Backend ist in Node.js/Express geschrieben und in **Services** aufgeteilt, die jeweils eine klar abgegrenzte Verantwortlichkeit haben.
|
||
|
||
---
|
||
|
||
## pipelineService.js
|
||
|
||
**Der Kern von Ripster** – orchestriert den gesamten Ripping-Workflow.
|
||
|
||
### Zuständigkeiten
|
||
|
||
- Verwaltung des Pipeline-Zustands als State Machine
|
||
- Koordination zwischen allen externen Tools
|
||
- Generierung von Encode-Plänen
|
||
- Fehlerbehandlung und Recovery
|
||
|
||
### Haupt-Methoden
|
||
|
||
| Methode | Beschreibung |
|
||
|---------|-------------|
|
||
| `analyzeDisc()` | Startet MakeMKV-Analyse der eingelegten Disc |
|
||
| `selectMetadata(jobId, omdbData, playlist)` | Setzt Metadaten und Playlist für einen Job |
|
||
| `startJob(jobId)` | Startet den Ripping-Prozess |
|
||
| `confirmEncode(jobId, trackSelection)` | Bestätigt Encode mit Track-Auswahl |
|
||
| `cancelPipeline()` | Bricht aktiven Prozess ab |
|
||
| `retryJob(jobId)` | Wiederholt fehlgeschlagenen Job |
|
||
| `reencodeJob(jobId)` | Encodiert bestehende Raw-MKV neu |
|
||
|
||
### Zustandsübergänge
|
||
|
||
<div class="pipeline-diagram">
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
START(( )) --> IDLE
|
||
IDLE -->|analyzeDisc()| ANALYZING[ANALYZING]
|
||
ANALYZING -->|MakeMKV fertig| META[METADATA\nSELECTION]
|
||
META -->|selectMetadata()| RTS[READY_TO\nSTART]
|
||
RTS -->|startJob()| RIP[RIPPING]
|
||
RIP -->|MKV erstellt| MIC[MEDIAINFO\nCHECK]
|
||
MIC -->|Tracks analysiert| RTE[READY_TO\nENCODE]
|
||
RTE -->|confirmEncode()| ENC[ENCODING]
|
||
ENC -->|HandBrake fertig| FIN([FINISHED])
|
||
ENC -->|Fehler| ERR([ERROR])
|
||
RIP -->|Fehler| ERR
|
||
ERR -->|retryJob() / cancel| IDLE
|
||
FIN -->|cancel / neue Disc| IDLE
|
||
|
||
style FIN fill:#e8f5e9,stroke:#66bb6a,color:#2e7d32
|
||
style ERR fill:#ffebee,stroke:#ef5350,color:#c62828
|
||
style ENC fill:#f3e5f5,stroke:#ab47bc,color:#6a1b9a
|
||
style RIP fill:#e3f2fd,stroke:#42a5f5,color:#1565c0
|
||
style MIC fill:#e3f2fd,stroke:#42a5f5,color:#1565c0
|
||
```
|
||
|
||
</div>
|
||
|
||
---
|
||
|
||
## diskDetectionService.js
|
||
|
||
Überwacht das Disc-Laufwerk auf Disc-Einleger- und Auswurf-Ereignisse.
|
||
|
||
### Modi
|
||
|
||
| Modus | Beschreibung |
|
||
|------|-------------|
|
||
| `auto` | Erkennt verfügbare Laufwerke automatisch |
|
||
| `explicit` | Überwacht ein bestimmtes Gerät (z.B. `/dev/sr0`) |
|
||
|
||
### Polling
|
||
|
||
Der Service pollt das Laufwerk im konfigurierten Intervall (`disc_poll_interval_ms`, Standard: 5000ms) und emittiert Events:
|
||
|
||
```js
|
||
// Ereignisse
|
||
emit('disc-detected', { device: '/dev/sr0' })
|
||
emit('disc-removed', { device: '/dev/sr0' })
|
||
```
|
||
|
||
---
|
||
|
||
## processRunner.js
|
||
|
||
Verwaltet externe CLI-Prozesse.
|
||
|
||
### Features
|
||
|
||
- **Streaming**: stdout/stderr werden zeilenweise gelesen
|
||
- **Progress-Callbacks**: Ermöglicht Echtzeit-Fortschrittsanzeige
|
||
- **Graceful Shutdown**: SIGINT → Warte-Timeout → SIGKILL
|
||
- **Prozess-Registry**: Verfolgt aktive Prozesse für sauberes Beenden
|
||
|
||
### Nutzung
|
||
|
||
```js
|
||
const result = await runProcess(
|
||
'HandBrakeCLI',
|
||
['--input', rawFile, '--output', outputFile, '--preset', preset],
|
||
{
|
||
onStderr: (line) => parseHandBrakeProgress(line),
|
||
onStdout: (line) => logger.debug(line)
|
||
}
|
||
);
|
||
```
|
||
|
||
---
|
||
|
||
## websocketService.js
|
||
|
||
WebSocket-Server für Echtzeit-Client-Kommunikation.
|
||
|
||
### Betrieb
|
||
|
||
- Läuft auf Pfad `/ws` des Express-Servers
|
||
- Hält eine Registry aller verbundenen Clients
|
||
- Ermöglicht Broadcast an alle Clients oder gezieltes Senden
|
||
|
||
### API
|
||
|
||
```js
|
||
broadcast({ type: 'PIPELINE_STATE_CHANGE', data: { state, jobId } });
|
||
broadcast({ type: 'PROGRESS_UPDATE', data: { progress, eta } });
|
||
```
|
||
|
||
---
|
||
|
||
## omdbService.js
|
||
|
||
Integration mit der [OMDb API](https://www.omdbapi.com/).
|
||
|
||
### Methoden
|
||
|
||
| Methode | Beschreibung |
|
||
|---------|-------------|
|
||
| `searchByTitle(title, type)` | Suche nach Titel (movie/series) |
|
||
| `fetchById(imdbId)` | Vollständige Metadaten per IMDb-ID |
|
||
|
||
### Zurückgegebene Daten
|
||
|
||
```json
|
||
{
|
||
"imdbId": "tt1375666",
|
||
"title": "Inception",
|
||
"year": "2010",
|
||
"type": "movie",
|
||
"poster": "https://...",
|
||
"plot": "...",
|
||
"director": "Christopher Nolan"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## settingsService.js
|
||
|
||
Verwaltet alle Anwendungseinstellungen.
|
||
|
||
### Features
|
||
|
||
- **Schema-getriebene Validierung**: Jede Einstellung hat Typ, Grenzen und Pflichtfeld-Flag
|
||
- **Kategorisierung**: Einstellungen sind in Kategorien gruppiert (Paths, Tools, Encoding, ...)
|
||
- **Persistenz**: Werte in SQLite, Schema ebenfalls in SQLite
|
||
- **Defaults**: `defaultSettings.js` definiert Standardwerte
|
||
|
||
### Einstellungs-Kategorien
|
||
|
||
| Kategorie | Einstellungen |
|
||
|-----------|--------------|
|
||
| `paths` | `raw_dir`, `movie_dir`, `log_dir` |
|
||
| `tools` | `makemkv_command`, `handbrake_command`, `mediainfo_command` |
|
||
| `encoding` | `handbrake_preset`, `handbrake_extra_args`, `output_extension`, `filename_template` |
|
||
| `drive` | `drive_mode`, `drive_device`, `disc_poll_interval_ms` |
|
||
| `makemkv` | `makemkv_min_length_minutes`, `makemkv_backup_mode` |
|
||
| `omdb` | `omdb_api_key`, `omdb_default_type` |
|
||
| `notifications` | `pushover_user_key`, `pushover_api_token` |
|
||
|
||
---
|
||
|
||
## historyService.js
|
||
|
||
Datenbankoperationen für Job-Historie.
|
||
|
||
### Hauptoperationen
|
||
|
||
| Operation | Beschreibung |
|
||
|-----------|-------------|
|
||
| `listJobs(filters)` | Jobs nach Status/Titel filtern |
|
||
| `getJob(id)` | Job-Details mit Logs abrufen |
|
||
| `findOrphanRawFolders()` | Nicht-getrackte Raw-Ordner finden |
|
||
| `importOrphanRaw(path)` | Orphan-Ordner als Job importieren |
|
||
| `assignOmdb(id, omdbData)` | OMDb-Metadaten nachträglich zuweisen |
|
||
| `deleteJob(id, deleteFiles)` | Job und optional Dateien löschen |
|
||
|
||
---
|
||
|
||
## notificationService.js
|
||
|
||
PushOver-Push-Benachrichtigungen.
|
||
|
||
```js
|
||
await notify({
|
||
title: 'Ripster: Job abgeschlossen',
|
||
message: 'Inception (2010) wurde erfolgreich encodiert'
|
||
});
|
||
```
|
||
|
||
---
|
||
|
||
## logger.js
|
||
|
||
Strukturiertes Logging mit täglicher Log-Rotation.
|
||
|
||
### Log-Level
|
||
|
||
| Level | Verwendung |
|
||
|-------|-----------|
|
||
| `debug` | Detaillierte Entwicklungs-Informationen |
|
||
| `info` | Normale Betriebsereignisse |
|
||
| `warn` | Warnungen, die Aufmerksamkeit benötigen |
|
||
| `error` | Fehler, die den Betrieb beeinträchtigen |
|
||
|
||
### Log-Dateien
|
||
|
||
```
|
||
logs/
|
||
├── ripster-2024-01-15.log ← Tages-Log
|
||
└── jobs/
|
||
└── job-42-handbrake.log ← Prozess-spezifische Logs
|
||
```
|