fix(windows): Dauerscan der Disc, aufblitzende Fenster, Docker-Einstellung uebernommen
Ampel / ampel (push) Successful in 1m30s
Ampel / ampel (push) Successful in 1m30s
Commander: „liest er die disc NOCHMAL ein das macht aber keinen sinn, wenn er
sie bereits erkannt hat. Außerdem öffnen sich nun immer irgendwelche fenster
ganz kurz im hintergrund."
## Beides war dieselbe Schleife
In der Disc-Wache stand:
except OSError:
continue
Damit blieb `bekannt[pfad]` ungesetzt, und im naechsten Durchlauf war
`vorher is None` — also wieder „Erststart, liegt schon eine Disc drin". **Ein
einziger fehlgeschlagener Lesevorgang loeste einen neuen Vor-Scan aus.**
Und der scheitert regelmaessig: Waehrend der Vor-Scan laeuft, haelt
makemkvcon das Laufwerk (gemessen: /devices braucht dann 14 s statt 5). Also
Scan haelt das Laufwerk -> Statusabfrage scheitert -> naechster Durchlauf
haelt es fuer den ersten -> neuer Scan. Eine Schleife, die sich selbst am
Leben haelt.
Und weil derselbe makemkvcon-Aufruf in `prescan.py` als EINZIGER kein
`creationflags=OHNE_FENSTER` hatte, blitzte bei jeder Runde eine Konsole auf.
Das war meine Zeile von heute Vormittag.
Die Entscheidung steckt jetzt in `disc_entscheidung()` — pure Funktion, also
ohne Laufwerk pruefbar. Zwei getrennte Fragen statt einer: Haben wir dieses
Laufwerk je gelesen, und was war zuletzt drin? Ein Fehlschlag beantwortet die
zweite nicht und darf die erste nicht zuruecksetzen.
Nachgemessen: Ein Tabwechsel loest KEINEN neuen Scan aus (8 Erkennungen
vorher, 8 nachher). Meine erste Zaehlung von „7 vs 8" war ein Messfehler —
zwei verschieden grosse Abfragefenster.
## Aus dem Docker-Betrieb uebernommen
`docker/worker/entrypoint.sh` setzt vor jedem Worker-Start zwei Dinge:
`app_Key` und `app_UpdateEnable`. Der Key war schon uebernommen, die zweite
nicht — auf dem Rechner des Commanders nachgesehen: NICHT gesetzt.
Das ist MakeMKVs Web-Kontakt; darueber holt es die Disc-Schluessel fuer
4K-UHD nach (Meldung 3338, auf Windows gemessen). „Fuer Windows umschreiben"
heisst hier: Registry statt settings.conf, DWORD statt Text — die
Nachbarwerte (`app_BackupDecrypted`) zeigen die Form.
Gesetzt wird NUR, was fehlt: Wer den Web-Kontakt bewusst abgeschaltet hat,
behaelt ihn abgeschaltet. Ein Waechter-Test vergleicht kuenftig die
`app_*`-Namen aus der entrypoint.sh gegen die Windows-Seite — sonst driften
die beiden Betriebe auseinander.
871 Tests gruen, ruff sauber.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
f0d39b4d04
commit
aeb3128a85
+77
-12
@@ -268,6 +268,51 @@ async def _auto_rip_wenn_aktiviert(pfad: str):
|
||||
start_rip(pfad, job_id, ziel)
|
||||
|
||||
|
||||
def disc_entscheidung(schon_gesehen: bool, vorher, status) -> str:
|
||||
"""Was ist zu tun? `""` | `"erststart"` | `"eingelegt"` | `"entfernt"`.
|
||||
|
||||
Pure Funktion — deshalb ohne Laufwerk prüfbar, und genau daran hing der
|
||||
Fehler unten.
|
||||
|
||||
## Der Befund des Commanders (29.08.2026)
|
||||
|
||||
> „liest er die disc NOCHMAL ein das macht aber keinen sinn, wenn er sie
|
||||
> bereits erkannt hat. Außerdem öffnen sich nun immer irgendwelche fenster
|
||||
> ganz kurz im hintergrund."
|
||||
|
||||
Beides war dieselbe Schleife. In der Disc-Wache stand:
|
||||
|
||||
except OSError:
|
||||
continue
|
||||
|
||||
Damit blieb `bekannt[pfad]` ungesetzt, und im nächsten Durchlauf war
|
||||
`vorher is None` — also wieder „Erststart, liegt schon eine Disc drin".
|
||||
**Ein einziger fehlgeschlagener Lesevorgang löste einen neuen Vor-Scan
|
||||
aus.**
|
||||
|
||||
Und der scheitert regelmäßig: Während der Vor-Scan läuft, hält
|
||||
`makemkvcon` das Laufwerk (gemessen: `/devices` braucht dann 14 s statt
|
||||
5). Also: Scan hält das Laufwerk → Statusabfrage scheitert → nächster
|
||||
Durchlauf hält es für den ersten → neuer Scan. Eine Schleife, die sich
|
||||
selbst am Leben hält — und weil derselbe Aufruf sein Konsolenfenster
|
||||
nicht unterdrückte, blitzte bei jeder Runde eines auf.
|
||||
|
||||
Deshalb zwei getrennte Fragen statt einer: **Haben wir dieses Laufwerk je
|
||||
gelesen?** (`schon_gesehen`) und **was war zuletzt drin?** (`vorher`). Ein
|
||||
Fehlschlag beantwortet die zweite nicht — und darf die erste nicht
|
||||
zurücksetzen.
|
||||
"""
|
||||
if not schon_gesehen:
|
||||
return "erststart" if status == CDS_DISC_OK else ""
|
||||
if status == vorher:
|
||||
return ""
|
||||
if status == CDS_DISC_OK:
|
||||
return "eingelegt"
|
||||
if status in (CDS_NO_DISC, CDS_TRAY_OPEN) and vorher == CDS_DISC_OK:
|
||||
return "entfernt"
|
||||
return ""
|
||||
|
||||
|
||||
async def disc_watcher():
|
||||
"""Disc-Wache: pollt die Laufwerke, protokolliert Einwurf/Auswurf und
|
||||
stößt beim Einlegen automatisch den Pre-Scan an (Dashboard-Disc-Karte).
|
||||
@@ -277,25 +322,45 @@ async def disc_watcher():
|
||||
für den Heim-Use-Case gleichwertig und läuft überall.
|
||||
"""
|
||||
bekannt: Dict[str, int] = {}
|
||||
# Laufwerke, die schon einmal ERFOLGREICH gelesen wurden. Getrennt von
|
||||
# `bekannt`, weil ein fehlgeschlagener Lesevorgang sonst wie ein
|
||||
# Erststart aussieht — siehe unten.
|
||||
gesehen: set = set()
|
||||
while True:
|
||||
try:
|
||||
for pfad in device_discovery.list_optical_devices():
|
||||
try:
|
||||
status = await asyncio.to_thread(drive_status, pfad)
|
||||
except OSError:
|
||||
# ⚠️ Hier stand nur `continue` (Befund 29.08.2026).
|
||||
#
|
||||
# `bekannt[pfad]` blieb damit ungesetzt, und beim nächsten
|
||||
# Durchlauf war `vorher is None` — also wieder „Erststart,
|
||||
# liegt schon eine Disc drin". Ein einziger fehlgeschlagener
|
||||
# Lesevorgang bewirkte einen NEUEN Vor-Scan.
|
||||
#
|
||||
# Und genau das passiert regelmäßig: Während der Vor-Scan
|
||||
# läuft, hält `makemkvcon` das Laufwerk, und die
|
||||
# Statusabfrage kommt nicht durch. Ergebnis: Scan hält das
|
||||
# Laufwerk → Statusabfrage scheitert → nächster Durchlauf
|
||||
# hält es für den ersten → neuer Scan. Eine Schleife, die
|
||||
# sich selbst am Leben hält, und bei jeder Runde blitzte
|
||||
# eine Konsole auf.
|
||||
#
|
||||
# `gesehen` merkt sich, ob wir dieses Laufwerk je gelesen
|
||||
# haben. Ein Fehlschlag heißt jetzt „nichts Neues erfahren"
|
||||
# — nicht „zum ersten Mal gesehen".
|
||||
continue
|
||||
vorher = bekannt.get(pfad)
|
||||
if vorher is None:
|
||||
# Erststart: liegt schon eine Disc drin, direkt erkennen
|
||||
if status == CDS_DISC_OK:
|
||||
asyncio.create_task(_auto_prescan(pfad))
|
||||
elif status != vorher:
|
||||
if status == CDS_DISC_OK:
|
||||
db.add_log("info", "watcher", f"Disc eingelegt: {pfad}")
|
||||
asyncio.create_task(_auto_prescan(pfad))
|
||||
elif status in (CDS_NO_DISC, CDS_TRAY_OPEN) and vorher == CDS_DISC_OK:
|
||||
db.add_log("info", "watcher", f"Disc entfernt: {pfad}")
|
||||
DISC_CACHE.pop(pfad, None)
|
||||
was = disc_entscheidung(pfad in gesehen, bekannt.get(pfad), status)
|
||||
gesehen.add(pfad)
|
||||
if was == "erststart":
|
||||
asyncio.create_task(_auto_prescan(pfad))
|
||||
elif was == "eingelegt":
|
||||
db.add_log("info", "watcher", f"Disc eingelegt: {pfad}")
|
||||
asyncio.create_task(_auto_prescan(pfad))
|
||||
elif was == "entfernt":
|
||||
db.add_log("info", "watcher", f"Disc entfernt: {pfad}")
|
||||
DISC_CACHE.pop(pfad, None)
|
||||
bekannt[pfad] = status
|
||||
except Exception as e:
|
||||
print(f"Disc-Wache: {e}")
|
||||
|
||||
Reference in New Issue
Block a user