78 lines
2.7 KiB
Python
78 lines
2.7 KiB
Python
import os
|
|
import time
|
|
from contextlib import asynccontextmanager
|
|
|
|
from fastapi import FastAPI, Request
|
|
from fastapi.middleware.gzip import GZipMiddleware
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.responses import FileResponse
|
|
|
|
from common.database.db_session_manager import DB_SESSION_MNG
|
|
from common.logger import LOG
|
|
from common.utils.gtime import GTime
|
|
from router.middleware.tenant_middleware import TenantMiddleware
|
|
import router.v1.health.health
|
|
import router.v1.negotiation.negotiation
|
|
import router.v1.chat.chat
|
|
import router.v1.learning.learning
|
|
import router.v1.card.card
|
|
|
|
API_SERVER_START_TIME = GTime.UTCStr()
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
# startup: 공유 베이스(_base) 없으면 자동 시드 (운영 자동화, P5)
|
|
from bootstrap.lifespan import ensure_base_seeded
|
|
await ensure_base_seeded()
|
|
yield
|
|
# shutdown: DB 엔진 커넥션 풀 정리
|
|
await DB_SESSION_MNG.dispose_all()
|
|
|
|
|
|
app = FastAPI(title="Negosium Agent Server", lifespan=lifespan)
|
|
|
|
# Accept-Encoding: gzip 요청에 대해 1000 bytes 이상 응답을 압축.
|
|
app.add_middleware(GZipMiddleware, minimum_size=1000)
|
|
# 테넌트 라우팅 미들웨어 (헤더 X-Tenant-ID → request.state.tenant_id).
|
|
app.add_middleware(TenantMiddleware)
|
|
# 데모 HTML(file:// 또는 타 출처)에서 호출 가능하도록 CORS 허용 (개발용 — 운영은 출처 제한 권장).
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["*"],
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
|
|
@app.middleware("http")
|
|
async def log_time(request: Request, call_next):
|
|
start_time = time.time()
|
|
response = await call_next(request)
|
|
elapsed = time.time() - start_time
|
|
LOG.d(f"took: {elapsed:.4f} - {request.url.path}")
|
|
return response
|
|
|
|
|
|
@app.get(path="/healthz", responses={404: {"description": "Not found"}})
|
|
async def healthz():
|
|
return API_SERVER_START_TIME
|
|
|
|
|
|
# 간단 테스트 프론트 (tests/negotiation_demo.html). 같은 출처로 서빙 → CORS 불필요.
|
|
_DEMO_HTML = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "tests", "negotiation_demo.html")
|
|
|
|
|
|
@app.get(path="/demo", include_in_schema=False)
|
|
async def demo():
|
|
return FileResponse(_DEMO_HTML)
|
|
|
|
|
|
# 각 도메인 라우터 등록. 새 기능 추가 시 router.v1.<domain>.<file> import 후 include.
|
|
# (chat / card / learning / qtable 라우터는 P7 에서 Chat_server 14개 API 이식하며 추가)
|
|
app.include_router(router.v1.health.health.router)
|
|
app.include_router(router.v1.negotiation.negotiation.router)
|
|
app.include_router(router.v1.chat.chat.router)
|
|
app.include_router(router.v1.learning.learning.router)
|
|
app.include_router(router.v1.card.card.router)
|