Files
game-marathon/status-service/main.py
2025-12-17 22:10:01 +07:00

110 lines
2.9 KiB
Python

import os
import asyncio
from datetime import datetime, timedelta
from typing import Optional
from contextlib import asynccontextmanager
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from monitors import ServiceMonitor, ServiceStatus
# Configuration
BACKEND_URL = os.getenv("BACKEND_URL", "http://backend:8000")
FRONTEND_URL = os.getenv("FRONTEND_URL", "http://frontend:80")
BOT_URL = os.getenv("BOT_URL", "http://bot:8080")
CHECK_INTERVAL = int(os.getenv("CHECK_INTERVAL", "30"))
# Initialize monitor
monitor = ServiceMonitor()
# Background task reference
background_task: Optional[asyncio.Task] = None
async def periodic_health_check():
"""Background task to check services periodically"""
while True:
await monitor.check_all_services(
backend_url=BACKEND_URL,
frontend_url=FRONTEND_URL,
bot_url=BOT_URL
)
await asyncio.sleep(CHECK_INTERVAL)
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Startup and shutdown events"""
global background_task
# Start background health checks
background_task = asyncio.create_task(periodic_health_check())
yield
# Cancel background task on shutdown
if background_task:
background_task.cancel()
try:
await background_task
except asyncio.CancelledError:
pass
app = FastAPI(
title="Status Monitor",
description="Service health monitoring",
lifespan=lifespan
)
templates = Jinja2Templates(directory="templates")
@app.get("/", response_class=HTMLResponse)
async def status_page(request: Request):
"""Main status page"""
services = monitor.get_all_statuses()
overall_status = monitor.get_overall_status()
return templates.TemplateResponse(
"index.html",
{
"request": request,
"services": services,
"overall_status": overall_status,
"last_check": monitor.last_check,
"check_interval": CHECK_INTERVAL
}
)
@app.get("/api/status")
async def api_status():
"""API endpoint for service statuses"""
services = monitor.get_all_statuses()
overall_status = monitor.get_overall_status()
return {
"overall_status": overall_status,
"services": {name: status.to_dict() for name, status in services.items()},
"last_check": monitor.last_check.isoformat() if monitor.last_check else None,
"check_interval_seconds": CHECK_INTERVAL
}
@app.get("/api/health")
async def health():
"""Health check for this service"""
return {"status": "ok", "service": "status-monitor"}
@app.post("/api/refresh")
async def refresh_status():
"""Force refresh all service statuses"""
await monitor.check_all_services(
backend_url=BACKEND_URL,
frontend_url=FRONTEND_URL,
bot_url=BOT_URL
)
return {"status": "refreshed"}