add landing
This commit is contained in:
parent
10b7108b40
commit
287f0340fa
@ -5,9 +5,8 @@ from fastapi.responses import JSONResponse
|
|||||||
from starlette.middleware.base import BaseHTTPMiddleware
|
from starlette.middleware.base import BaseHTTPMiddleware
|
||||||
from starlette.types import ASGIApp
|
from starlette.types import ASGIApp
|
||||||
|
|
||||||
from app.core.database import get_session
|
from app.core.config import settings
|
||||||
from app.models.session import Session
|
from app.models.session import Session
|
||||||
from app.repositories.session_repository import SessionRepository
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -20,6 +19,10 @@ class SessionMiddleware(BaseHTTPMiddleware):
|
|||||||
self.cookie_name = cookie_name
|
self.cookie_name = cookie_name
|
||||||
|
|
||||||
async def dispatch(self, request: Request, call_next):
|
async def dispatch(self, request: Request, call_next):
|
||||||
|
# В режиме landing пропускаем работу с БД
|
||||||
|
if settings.app_mode == "landing":
|
||||||
|
return await call_next(request)
|
||||||
|
|
||||||
# Пропускаем статические файлы, служебные эндпоинты и OPTIONS запросы
|
# Пропускаем статические файлы, служебные эндпоинты и OPTIONS запросы
|
||||||
if (
|
if (
|
||||||
request.url.path.startswith(
|
request.url.path.startswith(
|
||||||
@ -37,6 +40,10 @@ class SessionMiddleware(BaseHTTPMiddleware):
|
|||||||
session_obj = None
|
session_obj = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# Ленивый импорт для избежания загрузки database.py в landing режиме
|
||||||
|
from app.core.database import get_session
|
||||||
|
from app.repositories.session_repository import SessionRepository
|
||||||
|
|
||||||
# Работаем с БД в рамках одной async сессии
|
# Работаем с БД в рамках одной async сессии
|
||||||
async for db_session in get_session():
|
async for db_session in get_session():
|
||||||
session_repo = SessionRepository(db_session)
|
session_repo = SessionRepository(db_session)
|
||||||
|
|||||||
56
docker-compose.landing.yml
Normal file
56
docker-compose.landing.yml
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
# Docker Compose for Landing Mode
|
||||||
|
# Usage: docker-compose -f docker-compose.landing.yml up -d
|
||||||
|
# Requires APP_MODE=landing in .env
|
||||||
|
|
||||||
|
services:
|
||||||
|
# HR AI Backend (landing mode - no DB required)
|
||||||
|
backend:
|
||||||
|
image: cr.yandex/crpnbn7b142t058unrn0/hr-ai-backend:latest
|
||||||
|
expose:
|
||||||
|
- "8000"
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
environment:
|
||||||
|
- APP_MODE=landing
|
||||||
|
- APP_ENV=production
|
||||||
|
- DEBUG=false
|
||||||
|
command: ["uv", "run", "fastapi", "run", "main.py", "--host", "0.0.0.0", "--port", "8000"]
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
# Frontend
|
||||||
|
frontend:
|
||||||
|
image: cr.yandex/crpnbn7b142t058unrn0/hr-ai-frontend:latest
|
||||||
|
platform: linux/amd64
|
||||||
|
expose:
|
||||||
|
- "3000"
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./.env.local:/app/.env.local:ro
|
||||||
|
|
||||||
|
# Caddy reverse proxy with automatic HTTPS
|
||||||
|
caddy:
|
||||||
|
image: caddy:2-alpine
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
volumes:
|
||||||
|
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
||||||
|
- caddy_data:/data
|
||||||
|
- caddy_config:/config
|
||||||
|
depends_on:
|
||||||
|
- backend
|
||||||
|
- frontend
|
||||||
|
environment:
|
||||||
|
- DOMAIN=${DOMAIN:-localhost}
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
caddy_data:
|
||||||
|
caddy_config:
|
||||||
22
main.py
22
main.py
@ -7,11 +7,14 @@ from fastapi.middleware.cors import CORSMiddleware
|
|||||||
|
|
||||||
from app.core.config import settings
|
from app.core.config import settings
|
||||||
from app.core.mode_middleware import LandingModeMiddleware
|
from app.core.mode_middleware import LandingModeMiddleware
|
||||||
|
from app.routers.contact_router import router as contact_router
|
||||||
|
|
||||||
|
# В режиме landing не загружаем роутеры, требующие БД
|
||||||
|
if settings.app_mode != "landing":
|
||||||
from app.core.session_middleware import SessionMiddleware
|
from app.core.session_middleware import SessionMiddleware
|
||||||
from app.routers import resume_router, vacancy_router
|
from app.routers import resume_router, vacancy_router
|
||||||
from app.routers.admin_router import router as admin_router
|
from app.routers.admin_router import router as admin_router
|
||||||
from app.routers.analysis_router import router as analysis_router
|
from app.routers.analysis_router import router as analysis_router
|
||||||
from app.routers.contact_router import router as contact_router
|
|
||||||
from app.routers.interview_reports_router import router as interview_report_router
|
from app.routers.interview_reports_router import router as interview_report_router
|
||||||
from app.routers.interview_router import router as interview_router
|
from app.routers.interview_router import router as interview_router
|
||||||
from app.routers.session_router import router as session_router
|
from app.routers.session_router import router as session_router
|
||||||
@ -19,6 +22,13 @@ from app.routers.session_router import router as session_router
|
|||||||
|
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def lifespan(app: FastAPI):
|
async def lifespan(app: FastAPI):
|
||||||
|
# В режиме landing агент не нужен
|
||||||
|
if settings.app_mode == "landing":
|
||||||
|
print("[STARTUP] Landing mode - skipping AI Agent startup")
|
||||||
|
yield
|
||||||
|
print("[SHUTDOWN] Landing mode - no AI Agent to stop")
|
||||||
|
return
|
||||||
|
|
||||||
# Запускаем AI агента при старте приложения
|
# Запускаем AI агента при старте приложения
|
||||||
from app.services.agent_manager import agent_manager
|
from app.services.agent_manager import agent_manager
|
||||||
|
|
||||||
@ -56,12 +66,15 @@ app.add_middleware(
|
|||||||
allow_headers=["*"],
|
allow_headers=["*"],
|
||||||
)
|
)
|
||||||
|
|
||||||
# Добавляем middleware для управления сессиями (после CORS)
|
|
||||||
app.add_middleware(SessionMiddleware, cookie_name="session_id")
|
|
||||||
|
|
||||||
# Добавляем middleware для режима лендинга (блокирует API в режиме landing)
|
# Добавляем middleware для режима лендинга (блокирует API в режиме landing)
|
||||||
app.add_middleware(LandingModeMiddleware)
|
app.add_middleware(LandingModeMiddleware)
|
||||||
|
|
||||||
|
# Contact router доступен всегда (не требует БД)
|
||||||
|
app.include_router(contact_router, prefix="/api/v1")
|
||||||
|
|
||||||
|
# Остальные роутеры и session middleware только в app режиме
|
||||||
|
if settings.app_mode != "landing":
|
||||||
|
app.add_middleware(SessionMiddleware, cookie_name="session_id")
|
||||||
app.include_router(vacancy_router, prefix="/api/v1")
|
app.include_router(vacancy_router, prefix="/api/v1")
|
||||||
app.include_router(resume_router, prefix="/api/v1")
|
app.include_router(resume_router, prefix="/api/v1")
|
||||||
app.include_router(session_router, prefix="/api/v1")
|
app.include_router(session_router, prefix="/api/v1")
|
||||||
@ -69,7 +82,6 @@ app.include_router(interview_router, prefix="/api/v1")
|
|||||||
app.include_router(analysis_router, prefix="/api/v1")
|
app.include_router(analysis_router, prefix="/api/v1")
|
||||||
app.include_router(admin_router, prefix="/api/v1")
|
app.include_router(admin_router, prefix="/api/v1")
|
||||||
app.include_router(interview_report_router, prefix="/api/v1")
|
app.include_router(interview_report_router, prefix="/api/v1")
|
||||||
app.include_router(contact_router, prefix="/api/v1")
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/")
|
@app.get("/")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user