""" Rate Monitor — FastAPI Backend """ import logging import sys from contextlib import asynccontextmanager logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[logging.StreamHandler(sys.stdout)] ) from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from database import DATABASE_URL from api import bookability, competitors, analysis, direct from scheduler import start_scheduler, shutdown_scheduler @asynccontextmanager async def lifespan(app: FastAPI): try: import os, psycopg2 schema_path = os.path.join(os.path.dirname(__file__), 'schema.sql') if os.path.exists(schema_path): with open(schema_path) as f: sql = f.read() conn = psycopg2.connect(DATABASE_URL) try: conn.autocommit = True with conn.cursor() as cur: cur.execute(sql) logging.getLogger(__name__).info("Schema applied successfully") finally: conn.close() except Exception as e: logging.getLogger(__name__).warning(f"Schema init failed: {e}") try: from services.booking_scraper import cleanup_stale_batches from database import SyncSessionLocal db = SyncSessionLocal() try: cleanup_stale_batches(db, max_age_minutes=10) finally: db.close() except Exception as e: logging.getLogger(__name__).warning(f"Stale batch cleanup failed: {e}") start_scheduler() yield shutdown_scheduler() app = FastAPI( title="Rate Monitor API", description="Rate monitoring, competitor scraping, and bookability service", version="1.0.0", lifespan=lifespan, ) app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) app.include_router(bookability.router, prefix="/bookability", tags=["Bookability"]) app.include_router(competitors.router, prefix="/competitors", tags=["Competitors"]) app.include_router(analysis.router, prefix="/analysis", tags=["Rate Analysis"]) app.include_router(direct.router, prefix="/direct", tags=["Direct Rates"]) @app.get("/health") async def health_check(): return {"status": "healthy", "service": "rate-monitor-api"}