Files
hockey_new/hockey_data/account_activity.py
2026-09-26 23:18:54 +03:00

30 lines
1.3 KiB
Python

"""Account activity and the shared transaction lock for channel ownership."""
from __future__ import annotations
import hashlib
from datetime import datetime, timedelta
from sqlalchemy import func, select, text, update
from .models import HockeyWebSession, MatchParticipant
ACCOUNT_IDLE_SECONDS = 2 * 60 * 60
def lock_account(session, user_id: str) -> None:
if session.get_bind().dialect.name == "postgresql":
key = int.from_bytes(hashlib.sha256(("hockey-channel:" + user_id).encode()).digest()[:8], "big", signed=True)
session.execute(text("SELECT pg_advisory_xact_lock(:key)"), {"key": key})
else:
session.execute(update(MatchParticipant).where(MatchParticipant.user_id == user_id)
.values(last_seen_at=MatchParticipant.last_seen_at))
def account_is_idle(session, user_id: str, now: datetime) -> bool:
# All browser logins of this account count, including the last action before
# logout. Polling, OperatorSession timestamps and Agent traffic never count.
latest = session.scalar(select(func.max(HockeyWebSession.last_activity_at)).where(
HockeyWebSession.wfl_user_id == user_id))
# Header-based development/test auth has no persisted browser logins.
return latest is not None and latest <= now - timedelta(seconds=ACCOUNT_IDLE_SECONDS)