"""Flamenco Manager REST API client. Uses httpx (sync) for compatibility with Celery tasks and FastAPI endpoints. """ import logging from typing import Any import httpx logger = logging.getLogger(__name__) DEFAULT_TIMEOUT = 10.0 class FlamencoClient: """Thin wrapper around the Flamenco Manager v3 REST API.""" def __init__(self, manager_url: str): self.base_url = manager_url.rstrip("/") def _url(self, path: str) -> str: return f"{self.base_url}{path}" # ── Job management ────────────────────────────────────────────────────── def submit_job( self, name: str, job_type: str, settings: dict[str, Any], metadata: dict[str, str] | None = None, priority: int = 50, ) -> dict: """Submit a new render job to Flamenco Manager. Returns the created job dict (includes 'id'). """ payload = { "name": name, "type": job_type, "submitter_platform": "linux", "settings": settings, "metadata": metadata or {}, "priority": priority, } resp = httpx.post( self._url("/api/v3/jobs"), json=payload, timeout=DEFAULT_TIMEOUT, ) resp.raise_for_status() return resp.json() def get_job(self, job_id: str) -> dict: """Get job details by ID.""" resp = httpx.get( self._url(f"/api/v3/jobs/{job_id}"), timeout=DEFAULT_TIMEOUT, ) resp.raise_for_status() return resp.json() def cancel_job(self, job_id: str) -> None: """Request cancellation of a job.""" resp = httpx.post( self._url(f"/api/v3/jobs/{job_id}/setstatus"), json={"status": "cancel-requested"}, timeout=DEFAULT_TIMEOUT, ) resp.raise_for_status() # ── Workers ───────────────────────────────────────────────────────────── def list_workers(self) -> list[dict]: """List all registered workers.""" resp = httpx.get( self._url("/api/v3/worker-mgt/workers"), timeout=DEFAULT_TIMEOUT, ) resp.raise_for_status() data = resp.json() return data.get("workers", data) if isinstance(data, dict) else data # ── Farm status ───────────────────────────────────────────────────────── def get_farm_status(self) -> dict: """Get overall farm status from the Manager.""" resp = httpx.get( self._url("/api/v3/configuration"), timeout=DEFAULT_TIMEOUT, ) resp.raise_for_status() return resp.json() def health_check(self) -> dict: """Check if the Flamenco Manager is reachable and return version info.""" try: resp = httpx.get( self._url("/api/v3/version"), timeout=5.0, ) resp.raise_for_status() data = resp.json() return { "available": True, "version": data.get("version", "unknown"), "name": data.get("name", "Flamenco"), } except Exception as exc: logger.warning(f"Flamenco health check failed: {exc}") return { "available": False, "version": None, "name": None, "error": str(exc)[:200], } def get_flamenco_client(manager_url: str) -> FlamencoClient: """Factory that creates a FlamencoClient from a manager URL.""" return FlamencoClient(manager_url)