main_laptop_1 -> main byeonghap (4 hwangyeong 585 commits) #12

Merged
eomsangdon merged 585 commits from main_laptop_1 into main 2026-09-08 17:26:30 +09:00
Showing only changes of commit df02793caf - Show all commits
+49 -2
View File
@@ -15,7 +15,9 @@ import logging
import os
import signal
import subprocess
import time
from contextlib import asynccontextmanager
from datetime import datetime
from pathlib import Path
from typing import Any
@@ -271,6 +273,17 @@ async def lifespan(app: FastAPI):
# 시작
logger.info(f"[{ENVIRONMENT}] 앱 시작 중...")
# 지금 도는 코드가 언제 것인지 못박아 둔다 — `/api/health` 가 `stale` 로 알린다(7-2).
global _STARTED_AT, _CODE_MTIME_AT_START
_STARTED_AT = time.time()
if DEBUG:
_CODE_MTIME_AT_START = _newest_source_mtime()
logger.info(
"[reload] 감시 폴더 %d개, 소스 최신 수정 %s",
len(_reload_dirs()),
datetime.fromtimestamp(_CODE_MTIME_AT_START).isoformat(timespec="seconds"),
)
# 프론트엔드 빌드 (필수)
build_frontend()
@@ -440,10 +453,44 @@ async def root():
}
#: 이 프로세스가 뜬 시각과, 뜰 때 본 **가장 최근 소스 수정 시각**. 기동 때 채운다
#: (`_reload_dirs` 가 아래에 정의돼 있어 모듈 로드 시점에는 못 부른다).
#: 자동 리로드가 조용히 죽는 일이 잦아(오늘만 세 번, 매번 틀린 결론을 냄) 「지금 도는 서버가
#: 옛 코드인가」를 한 번에 가릴 수 있게 남긴다(2026-09-07, PLAN 7-2).
_STARTED_AT = 0.0
_CODE_MTIME_AT_START = 0.0
def _newest_source_mtime() -> float:
"""감시 대상 폴더의 `.py` 중 가장 최근 수정 시각. 못 읽으면 0."""
newest = 0.0
for folder in _reload_dirs():
for path in Path(folder).rglob("*.py"):
try:
newest = max(newest, path.stat().st_mtime)
except OSError:
continue
return newest
@app.get("/api/health")
async def health():
"""헬스 체크"""
return {"status": "ok", "environment": ENVIRONMENT}
"""헬스 체크.
개발 모드에서는 **코드가 최신인지**도 함께 알린다 — `stale: true` 면 소스가 더 새로우니
(자동 리로드가 안 붙은 것) 재시작 전에는 어떤 측정도 믿으면 안 된다.
"""
body: dict[str, Any] = {"status": "ok", "environment": ENVIRONMENT}
if DEBUG:
newest = _newest_source_mtime()
body["started_at"] = datetime.fromtimestamp(_STARTED_AT).isoformat(timespec="seconds")
body["code_mtime"] = datetime.fromtimestamp(_CODE_MTIME_AT_START).isoformat(
timespec="seconds"
)
body["source_mtime"] = datetime.fromtimestamp(newest).isoformat(timespec="seconds")
# 1초 여유 — 저장 직후의 미세한 시각차로 헛경고가 뜨지 않게.
body["stale"] = newest > _CODE_MTIME_AT_START + 1.0
return body
# ─────────────────────────────────────────────────────────────────────────