pounce/backend/run_scheduler.py

64 lines
1.6 KiB
Python

#!/usr/bin/env python3
"""
Standalone scheduler runner for Pounce.
Runs APScheduler jobs without starting the FastAPI server.
Recommended for production to avoid duplicate jobs when running multiple API workers.
"""
import asyncio
import logging
import signal
from dotenv import load_dotenv
# Load .env early (same as app/main.py)
load_dotenv()
from app.config import get_settings
from app.database import init_db
from app.scheduler import start_scheduler, stop_scheduler
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
)
logger = logging.getLogger("pounce.scheduler")
async def main() -> None:
settings = get_settings()
logger.info("Starting scheduler runner for %s...", settings.app_name)
# Ensure DB schema exists (create_all for new installs)
await init_db()
logger.info("Database initialized")
start_scheduler()
logger.info("Scheduler started")
stop_event = asyncio.Event()
def _request_shutdown(sig: signal.Signals) -> None:
logger.info("Received %s, shutting down scheduler...", sig.name)
stop_event.set()
loop = asyncio.get_running_loop()
for sig in (signal.SIGTERM, signal.SIGINT):
try:
loop.add_signal_handler(sig, lambda s=sig: _request_shutdown(s))
except NotImplementedError:
# Fallback (Windows / limited environments)
signal.signal(sig, lambda *_: _request_shutdown(sig))
await stop_event.wait()
stop_scheduler()
logger.info("Scheduler stopped. Bye.")
if __name__ == "__main__":
asyncio.run(main())