Files
linux-user-timer/app/scheduler.py
T
2026-09-19 12:46:23 +05:00

107 lines
2.9 KiB
Python

import threading
import time
from datetime import date
from .enforcement import enforce_all_users
from .storage import get_user_policy, record_usage, consume_grant_seconds
CHECK_INTERVAL = 5
class Scheduler:
def __init__(self, interval: int = CHECK_INTERVAL):
self.interval = interval
self._thread = None
self._stop_event = threading.Event()
self._last_usage_update = {}
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=self.interval + 2)
def _run(self):
self._tick()
while not self._stop_event.wait(self.interval):
self._tick()
def _tick(self):
now = time.monotonic()
results = enforce_all_users()
for result in results:
user_id = result["user_id"]
previous = self._last_usage_update.get(user_id)
if previous is not None:
elapsed = max(0, int(now - previous["monotonic"]))
if elapsed > 0 and previous["allowed"] and previous["logged_in"]:
self._record_allowed_usage(
user_id,
elapsed,
previous["weekday"],
previous["date"],
)
if result["logged_in"] and result["allowed"]:
self._last_usage_update[user_id] = {
"monotonic": now,
"allowed": True,
"logged_in": True,
"weekday": result["weekday"],
"date": result["timestamp"][:10],
}
else:
self._last_usage_update.pop(user_id, None)
def _record_allowed_usage(self, user_id: int, seconds: int, weekday: int, usage_date: str):
if seconds <= 0:
return
(
allowance_seconds,
usage_seconds,
_windows,
grant_seconds,
) = get_user_policy(user_id, weekday)
allowance_remaining = max(0, allowance_seconds - usage_seconds)
normal_usage = min(seconds, allowance_remaining)
grant_usage = min(max(0, seconds - normal_usage), grant_seconds)
total_usage = normal_usage + grant_usage
if total_usage <= 0:
return
record_usage(
user_id,
total_usage,
date.fromisoformat(usage_date),
)
if grant_usage > 0:
consume_grant_seconds(user_id, grant_usage)
scheduler = Scheduler()
def start_scheduler():
scheduler.start()
def stop_scheduler():
scheduler.stop()