llm-ready-data / app /api /server.py
xce009's picture
sure
c28ae12
Raw
History Blame
3.15 kB
from __future__ import annotations
import asyncio
import os
import time
from contextlib import asynccontextmanager
from datetime import datetime, timezone
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.gzip import GZipMiddleware
from app.config import get_settings
from app.core.banner import print_banner
from app.core.constants import SUPPORTED_EXTENSIONS
from app.core.logger import get_logger
from app.api.v1.router import api_v1_router
_logger = get_logger(__name__)
_settings = get_settings()
_START_TIME = time.time()
async def _self_ping():
import httpx
health_url = "https://aetherbase-llm-ready-data.hf.space/health"
while True:
try:
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.get(health_url)
if response.status_code == 200:
_logger.info("Self-ping successful: %s", health_url)
else:
_logger.warning("Self-ping returned: %s - %s", health_url, response.status_code)
except Exception as exc:
_logger.error("Self-ping error: %s", exc)
await asyncio.sleep(900)
@asynccontextmanager
async def lifespan(app: FastAPI):
print_banner()
_logger.info("Server ready at http://%s:%s", _settings.host, _settings.port)
_logger.info("Swagger UI : http://%s:%s/docs", _settings.host, _settings.port)
_logger.info("ReDoc : http://%s:%s/redoc", _settings.host, _settings.port)
_logger.info("Started at : %s", datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC"))
asyncio.create_task(_self_ping())
_logger.info("Self-ping task started (every hour)")
yield
_logger.info("Application shutting down gracefully")
def create_application() -> FastAPI:
app = FastAPI(
title=_settings.app_name,
description="Document-to-Markdown and structured data extraction API powered by Microsoft MarkItDown, RapidOCR, and spaCy.",
version=_settings.app_version,
docs_url="/docs",
redoc_url="/redoc",
openapi_tags=[
{"name": "Convert", "description": "Single-file and single-URL conversion"},
{"name": "Batch", "description": "Bulk conversion of files and URLs"},
{"name": "System", "description": "Health, info, and supported formats"},
],
lifespan=lifespan,
)
app.add_middleware(GZipMiddleware, minimum_size=1000)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(api_v1_router, prefix="/v1")
@app.get("/health", include_in_schema=False)
async def root_health():
return {"status": "ok", "version": _settings.app_version}
@app.get("/ping", include_in_schema=False)
async def ping():
return {"message": f"{_settings.app_name} is running..."}
_max_workers = min(32, (os.cpu_count() or 1) + 4)
_logger.info("Initialized thread pool with %s workers", _max_workers)
return app
app = create_application()