여러 줄 주석이 설명보다 경위(예전·실측·지적)를 적고 있어 읽는 사람이 결론을 찾기 어려웠다. - ts·tsx·js·mjs·css·py 478개: 여러 줄 주석은 첫 문장 한 줄로, 과거형·날짜 문장은 삭제 - 주석 위치는 TypeScript 파서·파이썬 tokenize/ast 로 찾는다 — 문자열 안의 # · /* 는 건드리지 않는다 - eslint·ts·noqa·type: ignore 같은 지시 주석은 그대로 둔다 파이썬 275개 정리 전후 AST 동일, TS 298개 주석 뺀 토큰 동일(빈 JSX 주석 10곳만 차이). site·frontend·admin tsc, site vitest 105 passed Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
56 lines
2.1 KiB
Python
56 lines
2.1 KiB
Python
"""백그라운드 스케줄러(크론) 패키지 — '언제'(when) 담당."""
|
|
import os
|
|
|
|
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
|
|
|
from common.logger import LOG
|
|
|
|
__all__ = ["start_scheduler", "shutdown_scheduler"]
|
|
|
|
_scheduler = None # AsyncIOScheduler | None
|
|
|
|
|
|
def _is_enabled() -> bool:
|
|
return os.environ.get("SCHEDULER_ENABLED", "0") == "1"
|
|
|
|
|
|
def start_scheduler():
|
|
"""lifespan startup 에서 호출."""
|
|
global _scheduler
|
|
if not _is_enabled():
|
|
LOG.i("[scheduler] disabled (SCHEDULER_ENABLED != 1)")
|
|
return
|
|
if _scheduler is not None:
|
|
return
|
|
|
|
# 한국시간 기준.
|
|
_scheduler = AsyncIOScheduler(timezone="Asia/Seoul")
|
|
# 1분이 아니라 5분이다.
|
|
from scheduler.jobs import sweep_social_posts
|
|
_scheduler.add_job(sweep_social_posts, 'interval', minutes=5, max_instances=1, coalesce=True)
|
|
if os.environ.get("GSC_ENABLED") == "1":
|
|
from services.search_console_service import run_scheduled_check
|
|
_scheduler.add_job(run_scheduled_check, "interval", minutes=10,
|
|
id="search-console", max_instances=1, coalesce=True)
|
|
|
|
from scheduler.jobs import sweep_alert_outbox, sweep_blog_mail, sweep_queue_health
|
|
_scheduler.add_job(sweep_alert_outbox, "interval", minutes=1,
|
|
id="alert-outbox", max_instances=1, coalesce=True)
|
|
_scheduler.add_job(sweep_queue_health, "interval", minutes=5,
|
|
id="queue-health", max_instances=1, coalesce=True)
|
|
# 미니 블로그 — 새벽에 재고를 채우고, 아침에 검수 통과분을 보낸다(docs/MINI_BLOG.md).
|
|
_scheduler.add_job(sweep_blog_mail, "cron", hour=9, minute=0,
|
|
id="blog-mail", max_instances=1, coalesce=True)
|
|
_scheduler.start()
|
|
LOG.i("[scheduler] started (KST: SNS 승인 만료·중단 복구)")
|
|
LOG.i(f"[scheduler] started (KST: {len(_scheduler.get_jobs())}개 잡)")
|
|
|
|
|
|
def shutdown_scheduler():
|
|
"""lifespan shutdown 에서 호출."""
|
|
global _scheduler
|
|
if _scheduler is not None:
|
|
_scheduler.shutdown(wait=False)
|
|
_scheduler = None
|
|
LOG.i("[scheduler] stopped")
|