Files
lair.moe/blueprints/risdeveau/modules/api/scheduler_guard.py
T

36 lines
977 B
Python
Raw Normal View History

2026-04-08 22:55:27 +03:00
from __future__ import annotations
import os
import fcntl
from typing import Optional
_LOCK_FD: Optional[int] = None # keep fd open for process lifetime
def should_start_scheduler() -> bool:
"""Return True in exactly one process (the scheduler owner).
Under gunicorn --workers N, code is imported in N processes. If APScheduler
starts at import time, you get N schedulers => N× API calls.
We prevent that by taking a non-blocking exclusive lock on a lockfile.
"""
global _LOCK_FD
if _LOCK_FD is not None:
return True
lock_path = os.environ.get("LAIR_SCHED_LOCK", "/tmp/lair-scheduler.lock")
fd = os.open(lock_path, os.O_CREAT | os.O_RDWR, 0o644)
try:
fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
_LOCK_FD = fd
return True
except BlockingIOError:
os.close(fd)
return False
except Exception:
try:
os.close(fd)
finally:
return False