openreplay/api/app.py

133 lines
3.7 KiB
Python

import logging
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.gzip import GZipMiddleware
from boot.config import settings
from boot.middleware import timing_middleware, setup_cors
from boot.scheduler.manager import SchedulerManager
from boot.health.router import health_router
from chalicelib.utils import pg_client, ch_client
# Import routers and cron jobs
from crons import core_crons, core_dynamic_crons
from routers import core, core_dynamic
from routers.subs import insights, metrics, v1_api, health, usability_tests, spot, product_anaytics
# Configure logging
settings.configure_logging()
logger = logging.getLogger(__name__)
@asynccontextmanager
async def lifespan(app: FastAPI):
"""
Application lifespan context manager.
Handles startup and shutdown tasks:
- Database connections initialization
- Scheduler setup
- Cleanup on shutdown
"""
# Startup
logger.info(">>>>> starting up <<<<<")
# Initialize database connections
await pg_client.init()
await ch_client.init()
# Initialize scheduler with jobs
all_jobs = core_crons.cron_jobs + core_dynamic_crons.cron_jobs
SchedulerManager.initialize(all_jobs)
# Store PostgreSQL pool in app state for backwards compatibility
# app.state.postgresql = pg_client.
# App is ready to handle requests
yield
# Shutdown
logger.info(">>>>> shutting down <<<<<")
# Shutdown scheduler
SchedulerManager.shutdown()
# Close database connections
await pg_client.terminate()
await ch_client.terminate()
def create_app() -> FastAPI:
"""Create and configure the FastAPI application."""
# Create FastAPI app
app = FastAPI(
root_path=settings.ROOT_PATH,
docs_url=settings.DOCS_URL,
redoc_url=settings.REDOC_URL,
lifespan=lifespan,
title=f"{settings.APP_NAME} API",
description=f"API for {settings.APP_NAME}",
version="1.0.0"
)
# Add middlewares
app.add_middleware(GZipMiddleware, minimum_size=1000)
app.middleware('http')(timing_middleware)
setup_cors(app)
# Register health check routes first for monitoring systems
app.include_router(health_router)
# Register existing application routers
register_routers(app)
return app
def register_routers(app: FastAPI) -> None:
"""Register all application routers."""
# Core routers
app.include_router(core.public_app)
app.include_router(core.app)
app.include_router(core.app_apikey)
# Core dynamic routers
app.include_router(core_dynamic.public_app)
app.include_router(core_dynamic.app)
app.include_router(core_dynamic.app_apikey)
# Feature routers
app.include_router(metrics.app)
app.include_router(insights.app)
app.include_router(v1_api.app_apikey)
# Health routers (existing ones from the codebase)
app.include_router(health.public_app)
app.include_router(health.app)
app.include_router(health.app_apikey)
# Usability tests routers
app.include_router(usability_tests.public_app)
app.include_router(usability_tests.app)
app.include_router(usability_tests.app_apikey)
# Spot routers
app.include_router(spot.public_app)
app.include_router(spot.app)
app.include_router(spot.app_apikey)
# Product analytics routers
app.include_router(product_anaytics.public_app)
app.include_router(product_anaytics.app)
app.include_router(product_anaytics.app_apikey)
# Create application instance
app = create_app()
# For running with a proper ASGI server like uvicorn
if __name__ == "__main__":
import uvicorn
uvicorn.run("app:app", host="0.0.0.0", port=8000, reload=True)