2.7 KiB
2.7 KiB
DB 기반 스케줄러 관리 시스템 구현
날짜: 2026-01-02
작성자: happybell80
관련 파일: rb8001/app/state/scheduler_repository.py, rb8001/app/scheduler/db_loader.py, rb8001/app/router/scheduler_endpoint.py, rb8001/main.py
문제 상황
환경변수 하드코딩 불일치
lunch_worldcup.py:16: 기본값"false"설정.env파일:LUNCH_WORLDCUP_ENABLED=true하드코딩- 결과: 코드 기본값과 환경변수 불일치로 12시 스케줄 실행됨
- 원인:
311_FastAPI_구조_원칙.md:241-252단일 소스 원칙 위반
main.py 스케줄 코드 과다
- 732줄 중 130줄이 스케줄 관련 코드
- 환경변수 기반 등록으로 동적 관리 불가
해결 방안
Phase 1-2: Repository 구현
scheduler_repository.py:scheduled_jobs테이블 CRUD_ensure_table(): 테이블 자동 생성- JSONB
config필드 파싱:json.loads()적용 (get_enabled_jobs,get_job_by_name)
Phase 3: DB 로더 구현
db_loader.py:JOB_TYPE_MAP으로 job_type → 함수 매핑load_jobs_from_db(): DB 조회 → APScheduler 등록- async 함수는 sync 래퍼(
_run_*_with_logging) 사용
Phase 4: main.py 리팩토링
main.py:146-149: 환경변수 기반 등록 제거,load_jobs_from_db()호출app.state.scheduler설정:scheduler_endpoint.py에서request.app.state.scheduler사용
Phase 5: API 엔드포인트
scheduler_endpoint.py: CRUD + run 엔드포인트POST /api/scheduler/jobs: 잡 생성PATCH /api/scheduler/jobs/{name}: 수정DELETE /api/scheduler/jobs/{name}: 삭제GET /api/scheduler/jobs: 목록 조회
테스트 이슈 해결
- JSONB 파싱:
asyncpg가 JSONB를 string으로 반환 →json.loads()적용 - E2E 테스트 이벤트 루프 충돌:
pytest-asyncio와TestClient충돌 - 해결: 동기
TestClientfixture +run_async()헬퍼 함수 사용
구현 완료
- 커밋:
1e82dee(2026-01-02) - 테스트: 13개 모두 통과 (repository 5, loader 3, E2E 5)
- 배포: Gitea Actions 자동 배포 완료
교훈
환경변수 관리 원칙 준수
os.getenv()직접 호출 시 기본값과.env하드코딩 불일치 위험- DB 기반 설정으로 단일 소스 원칙 준수 가능
- 향후 Pydantic Settings 전환 권장 (
Phase 7)
JSONB 타입 처리
asyncpg는 JSONB를 string으로 반환하므로 명시적 파싱 필요json.loads()적용 위치: Repository 레이어에서 일관되게 처리
E2E 테스트 이벤트 루프 관리
pytest-asyncio와 FastAPITestClient의 lifespan 이벤트 충돌 가능- 해결: 동기
TestClient+ 비동기 작업은 별도 루프에서 실행 app.state패턴으로 의존성 주입 간소화