Files
agentic-soc-platform/backend/apps/dashboard/cache.py

77 lines
2.4 KiB
Python

import logging
from django.core.cache import cache
from django.utils import timezone
from django.utils.dateparse import parse_datetime
from django_redis import get_redis_connection
from redis.exceptions import LockNotOwnedError
logger = logging.getLogger(__name__)
DASHBOARD_CACHE_KEY = "dashboard:overview:v1:{window}"
DASHBOARD_REFRESH_LOCK_KEY = "dashboard:overview:refresh:v1:{window}"
DASHBOARD_REFRESH_LOCK_TIMEOUT_SECONDS = 600
DASHBOARD_STALE_WARNING_INTERVALS = 3
def _cache_key(window):
return DASHBOARD_CACHE_KEY.format(window=window)
def set_cached_dashboard_overview(window, overview, refresh_interval_seconds):
cache.set(
_cache_key(window),
{
"overview": overview,
"refreshed_at": timezone.now().isoformat(),
"refresh_interval_seconds": int(refresh_interval_seconds),
},
timeout=None,
)
def get_cached_dashboard_overview(window):
snapshot = cache.get(_cache_key(window))
if snapshot is None:
return None
refreshed_at = parse_datetime(snapshot["refreshed_at"])
if refreshed_at is None:
raise ValueError(f"Invalid dashboard cache timestamp for window {window}.")
refresh_interval_seconds = int(snapshot["refresh_interval_seconds"])
age_seconds = max(0, int((timezone.now() - refreshed_at).total_seconds()))
overview = dict(snapshot["overview"])
overview["cache"] = {
"generated_at": overview["generated_at"],
"refreshed_at": refreshed_at.isoformat(),
"refresh_interval_seconds": refresh_interval_seconds,
"age_seconds": age_seconds,
"stale_warning": age_seconds > refresh_interval_seconds * DASHBOARD_STALE_WARNING_INTERVALS,
}
return overview
def refresh_cached_dashboard_overview(window, refresh_interval_seconds):
connection = get_redis_connection("default")
lock = connection.lock(
DASHBOARD_REFRESH_LOCK_KEY.format(window=window),
timeout=DASHBOARD_REFRESH_LOCK_TIMEOUT_SECONDS,
blocking_timeout=0,
)
if not lock.acquire(blocking=False):
return False
try:
from .views import build_dashboard_overview
overview = build_dashboard_overview(window)
set_cached_dashboard_overview(window, overview, refresh_interval_seconds)
return True
finally:
try:
lock.release()
except LockNotOwnedError:
logger.warning("Dashboard refresh lock expired before release: window=%s", window)