Resilience : ecran pause, reconnexion WS auto, watchdog systemd, WiFi monitor
- WebSocket : reconnexion avec backoff exponentiel au lieu de reload page - Ecran pause avec tasse de cafe quand le backend est injoignable - Endpoint /api/health pour monitoring externe - Watchdog systemd (sd_notify READY=1 + WATCHDOG=1 toutes les 10s) - Service systemd durci (Type=notify, WatchdogSec=30, KillMode, limites) - WiFi watchdog : script + timer systemd, verifie la gateway toutes les 60s - Destinations : fallback url_tunnel (WireGuard) en priorite Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@ import asyncio
|
||||
import base64
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import threading
|
||||
import time
|
||||
from pathlib import Path
|
||||
@@ -273,6 +274,24 @@ def _appliquer_config_camera():
|
||||
camera.configurer_flash(flash_integre)
|
||||
|
||||
|
||||
async def _watchdog_systemd():
|
||||
"""Notifie systemd que le service est vivant + surveille la santé."""
|
||||
try:
|
||||
import socket
|
||||
addr = os.environ.get("NOTIFY_SOCKET")
|
||||
if not addr:
|
||||
return
|
||||
sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
|
||||
if addr[0] == "@":
|
||||
addr = "\0" + addr[1:]
|
||||
sock.sendto(b"READY=1", addr)
|
||||
while True:
|
||||
await asyncio.sleep(10)
|
||||
sock.sendto(b"WATCHDOG=1", addr)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
"""Demarrage et arret de l'application."""
|
||||
@@ -287,10 +306,12 @@ async def lifespan(app: FastAPI):
|
||||
task_dslr = asyncio.create_task(surveiller_dslr())
|
||||
task_push = asyncio.create_task(_pusher_preview())
|
||||
task_spool = asyncio.create_task(tache_spool_demarrage())
|
||||
task_watchdog = asyncio.create_task(_watchdog_systemd())
|
||||
yield
|
||||
task_dslr.cancel()
|
||||
task_push.cancel()
|
||||
task_spool.cancel()
|
||||
task_watchdog.cancel()
|
||||
log.info("Arret du photobooth")
|
||||
camera.deconnecter()
|
||||
|
||||
@@ -311,6 +332,18 @@ async def page_admin():
|
||||
return FileResponse(str(RACINE / "frontend" / "index.html"))
|
||||
|
||||
|
||||
@app.get("/api/health")
|
||||
async def api_health():
|
||||
return {
|
||||
"status": "ok",
|
||||
"camera": camera.mode if camera.connectee else "disconnected",
|
||||
"clients": len(clients_ws),
|
||||
"uptime": int(time.time() - _start_time),
|
||||
}
|
||||
|
||||
_start_time = time.time()
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def page_principale(request: Request):
|
||||
from fastapi.responses import RedirectResponse
|
||||
|
||||
Reference in New Issue
Block a user