"""Entry point: starts Redis (if possible), serves the FastAPI backend + static frontend.""" import subprocess import time import socket import uvicorn from fastapi.staticfiles import StaticFiles from backend.api.main import app from backend.core.config import get_settings # Mount at module level so the reloader worker picks it up when importing run:app app.mount("/", StaticFiles(directory="frontend", html=True), name="frontend") def _redis_already_up(host: str = "127.0.0.1", port: int = 6379) -> bool: try: with socket.create_connection((host, port), timeout=1): return True except OSError: return False def _start_redis() -> subprocess.Popen | None: if _redis_already_up(): print("[run] Redis already running.") return None # Try Docker first try: proc = subprocess.Popen( ["docker", "run", "--rm", "-p", "6379:6379", "--name", "mas-redis", "redis:7-alpine"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, ) for _ in range(10): time.sleep(0.5) if _redis_already_up(): print("[run] Redis started via Docker.") return proc proc.terminate() except FileNotFoundError: pass # Try local redis-server try: proc = subprocess.Popen( ["redis-server", "--daemonize", "no"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, ) for _ in range(6): time.sleep(0.5) if _redis_already_up(): print("[run] Redis started via redis-server.") return proc proc.terminate() except FileNotFoundError: pass print("[run] Redis unavailable — short-term memory disabled (app still works).") return None if __name__ == "__main__": settings = get_settings() redis_proc = _start_redis() try: uvicorn.run( "run:app", host=settings.app_host, port=settings.app_port, reload=settings.is_dev, ) finally: if redis_proc is not None: redis_proc.terminate() print("[run] Redis stopped.")