import sqlite3 from pathlib import Path from typing import Any, Dict, List, Optional from app_state import StateStore def health_payload( data_dir: Path, session_dir: Path, state_store: StateStore, continuous_snapshot: Dict[str, Any], job_queue_size: int, account_ids: Optional[List[str]] = None, ) -> Dict[str, Any]: checks = { "data_dir": _dir_check(data_dir, writable=True), "session_dir": _dir_check(session_dir, writable=True), "state_file": _state_check(state_store), "sqlite": _sqlite_check(), "continuous": _continuous_check(continuous_snapshot), "job_queue": {"ok": True, "size": job_queue_size}, } # Per-account health if account_ids: account_checks: Dict[str, Any] = {} for acc_id in account_ids: acc_dir = data_dir / "accounts" / acc_id session_file = session_dir / f"{acc_id}.session" account_checks[acc_id] = { "data_dir": _dir_check(acc_dir), "session_file": { "ok": session_file.exists(), "path": str(session_file), }, } checks["accounts"] = { "ok": all( item.get("data_dir", {}).get("ok", False) for item in account_checks.values() ), "items": account_checks, } ok = all(item.get("ok", False) for item in checks.values()) return {"ok": ok, "status": "ok" if ok else "degraded", "checks": checks} def _dir_check(path: Path, writable: bool = False) -> Dict[str, Any]: path.mkdir(parents=True, exist_ok=True) ok = path.exists() and path.is_dir() payload: Dict[str, Any] = {"ok": ok, "path": str(path)} if writable: probe = path / ".healthcheck" try: probe.write_text("ok", encoding="utf-8") probe.unlink(missing_ok=True) payload["writable"] = True except OSError as exc: payload.update({"ok": False, "writable": False, "error": str(exc)}) return payload def _state_check(state_store: StateStore) -> Dict[str, Any]: try: state = state_store.load() return { "ok": True, "path": str(state_store.path), "has_api_credentials": bool(state.get("api_id") and state.get("api_hash")), "tracked_channels": len(state.get("channels", {})), } except Exception as exc: return {"ok": False, "path": str(state_store.path), "error": str(exc)} def _sqlite_check() -> Dict[str, Any]: try: conn = sqlite3.connect(":memory:") conn.execute("SELECT 1") conn.close() return {"ok": True} except sqlite3.Error as exc: return {"ok": False, "error": str(exc)} def _continuous_check(snapshot: Dict[str, Any]) -> Dict[str, Any]: running_accounts = snapshot.get("running_accounts") if running_accounts is None: running_accounts = snapshot return { "ok": True, "account_count": len(running_accounts), "accounts": { aid: { "running": bool((info.get("status") or info).get("running")), "enabled": bool((info.get("config") or {}).get("enabled", False)), "last_error": (info.get("status") or info).get("last_error"), } for aid, info in running_accounts.items() if isinstance(info, dict) }, }