Starting phase 2
This commit is contained in:
parent
65c1954db5
commit
b5d2605d99
182
server/main.py
182
server/main.py
@ -58,23 +58,27 @@ if not public_url.endswith("/"):
|
||||
|
||||
ADMIN_TOKEN = os.getenv("ADMIN_TOKEN", None)
|
||||
|
||||
# Create FastAPI app first
|
||||
app = FastAPI(
|
||||
title="AI Voice Bot Server (Refactored)",
|
||||
description="WebRTC voice chat server with modular architecture",
|
||||
version="2.0.0",
|
||||
)
|
||||
|
||||
logger.info(f"Starting server with public URL: {public_url}")
|
||||
|
||||
|
||||
# Global managers - these replace the global variables from original main.py
|
||||
session_manager: SessionManager = None
|
||||
lobby_manager: LobbyManager = None
|
||||
auth_manager: AuthManager = None
|
||||
websocket_manager: WebSocketConnectionManager = None
|
||||
|
||||
# API routers
|
||||
admin_api: AdminAPI = None
|
||||
session_api: SessionAPI = None
|
||||
lobby_api: LobbyAPI = None
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
"""Lifespan context manager for startup and shutdown events"""
|
||||
global session_manager, lobby_manager, auth_manager, websocket_manager
|
||||
global admin_api, session_api, lobby_api
|
||||
|
||||
# Startup
|
||||
logger.info("Starting AI Voice Bot server with modular architecture...")
|
||||
@ -88,14 +92,11 @@ async def lifespan(app: FastAPI):
|
||||
session_manager.load()
|
||||
|
||||
# Restore lobbies for existing sessions
|
||||
# Note: This is a simplified version - full lobby restoration would be more complex
|
||||
for session in session_manager.get_all_sessions():
|
||||
for lobby_info in session.lobbies:
|
||||
# Create lobby if it doesn't exist
|
||||
lobby = lobby_manager.create_or_get_lobby(
|
||||
name=lobby_info.name, private=lobby_info.private
|
||||
)
|
||||
# Add session to lobby (but don't trigger events during startup)
|
||||
with lobby.lock:
|
||||
lobby.sessions[session.id] = session
|
||||
|
||||
@ -109,7 +110,7 @@ async def lifespan(app: FastAPI):
|
||||
auth_manager=auth_manager,
|
||||
)
|
||||
|
||||
# Initialize API routers
|
||||
# Create and register API routes
|
||||
admin_api = AdminAPI(
|
||||
session_manager=session_manager,
|
||||
lobby_manager=lobby_manager,
|
||||
@ -126,92 +127,23 @@ async def lifespan(app: FastAPI):
|
||||
public_url=public_url,
|
||||
)
|
||||
|
||||
# Register API routes
|
||||
# Register API routes during startup
|
||||
app.include_router(admin_api.router)
|
||||
app.include_router(session_api.router)
|
||||
app.include_router(lobby_api.router)
|
||||
|
||||
# Start background tasks
|
||||
await session_manager.start_background_tasks()
|
||||
# Register static file serving AFTER API routes to avoid conflicts
|
||||
PRODUCTION = os.getenv("PRODUCTION", "false").lower() == "true"
|
||||
client_build_path = os.path.join(os.path.dirname(__file__), "/client/build")
|
||||
|
||||
logger.info("AI Voice Bot server started successfully!")
|
||||
logger.info(f"Server URL: {public_url}")
|
||||
logger.info(f"Sessions loaded: {session_manager.get_session_count()}")
|
||||
logger.info(f"Lobbies available: {lobby_manager.get_lobby_count()}")
|
||||
logger.info(f"Protected names: {auth_manager.get_protection_count()}")
|
||||
|
||||
if ADMIN_TOKEN:
|
||||
logger.info("Admin endpoints protected with token")
|
||||
else:
|
||||
logger.warning("Admin endpoints are unprotected")
|
||||
|
||||
yield
|
||||
|
||||
# Shutdown
|
||||
logger.info("Shutting down AI Voice Bot server...")
|
||||
|
||||
# Stop background tasks
|
||||
if session_manager:
|
||||
await session_manager.stop_background_tasks()
|
||||
|
||||
logger.info("Server shutdown complete")
|
||||
|
||||
|
||||
# Create FastAPI app
|
||||
app = FastAPI(
|
||||
title="AI Voice Bot Server (Refactored)",
|
||||
description="WebRTC voice chat server with modular architecture",
|
||||
version="2.0.0",
|
||||
lifespan=lifespan,
|
||||
)
|
||||
|
||||
logger.info(f"Starting server with public URL: {public_url}")
|
||||
|
||||
|
||||
@app.websocket(f"{public_url}" + "ws/lobby/{lobby_id}/{session_id}")
|
||||
async def lobby_websocket(
|
||||
websocket: WebSocket,
|
||||
lobby_id: str | None = Path(...),
|
||||
session_id: str | None = Path(...),
|
||||
):
|
||||
"""WebSocket endpoint for lobby connections - now uses WebSocketConnectionManager"""
|
||||
await websocket_manager.handle_connection(websocket, lobby_id, session_id)
|
||||
|
||||
|
||||
# Health check for the new architecture
|
||||
@app.get(f"{public_url}api/system/health")
|
||||
def system_health():
|
||||
"""System health check showing manager status"""
|
||||
return {
|
||||
"status": "ok",
|
||||
"architecture": "modular",
|
||||
"version": "2.0.0",
|
||||
"managers": {
|
||||
"session_manager": "active" if session_manager else "inactive",
|
||||
"lobby_manager": "active" if lobby_manager else "inactive",
|
||||
"auth_manager": "active" if auth_manager else "inactive",
|
||||
"websocket_manager": "active" if websocket_manager else "inactive",
|
||||
},
|
||||
"statistics": {
|
||||
"sessions": session_manager.get_session_count() if session_manager else 0,
|
||||
"lobbies": lobby_manager.get_lobby_count() if lobby_manager else 0,
|
||||
"protected_names": auth_manager.get_protection_count()
|
||||
if auth_manager
|
||||
else 0,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
# Serve static files or proxy to frontend development server
|
||||
PRODUCTION = os.getenv("PRODUCTION", "false").lower() == "true"
|
||||
client_build_path = os.path.join(os.path.dirname(__file__), "/client/build")
|
||||
|
||||
if PRODUCTION:
|
||||
if PRODUCTION:
|
||||
logger.info(f"Serving static files from: {client_build_path} at {public_url}")
|
||||
app.mount(
|
||||
public_url, StaticFiles(directory=client_build_path, html=True), name="static"
|
||||
public_url,
|
||||
StaticFiles(directory=client_build_path, html=True),
|
||||
name="static",
|
||||
)
|
||||
else:
|
||||
else:
|
||||
logger.info(f"Proxying static files to http://client:3000 at {public_url}")
|
||||
|
||||
import ssl
|
||||
@ -233,7 +165,10 @@ else:
|
||||
# Accept self-signed certs in dev
|
||||
async with httpx.AsyncClient(verify=False) as client:
|
||||
proxy_req = client.build_request(
|
||||
request.method, url, headers=headers, content=await request.body()
|
||||
request.method,
|
||||
url,
|
||||
headers=headers,
|
||||
content=await request.body(),
|
||||
)
|
||||
proxy_resp = await client.send(proxy_req, stream=True)
|
||||
content = await proxy_resp.aread()
|
||||
@ -243,7 +178,11 @@ else:
|
||||
k: v
|
||||
for k, v in proxy_resp.headers.items()
|
||||
if k.lower()
|
||||
not in ["content-encoding", "transfer-encoding", "content-length"]
|
||||
not in [
|
||||
"content-encoding",
|
||||
"transfer-encoding",
|
||||
"content-length",
|
||||
]
|
||||
}
|
||||
return Response(
|
||||
content=content,
|
||||
@ -292,6 +231,69 @@ else:
|
||||
logger.error(f"REACT: WebSocket proxy error: {e}")
|
||||
await websocket.close()
|
||||
|
||||
# Start background tasks
|
||||
await session_manager.start_background_tasks()
|
||||
|
||||
logger.info("AI Voice Bot server started successfully!")
|
||||
logger.info(f"Server URL: {public_url}")
|
||||
logger.info(f"Sessions loaded: {session_manager.get_session_count()}")
|
||||
logger.info(f"Lobbies available: {lobby_manager.get_lobby_count()}")
|
||||
logger.info(f"Protected names: {auth_manager.get_protection_count()}")
|
||||
|
||||
if ADMIN_TOKEN:
|
||||
logger.info("Admin endpoints protected with token")
|
||||
else:
|
||||
logger.warning("Admin endpoints are unprotected")
|
||||
|
||||
yield
|
||||
|
||||
# Shutdown
|
||||
logger.info("Shutting down AI Voice Bot server...")
|
||||
|
||||
# Stop background tasks
|
||||
if session_manager:
|
||||
await session_manager.stop_background_tasks()
|
||||
|
||||
logger.info("Server shutdown complete")
|
||||
|
||||
|
||||
# Set the lifespan
|
||||
app.router.lifespan_context = lifespan
|
||||
|
||||
|
||||
@app.websocket(f"{public_url}" + "ws/lobby/{lobby_id}/{session_id}")
|
||||
async def lobby_websocket(
|
||||
websocket: WebSocket,
|
||||
lobby_id: str | None = Path(...),
|
||||
session_id: str | None = Path(...),
|
||||
):
|
||||
"""WebSocket endpoint for lobby connections - now uses WebSocketConnectionManager"""
|
||||
await websocket_manager.handle_connection(websocket, lobby_id, session_id)
|
||||
|
||||
|
||||
# Health check for the new architecture
|
||||
@app.get(f"{public_url}api/system/health")
|
||||
def system_health():
|
||||
"""System health check showing manager status"""
|
||||
return {
|
||||
"status": "ok",
|
||||
"architecture": "modular",
|
||||
"version": "2.0.0",
|
||||
"managers": {
|
||||
"session_manager": "active" if session_manager else "inactive",
|
||||
"lobby_manager": "active" if lobby_manager else "inactive",
|
||||
"auth_manager": "active" if auth_manager else "inactive",
|
||||
"websocket_manager": "active" if websocket_manager else "inactive",
|
||||
},
|
||||
"statistics": {
|
||||
"sessions": session_manager.get_session_count() if session_manager else 0,
|
||||
"lobbies": lobby_manager.get_lobby_count() if lobby_manager else 0,
|
||||
"protected_names": auth_manager.get_protection_count()
|
||||
if auth_manager
|
||||
else 0,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
|
Loading…
x
Reference in New Issue
Block a user