generated from nathanwoodburn/python-webserver-template
feat: Initial code
This commit is contained in:
3
services/__init__.py
Normal file
3
services/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from .scheduler import CollectionScheduler, should_autostart_scheduler
|
||||
|
||||
__all__ = ["CollectionScheduler", "should_autostart_scheduler"]
|
||||
57
services/scheduler.py
Normal file
57
services/scheduler.py
Normal file
@@ -0,0 +1,57 @@
|
||||
import fcntl
|
||||
import logging
|
||||
import os
|
||||
import threading
|
||||
|
||||
from collectors import InventoryCollectorOrchestrator
|
||||
from config import AppConfig
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CollectionScheduler:
|
||||
def __init__(self, config: AppConfig, orchestrator: InventoryCollectorOrchestrator):
|
||||
self.config = config
|
||||
self.orchestrator = orchestrator
|
||||
self._stop_event = threading.Event()
|
||||
self._thread: threading.Thread | None = None
|
||||
self._leader_file = None
|
||||
|
||||
def start(self) -> bool:
|
||||
if not self.config.scheduler_enabled:
|
||||
LOGGER.info("Scheduler disabled via config")
|
||||
return False
|
||||
|
||||
leader_file = open("/tmp/inventory-scheduler.lock", "w", encoding="utf-8")
|
||||
try:
|
||||
fcntl.flock(leader_file.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||
except OSError:
|
||||
leader_file.close()
|
||||
LOGGER.info("Another worker owns scheduler lock")
|
||||
return False
|
||||
|
||||
self._leader_file = leader_file
|
||||
|
||||
self._thread = threading.Thread(target=self._run_loop, name="inventory-scheduler", daemon=True)
|
||||
self._thread.start()
|
||||
LOGGER.info("Scheduler started with %s second interval", self.config.poll_interval_seconds)
|
||||
return True
|
||||
|
||||
def _run_loop(self) -> None:
|
||||
while not self._stop_event.is_set():
|
||||
self.orchestrator.collect_once()
|
||||
self._stop_event.wait(self.config.poll_interval_seconds)
|
||||
|
||||
def shutdown(self) -> None:
|
||||
self._stop_event.set()
|
||||
if self._thread and self._thread.is_alive():
|
||||
self._thread.join(timeout=1.0)
|
||||
if self._leader_file:
|
||||
fcntl.flock(self._leader_file.fileno(), fcntl.LOCK_UN)
|
||||
self._leader_file.close()
|
||||
self._leader_file = None
|
||||
|
||||
|
||||
def should_autostart_scheduler() -> bool:
|
||||
# Do not auto-start on Flask's reloader child process.
|
||||
return os.getenv("WERKZEUG_RUN_MAIN", "true") != "false"
|
||||
Reference in New Issue
Block a user