1 Commits

Author SHA1 Message Date
Hitonabi 46a8f50c34 fix(api): remount nicht-blockierend (Netz-Mount darf API-Start nicht haengen)
Ampel / ampel (push) Successful in 28s
Vorfall 24.07.: Beim API-Start blockierte der synchrone CIFS-Schreibtest in
alle_remounten()/mounten() im Kernel (wait_for_response), als der SMB-Server
langsam war -> ~5 min "Waiting for application startup", kein Endpoint bedient
(bis der soft-Mount per Timeout abbrach). startup_event() lief isoliert sauber,
also war es der blockierende Netz-Mount, nicht die App-Logik.

Fix: remount als Hintergrund-Task (asyncio.create_task) statt await -> die API
kommt sofort hoch, die Mounts stellen sich her sobald der Server antwortet.
Test (test_api_smoke.py): haelt den Nicht-blockierend-Vertrag per Quelltext-
Inspektion fest, im Stil der anderen Verdrahtungs-Tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 21:50:32 +02:00
2 changed files with 22 additions and 2 deletions
+7 -2
View File
@@ -47,11 +47,16 @@ async def startup_event():
except ConfigValidationError as e:
print(f"⚠️ Konfigurations-Warnung: {e}")
# Gespeicherte Netzwerk-Speicherziele wiederherstellen
# Gespeicherte Netzwerk-Speicherziele wiederherstellen — NICHT-BLOCKIEREND.
# Ein zickiger/langsamer Netz-Mount (der CIFS-Schreibtest in mounten() kann im
# Kernel haengen, wait_for_response) darf den API-Start NIE blockieren. Vorfall
# 24.07.: ~5 min "Waiting for application startup", kein Endpoint bedient, bis der
# soft-Mount per Timeout abbrach. Darum im Hintergrund: die Mounts stellen sich
# her, sobald der Server antwortet, ohne die API auszubremsen.
def remount():
for meldung in mount_verwaltung.alle_remounten():
db.add_log("info", "mounts", meldung)
await asyncio.to_thread(remount)
asyncio.create_task(asyncio.to_thread(remount))
asyncio.create_task(disc_watcher())
# MakeMKV-Beta-Key automatisch aktuell halten (wechselt ~monatlich, laeuft zum
+15
View File
@@ -42,3 +42,18 @@ def test_worker_task_name_passt_zum_celery_client():
quelle = inspect.getsource(celery_client.start_rip)
assert '"worker.tasks.rip_disc"' in quelle
def test_remount_blockiert_den_api_start_nicht():
"""Regression (Vorfall 24.07.): ein haengender Netz-Mount (CIFS-Schreibtest kann
im Kernel haengen, wait_for_response) darf den API-Start NICHT blockieren. remount
muss als Hintergrund-Task laufen (create_task), nicht direkt awaited werden."""
import inspect
import main
quelle = inspect.getsource(main.startup_event)
assert "create_task(asyncio.to_thread(remount))" in quelle, \
"remount muss als Hintergrund-Task laufen (nicht blockierend)"
assert "await asyncio.to_thread(remount)" not in quelle, \
"remount darf nicht mehr direkt awaited werden (blockiert sonst den Start)"