WAS: Eine 28,6-MB-Datei, drei Betriebsarten. Doppelklick installiert,
`--dienst` laeuft im Hintergrund, `--deinstallieren` raeumt sich weg.
Dazu packaging/windows/build.py, das sie baut.
DIE ZWEI COMMANDER-WUENSCHE, GEMESSEN:
1. EINTRAG IM TASKMANAGER
ProcessName Rippy
Beschreibung Rippy — automatisches Ripping
Produkt Rippy
Version 2.0.0
Der Prozessname kommt vom Dateinamen (bei der Installation kopiert sich
die Datei als Rippy.exe), die Beschreibung aus einer eingebetteten
Versions-Ressource. Ohne die steht dort nichts, und Windows SmartScreen
sieht eine EXE ohne Herausgeberangabe genauso misstrauisch wie ein Mensch.
2. EINTRAG IN PROGRAMME UND FEATURES
Aus der Registry zurueckgelesen, nicht behauptet:
DisplayName Rippy
DisplayVersion 2.0.0
Publisher Rippy
InstallLocation <Zielordner>
UninstallString "<pfad>\Rippy.exe" --deinstallieren
EstimatedSize 29241 (KiB)
NoModify/NoRepair 1
HKCU statt HKLM: Der Eintrag erscheint genauso in "Apps & Features", die
Installation laeuft aber ohne UAC-Abfrage durch.
VOLLER KREISLAUF GEMESSEN: installieren -> Rippy.exe + rippy.ico liegen da,
Registry-Eintrag da, Autostart da; Dienst starten -> nach 1 s bereit, alle
sieben Endpunkte HTTP 200, Oberflaeche kommt; deinstallieren -> nach ~4 s
sind Datei, Ordner, Registry-Eintrag, Autostart UND das Aufraeum-Skript weg.
VIER FEHLER, DIE NUR DIE FERTIGE EXE ZEIGT:
1. rippy/store baute die Engine BEIM IMPORT, mit PostgreSQL als Vorgabe.
Im Windows-Paket gibt es psycopg2 bewusst nicht -> die EXE starb sofort.
Die Engine entsteht jetzt beim ersten Zugriff. Und der Fehler war
grundsaetzlicher als der fehlende Treiber: Ein Modul, das beim Import
schon eine Verbindung aufbaut, laesst sich gar nicht mehr umstellen —
store.verbinden() kaeme immer zu spaet.
2. celery_client baute den Broker-Client beim Import. Dasselbe Muster, und
`from celery_client import celery_client` loeste es sogar dann aus, wenn
nie ein Rip angestossen wird. Jetzt traege, mit KeinBroker als klarer
Ansage statt eines Importfehlers.
3. Die Selbstloeschung beim Deinstallieren ging als EIN Argument an cmd.
Python maskiert dabei die inneren Anfuehrungszeichen — cmd suchte einen
Dateinamen mit Backslashes davor, fand nichts und meldete nichts (>nul).
Registry und Autostart waren weg, die 28-MB-Datei blieb liegen: ein still
scheiternder Hintergrundprozess, wie ihn AGENTS.md beschreibt. Jetzt ein
Aufraeum-Skript, das 15-mal versucht (die Onefile-EXE laeuft als ZWEI
Prozesse; der Starter haelt die Datei nach dem Ende noch offen).
4. deinstallieren() raeumte den STANDARD-Ordner auf statt des tatsaechlichen.
Wer nach --ziel D:\Rippy installiert hatte, dessen Dateien waeren
geblieben, waehrend ein fremder Ordner angefasst worden waere. Der Pfad
steht in der Registry (InstallLocation) und wird jetzt dort gelesen.
WAS NOCH NICHT GEHT, ausdruecklich: Ein RIP laesst sich unter Windows noch
nicht anstossen — die Zustellung laeuft weiter ueber Celery. Die Umstellung
auf die LocalQueue ist V2-5. Oberflaeche, Laufwerks-Erkennung, Auswurf und
alles Lesende laufen.
GEMESSEN: ruff sauber, 456 Tests gruen + 15 uebersprungen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1) Speicher-Mounts robust (Befund: toter CIFS-Mount nach NAS-Ausfall/Rebuild —
mounted:false, verschwand aus 'Verfuegbare Ziele', Neu-Anlegen -> 409, man
sass fest):
- mounts.py: ist_erreichbar() (listdir, soft-Mount bricht schnell ab),
ist_gemountet() faengt OSError toter Mounts, aushaengen() mit
umount -l Fallback, reparieren() (lazy abhaengen + frisch mounten).
- /storage-mounts liefert 'reachable'; POST bei existierendem Namen:
aktiv -> 409, tot -> automatische Reparatur mit neuen Angaben;
neuer POST /storage-mounts/{name}/repair (gespeicherte Zugangsdaten).
- /storage-targets crasht nicht mehr an totem Mount (os.path.ismount
OSError abgefangen).
- UI: eigene 'Netzwerk-Mounts'-Liste mit Status (aktiv/nicht erreichbar/
getrennt) + Reparieren- und Entfernen-Knopf — tote Mounts sind sichtbar
und wiederherstellbar statt zu verschwinden.
2) HandBrake-Versionen konsistent (Befund: Docker 1.6.1, Windows-Skript
fest 1.9.2, Update-Check meldet 1.11.2 — verwirrend):
- Windows-Installer zieht jetzt DYNAMISCH die neueste Version (GitHub
latest, Fallback 1.11.2) — passt zum Update-Check.
- Update-UI erklaert klar: Docker = stabiles Debian-Paket (bewusst aelter,
kein Fehler), Windows = neueste. MakeMKV-Update zeigt den Befehl.
3) Encoder-/Worker-Auswahl beim Rip (Feature):
- Celery worker_direct=True: jeder Worker konsumiert zusaetzlich seine
Direkt-Queue. API-Helper transcode_queue(node) routet gezielt an den
gewaehlten Worker, faellt aber sicher auf die geteilte transcode-Queue
zurueck, wenn er offline ist (kein Haengenbleiben).
- /capabilities liefert den Celery-Node je Worker; POST /jobs nimmt
transcode_node (-> Job-meta); rip_disc + retry-transcode routen danach.
- Rip-Dialog: Encoder-/Worker-Dropdown, sichtbar ab 2 Online-Workern.
- ping_worker-Task zum Verifizieren des gezielten Routings.
- Nebenfund gefixt: DeviceDiscovery leitete die Titel-Auswahl (titles)
gar nicht an die API weiter — jetzt titles + transcode_node.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- POST /jobs nimmt target_dir (validiert unter /app/media, .. fliegt raus)
- GET /storage-targets: Verzeichnisse unter /app/media inkl. Mount-Flag
und freiem Platz — NFS/SMB-Shares unter /srv/rippy/media erscheinen
dank rslave-Bind automatisch
- jobs.target_dir (Mini-Migration via ADD COLUMN IF NOT EXISTS)
- Worker: rip_disc(target_dir) mit eigener Validierung; CD/Video/
Transcode-Pfade legen im gewaehlten Ziel ab
- UI: "Rippen starten" oeffnet den Ziel-Dialog (Filme/Serien/Musik oder
eigener Pfad); Modal-Bugfix: customPath wurde still ignoriert
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Vorher gab es KEINEN Code-Pfad, der je einen Rip ausgelöst hat: kein
POST /jobs, kein udev-Daemon (udev_daemon.py existierte nirgends), GET /jobs
gab hart [] zurück, Postgres lag komplett brach, der SSE-Stream konnte
strukturell nie senden (sse_connections wurde nie befüllt), udevadm lieferte
ohne udevd nichts.
- POST /jobs: legt Job-Zeile an, schickt worker.tasks.rip_disc via Celery
- GET /jobs aus Postgres (running→processing fürs UI)
- Disc-Watcher: 3s-ioctl-Poll statt udev, protokolliert Einwurf/Auswurf
- /devices über /sys (vendor/model) + ioctl-Status — ehrlich statt leer
- /logs + /settings (Settings-Seite sprach vorher gegen 404)
- SSE-Fix, udev aus dem API-Image entfernt, Import-Smoke-Test
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>