updates on the backend
This commit is contained in:
107
app/main.py
Normal file
107
app/main.py
Normal file
@@ -0,0 +1,107 @@
|
||||
"""
|
||||
FastAPI application entry point.
|
||||
|
||||
Run with:
|
||||
uvicorn app.main:app --reload --port 8000
|
||||
|
||||
(see backend/README.md / the project documentation for full setup steps)
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import threading
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.responses import FileResponse
|
||||
|
||||
from app.infrastructure.settings import API_CORS_ORIGINS
|
||||
from app.api.routers import health, brands, search, chat, catalog, system
|
||||
from app.api.routers import stores, discounts, analytics as store_analytics, trending, recommendations, store_admin
|
||||
from app.api.routers import nutrition, nutrition_admin, upload
|
||||
from app.api.routers import auth, user_products, admin_train
|
||||
from app.services.store_db import ensure_store_intelligence_schema
|
||||
from app.services.nutrition_db import ensure_nutrition_schema
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
app = FastAPI(
|
||||
title="Brand Product Search Engine - RAG API",
|
||||
description=(
|
||||
"Local, CPU-only RAG API over an Indian FMCG product catalog stored in pgvector. "
|
||||
"Includes automated multi-store intelligence, ML discount engines, and nutrition intelligence."
|
||||
),
|
||||
version="3.2.0",
|
||||
)
|
||||
|
||||
|
||||
@app.on_event("startup")
|
||||
def _on_startup() -> None:
|
||||
# Asynchronously ensure schemas and background auto-init so server starts instantly (<1s)
|
||||
def _async_init():
|
||||
try:
|
||||
ensure_store_intelligence_schema()
|
||||
ensure_nutrition_schema()
|
||||
from app.api.routers.system import _run_background_auto_seed
|
||||
_run_background_auto_seed()
|
||||
except Exception as e:
|
||||
logger.warning("Startup background init warning: %s", e)
|
||||
|
||||
threading.Thread(target=_async_init, daemon=True).start()
|
||||
|
||||
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=API_CORS_ORIGINS,
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
app.include_router(health.router, prefix="/api")
|
||||
app.include_router(auth.router, prefix="/api")
|
||||
app.include_router(user_products.router, prefix="/api")
|
||||
app.include_router(admin_train.router, prefix="/api")
|
||||
app.include_router(system.router, prefix="/api")
|
||||
app.include_router(brands.router, prefix="/api")
|
||||
app.include_router(search.router, prefix="/api")
|
||||
app.include_router(chat.router, prefix="/api")
|
||||
app.include_router(catalog.router, prefix="/api")
|
||||
app.include_router(stores.router, prefix="/api")
|
||||
app.include_router(discounts.router, prefix="/api")
|
||||
app.include_router(store_analytics.router, prefix="/api")
|
||||
app.include_router(trending.router, prefix="/api")
|
||||
app.include_router(recommendations.router, prefix="/api")
|
||||
app.include_router(store_admin.router, prefix="/api")
|
||||
app.include_router(nutrition.router, prefix="/api")
|
||||
app.include_router(nutrition_admin.router, prefix="/api")
|
||||
app.include_router(upload.router, prefix="/api")
|
||||
|
||||
# Serve built frontend static files if dist exists (single-port unified deployment)
|
||||
FRONTEND_DIST = Path(__file__).resolve().parents[2] / "frontend" / "dist"
|
||||
if FRONTEND_DIST.exists() and (FRONTEND_DIST / "assets").exists():
|
||||
app.mount("/assets", StaticFiles(directory=str(FRONTEND_DIST / "assets")), name="assets")
|
||||
|
||||
@app.get("/{full_path:path}")
|
||||
def serve_frontend(full_path: str):
|
||||
if full_path.startswith("api") or full_path.startswith("docs") or full_path.startswith("openapi.json"):
|
||||
return None
|
||||
file_path = FRONTEND_DIST / full_path
|
||||
if file_path.exists() and file_path.is_file():
|
||||
return FileResponse(file_path)
|
||||
return FileResponse(FRONTEND_DIST / "index.html")
|
||||
else:
|
||||
@app.get("/")
|
||||
def root() -> dict:
|
||||
return {
|
||||
"service": "Brand Product Search Engine - RAG API",
|
||||
"docs": "/docs",
|
||||
"health": "/api/health",
|
||||
"system_status": "/api/system/status",
|
||||
}
|
||||
Reference in New Issue
Block a user