File size: 4,940 Bytes
19dc325
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from app.core.config import settings
from app.api.router import api_router

app = FastAPI(
    title=settings.PROJECT_NAME, 
    openapi_url=f"{settings.API_V1_STR}/openapi.json"
)

# Set all CORS enabled origins
from app.db.base import Base
from app.db.session import engine
from app.models.resume import Resume
from app.models.score import ResumeScore
from app.models.user import User

# Create tables (Moved to startup event)
# Base.metadata.create_all(bind=engine)

import asyncio

@app.on_event("startup")
async def startup_event():
    print("Server ready")
    
    async def load_models_background():
        print("Models loading in background...")
        try:
            # 1. Initialize DB
            Base.metadata.create_all(bind=engine)
            print("Database initialized.")
            
            # Models will load lazily on usage, saving startup memory.
            # print("Loading Embedding Model...")
            # EmbeddingService().load_model()
            # print("Embedding Model loaded.")
            
            # print("Initializing Vector Store...")
            # FAISSStore().initialize()
            # print("Vector Store initialized.")
            
            # 2. Rebuild FAISS index from DB if needed (Stateless Recovery)
            from app.vectorstore.faiss_store import FAISSStore
            from app.services.embedding_service import EmbeddingService
            from app.db.session import SessionLocal
            
            faiss_store = FAISSStore()
            faiss_store.initialize()
            
            db = SessionLocal()
            try:
                db_resumes = db.query(Resume).all()
                if db_resumes:
                    print(f"Startup check: Found {len(db_resumes)} resumes in database.")
                    unique_faiss_resumes = faiss_store.get_all_resumes()
                    unique_faiss_ids = {r.get("resume_id") for r in unique_faiss_resumes if r.get("resume_id")}
                    
                    missing_resumes = [r for r in db_resumes if r.resume_id not in unique_faiss_ids]
                    
                    if missing_resumes:
                        print(f"Rebuilding FAISS index: {len(missing_resumes)} resumes are missing from the FAISS store. Indexing...")
                        embedding_service = EmbeddingService()
                        embedding_service.load_model()
                        
                        for resume in missing_resumes:
                            if resume.extracted_text:
                                print(f"Generating embeddings and indexing resume: {resume.filename} (v{resume.version_number})")
                                embeddings = embedding_service.generate_embeddings(resume.extracted_text)
                                base_metadata = {
                                    "source": resume.filepath,
                                    "page_count": 0,
                                    "author": None,
                                    "creation_date": None,
                                    "producer": None,
                                    "resume_id": resume.resume_id,
                                    "filename": resume.filename,
                                    "filepath": resume.filepath,
                                    "version": resume.version_number,
                                }
                                metadatas = [base_metadata] * len(embeddings)
                                faiss_store.add_vectors(embeddings, metadatas)
                        print("FAISS index rebuild completed successfully.")
                    else:
                        print("Startup check: FAISS index is fully in sync with database.")
                else:
                    print("Startup check: No resumes found in database.")
            except Exception as e:
                print(f"FAISS startup rebuild failed: {e}")
            finally:
                db.close()
            
        except Exception as e:
            print(f"Startup initialization failed (non-critical, retrying or continuing): {e}")

    # Schedule the task to run in the background
    asyncio.create_task(load_models_background())

# Set all CORS enabled origins
origins = [
    "http://localhost:3000",
    "http://127.0.0.1:3000",
    "http://localhost:3001",
    "http://127.0.0.1:3001",
]

# Append dynamic CORS origins from environment config
if settings.BACKEND_CORS_ORIGINS:
    for origin in settings.BACKEND_CORS_ORIGINS:
        origin_str = str(origin).rstrip("/")
        if origin_str not in origins:
            origins.append(origin_str)

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

app.include_router(api_router, prefix=settings.API_V1_STR)