Spaces:
Running
Running
| 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) | |
| 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") | |
| async def root_health(): | |
| return {"status": "ok", "version": _settings.app_version} | |
| 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() | |