import time from contextlib import asynccontextmanager from fastapi import FastAPI, Request from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.gzip import GZipMiddleware from common.database.db_session_manager import DB_SESSION_MNG from common.logger import LOG from common.utils.gtime import GTime from config.server_configs import web_server_config from scheduler import shutdown_scheduler, start_scheduler import router.v1.auth.account import router.v1.company.user import router.v1.item.item import router.v1.supplier.supplier import router.v1.card.card import router.v1.quotation.quotation import router.v1.quotation_setting.quotation_setting import router.v1.dashboard.dashboard API_SERVER_START_TIME = GTime.UTCStr() @asynccontextmanager async def lifespan(app: FastAPI): # startup: 마감 스케줄러 기동(SCHEDULER_ENABLED=1 인 프로세스에서만) start_scheduler() yield # shutdown: 스케줄러 정지 + DB 엔진 커넥션 풀 정리 shutdown_scheduler() await DB_SESSION_MNG.dispose_all() app = FastAPI(title="Negodata Api Server", lifespan=lifespan) # CORS app.add_middleware( CORSMiddleware, allow_origins=[web_server_config.client_url], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Accept-Encoding: gzip 요청에 대해 1000 bytes 이상 응답을 압축. app.add_middleware(GZipMiddleware, minimum_size=1000) @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 # status_code 를 함께 남긴다(403/4xx 등을 로그만으로 식별 가능하게). LOG.d(f"{response.status_code} {request.method} {request.url.path} - {elapsed:.4f}s") return response @app.get(path="/healthz", responses={404: {"description": "Not found"}}) async def healthz(): return API_SERVER_START_TIME # 각 도메인 라우터를 등록한다. 새 기능 추가 시 router.v1.. 를 import 후 include. app.include_router(router.v1.auth.account.router) app.include_router(router.v1.company.user.router) app.include_router(router.v1.item.item.router) app.include_router(router.v1.supplier.supplier.router) app.include_router(router.v1.card.card.router) app.include_router(router.v1.quotation.quotation.router) app.include_router(router.v1.quotation_setting.quotation_setting.router) app.include_router(router.v1.dashboard.dashboard.router)