updated gui and enforcement

This commit is contained in:
2026-09-17 20:41:35 +05:00
parent 77c00c4ed5
commit 47c292f4cd
15 changed files with 3065 additions and 1095 deletions
+44 -126
View File
@@ -1,33 +1,34 @@
from __future__ import annotations
import threading
import time
from datetime import datetime
import traceback
from .enforcement import (
enforce_all_users,
record_usage,
get_user_policy,
consume_grant_seconds,
)
CHECK_INTERVAL = 5
class Scheduler:
def __init__(
self,
interval: int = CHECK_INTERVAL,
interval_seconds: float = 1.0,
):
self.interval = interval
self.interval_seconds = max(
0.1,
float(
interval_seconds
),
)
self._stop_event = (
threading.Event()
)
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()
@@ -45,139 +46,56 @@ class Scheduler:
self._thread.start()
def stop(self):
self._stop_event.set()
if self._thread is not None:
self._thread.join(
timeout=self.interval + 2
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()
# Evaluate immediately when the
# application starts.
self._tick()
try:
self.run_once()
while not self._stop_event.wait(
self.interval
):
self._tick()
except Exception:
traceback.print_exc()
def _tick(self):
now = time.monotonic()
results = enforce_all_users()
for result in results:
user_id = result["user_id"]
if not result["logged_in"]:
self._last_usage_update.pop(
user_id,
None,
)
continue
if not result["allowed"]:
self._last_usage_update.pop(
user_id,
None,
)
continue
previous = (
self._last_usage_update.get(
user_id
)
elapsed = (
time.monotonic()
- started
)
self._last_usage_update[user_id] = now
if previous is None:
continue
elapsed = int(
now - previous
remaining = max(
0.0,
self.interval_seconds
- elapsed,
)
if elapsed <= 0:
continue
self._record_allowed_usage(
user_id,
elapsed,
)
def _record_allowed_usage(
self,
user_id: int,
seconds: int,
):
if seconds <= 0:
return
weekday = datetime.now().weekday()
(
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 = (
seconds
- normal_usage
)
if grant_usage > grant_seconds:
grant_usage = grant_seconds
total_usage = (
normal_usage
+ grant_usage
)
if total_usage <= 0:
return
record_usage(
user_id,
total_usage,
)
if grant_usage > 0:
consume_grant_seconds(
user_id,
grant_usage,
self._stop_event.wait(
remaining
)
scheduler = Scheduler()
_scheduler = Scheduler(
interval_seconds=1.0
)
def start_scheduler():
scheduler.start()
_scheduler.start()
def stop_scheduler():
scheduler.stop()
_scheduler.stop()
def run_scheduler_once():
return _scheduler.run_once()