Files
monlet/server/monlet_server/main.py
2026-05-27 10:01:59 +04:00

75 lines
2.3 KiB
Python

import asyncio
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.responses import Response
from . import metrics
from .api import agents, checks, events, health, heartbeat, incidents, outbox
from .db import dispose_engine, get_engine, get_sessionmaker
from .errors import install_error_handlers
from .logging_config import configure_logging, get_logger
from .middleware.auth import BearerAuthMiddleware
from .middleware.body_limit import BodyLimitMiddleware
from .middleware.request_id import RequestIdMiddleware
from .services.detector import run_detector
from .services.notifier_worker import run_notifier_worker
from .settings import get_settings
log = get_logger("monlet.main")
@asynccontextmanager
async def lifespan(app: FastAPI):
s = get_settings()
configure_logging(s.log_level)
get_engine()
sm = get_sessionmaker()
stop_event = asyncio.Event()
tasks: list[asyncio.Task] = []
if s.enable_detector:
tasks.append(asyncio.create_task(run_detector(sm, stop_event), name="detector"))
if s.enable_notifier_worker:
tasks.append(
asyncio.create_task(run_notifier_worker(sm, stop_event), name="notifier_worker")
)
log.info("server_started", host=s.host, port=s.port)
try:
yield
finally:
stop_event.set()
for t in tasks:
try:
await asyncio.wait_for(t, timeout=5.0)
except TimeoutError:
t.cancel()
await dispose_engine()
def create_app() -> FastAPI:
app = FastAPI(title="Monlet Server", version="1.0.0", lifespan=lifespan)
app.add_middleware(BearerAuthMiddleware)
app.add_middleware(BodyLimitMiddleware)
app.add_middleware(RequestIdMiddleware)
install_error_handlers(app)
app.include_router(health.router, prefix="/api/v1")
app.include_router(heartbeat.router, prefix="/api/v1")
app.include_router(events.router, prefix="/api/v1")
app.include_router(agents.router, prefix="/api/v1")
app.include_router(checks.router, prefix="/api/v1")
app.include_router(incidents.router, prefix="/api/v1")
app.include_router(outbox.router, prefix="/api/v1")
@app.get("/metrics")
async def metrics_endpoint() -> Response:
body, ct = metrics.render()
return Response(content=body, media_type=ct)
return app
app = create_app()