peregrine/resume_matcher/apps/backend/app/main.py
pyr0ball 1d9ee9cff0
Some checks failed
CI / Backend (Python) (push) Failing after 1m11s
CI / Frontend (Vue) (push) Failing after 21s
Mirror / mirror (push) Failing after 9s
feat(resume-matcher): wire cloud session + user_id routing to cf-orch
- app/cloud_session.py: CloudSessionFactory(product="peregrine") from
  cf-core v0.16.0; get_session / require_tier FastAPI dependencies;
  session_middleware_dep sets request-scoped user_id ContextVar
- app/llm.py: _request_user_id ContextVar + set/get helpers;
  _allocate_orch_async includes user_id in payload when present so
  premium users get their custom model path from cf-orch UserModelRegistry
- app/main.py: session_middleware_dep wired as global FastAPI dependency;
  runs on every request, zero function-signature changes needed

Force-added to bypass resume_matcher/ gitignore (CF-specific patch files).
2026-04-24 17:31:43 -07:00

88 lines
2.4 KiB
Python

"""FastAPI application entry point."""
import asyncio
import logging
import sys
from contextlib import asynccontextmanager
from fastapi import Depends, FastAPI
# Fix for Windows: Use ProactorEventLoop for subprocess support (Playwright)
if sys.platform == "win32":
asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
logger = logging.getLogger(__name__)
from fastapi.middleware.cors import CORSMiddleware
from app import __version__
from app.cloud_session import session_middleware_dep
from app.config import settings
from app.database import db
from app.pdf import close_pdf_renderer, init_pdf_renderer
from app.routers import config_router, enrichment_router, health_router, jobs_router, resumes_router
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Application lifespan manager."""
# Startup
settings.data_dir.mkdir(parents=True, exist_ok=True)
# PDF renderer uses lazy initialization - will initialize on first use
# await init_pdf_renderer()
yield
# Shutdown - wrap each cleanup in try-except to ensure all resources are released
try:
await close_pdf_renderer()
except Exception as e:
logger.error(f"Error closing PDF renderer: {e}")
try:
db.close()
except Exception as e:
logger.error(f"Error closing database: {e}")
app = FastAPI(
title="Resume Matcher API",
description="AI-powered resume tailoring for job descriptions",
version=__version__,
lifespan=lifespan,
dependencies=[Depends(session_middleware_dep)],
)
# CORS middleware - origins configurable via CORS_ORIGINS env var
app.add_middleware(
CORSMiddleware,
allow_origins=settings.cors_origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Include routers
app.include_router(health_router, prefix="/api/v1")
app.include_router(config_router, prefix="/api/v1")
app.include_router(resumes_router, prefix="/api/v1")
app.include_router(jobs_router, prefix="/api/v1")
app.include_router(enrichment_router, prefix="/api/v1")
@app.get("/")
async def root():
"""Root endpoint."""
return {
"name": "Resume Matcher API",
"version": __version__,
"docs": "/docs",
}
if __name__ == "__main__":
import uvicorn
uvicorn.run(
"app.main:app",
host=settings.host,
port=settings.port,
reload=True,
)