102 lines
1.8 KiB
Python
102 lines
1.8 KiB
Python
from __future__ import annotations
|
|
|
|
import threading
|
|
import time
|
|
import traceback
|
|
|
|
from .enforcement import (
|
|
enforce_all_users,
|
|
)
|
|
|
|
|
|
class Scheduler:
|
|
|
|
def __init__(
|
|
self,
|
|
interval_seconds: float = 1.0,
|
|
):
|
|
self.interval_seconds = max(
|
|
0.1,
|
|
float(
|
|
interval_seconds
|
|
),
|
|
)
|
|
|
|
self._stop_event = (
|
|
threading.Event()
|
|
)
|
|
|
|
self._thread = None
|
|
|
|
def start(self):
|
|
if (
|
|
self._thread is not None
|
|
and self._thread.is_alive()
|
|
):
|
|
return
|
|
|
|
self._stop_event.clear()
|
|
|
|
self._thread = threading.Thread(
|
|
target=self._run,
|
|
name="parental-control-scheduler",
|
|
daemon=True,
|
|
)
|
|
|
|
self._thread.start()
|
|
|
|
def stop(self):
|
|
self._stop_event.set()
|
|
|
|
if self._thread is not None:
|
|
self._thread.join(
|
|
timeout=3
|
|
)
|
|
|
|
self._thread = None
|
|
|
|
def run_once(self):
|
|
return enforce_all_users()
|
|
|
|
def _run(self):
|
|
while not self._stop_event.is_set():
|
|
started = time.monotonic()
|
|
|
|
try:
|
|
self.run_once()
|
|
|
|
except Exception:
|
|
traceback.print_exc()
|
|
|
|
elapsed = (
|
|
time.monotonic()
|
|
- started
|
|
)
|
|
|
|
remaining = max(
|
|
0.0,
|
|
self.interval_seconds
|
|
- elapsed,
|
|
)
|
|
|
|
self._stop_event.wait(
|
|
remaining
|
|
)
|
|
|
|
|
|
_scheduler = Scheduler(
|
|
interval_seconds=1.0
|
|
)
|
|
|
|
|
|
def start_scheduler():
|
|
_scheduler.start()
|
|
|
|
|
|
def stop_scheduler():
|
|
_scheduler.stop()
|
|
|
|
|
|
def run_scheduler_once():
|
|
return _scheduler.run_once()
|