Adding the new rewrite
This commit is contained in:
1 parent
4aca9f08d1
commit
9b48b01d1d
62 files changed
+4510
-1406
No files matched your search
+30
-19
@@ -1,51 +1,62 @@
|
||||
from __future__ import annotations
|
||||
import asyncio
|
||||
import time
|
||||
from typing import Dict, Any, List
|
||||
import redis
|
||||
import json
|
||||
import os
|
||||
|
||||
REDIS_URL = os.environ.get("REDIS_URL", "redis://redis:6379/0")
|
||||
import json
|
||||
import time
|
||||
from typing import Any
|
||||
|
||||
import redis
|
||||
|
||||
from .settings import settings
|
||||
|
||||
RETENTION_SECONDS = 7 * 24 * 3600
|
||||
MAX_SAMPLES_PER_UPS = 7 * 24 * 60 * 2 # assume worst-case 30s interval -> ~20160 entries
|
||||
MAX_SAMPLES_PER_UPS = 7 * 24 * 60 * 2 # worst-case ~30s interval
|
||||
|
||||
_redis: redis.Redis | None = None
|
||||
|
||||
|
||||
def get_redis() -> redis.Redis:
|
||||
global _redis
|
||||
if _redis:
|
||||
return _redis
|
||||
_redis = redis.Redis.from_url(REDIS_URL, decode_responses=True)
|
||||
_redis = redis.Redis.from_url(settings.redis_url, decode_responses=True)
|
||||
return _redis
|
||||
|
||||
SNAP_KEY_PREFIX = "ups:snap:" # latest hash per ups
|
||||
HIST_KEY_PREFIX = "ups:hist:" # time-series list per ups (append JSON)
|
||||
|
||||
async def store_snapshot(ups_name: str, data: Dict[str, Any]):
|
||||
def reset_redis_client() -> None:
|
||||
"""Test hook - clears cached Redis connection."""
|
||||
global _redis
|
||||
_redis = None
|
||||
|
||||
|
||||
SNAP_KEY_PREFIX = "ups:snap:"
|
||||
HIST_KEY_PREFIX = "ups:hist:"
|
||||
|
||||
|
||||
async def store_snapshot(ups_name: str, data: dict[str, Any]):
|
||||
r = get_redis()
|
||||
ts = int(time.time())
|
||||
pipe = r.pipeline()
|
||||
# store latest snapshot (hash)
|
||||
pipe.hset(f"{SNAP_KEY_PREFIX}{ups_name}", mapping={**data, "_ts": ts})
|
||||
# append to history list
|
||||
hist_key = f"{HIST_KEY_PREFIX}{ups_name}"
|
||||
pipe.rpush(hist_key, json.dumps({"ts": ts, "data": data}))
|
||||
pipe.ltrim(hist_key, -MAX_SAMPLES_PER_UPS, -1)
|
||||
# add pruning via async task (length-based + time-based)
|
||||
pipe.execute()
|
||||
|
||||
async def get_latest(ups_name: str) -> Dict[str, Any] | None:
|
||||
|
||||
async def get_latest(ups_name: str) -> dict[str, Any] | None:
|
||||
r = get_redis()
|
||||
h = r.hgetall(f"{SNAP_KEY_PREFIX}{ups_name}")
|
||||
return h or None
|
||||
|
||||
async def get_history(ups_name: str, since_seconds: int = RETENTION_SECONDS) -> List[Dict[str, Any]]:
|
||||
|
||||
async def get_history(
|
||||
ups_name: str, since_seconds: int = RETENTION_SECONDS
|
||||
) -> list[dict[str, Any]]:
|
||||
r = get_redis()
|
||||
key = f"{HIST_KEY_PREFIX}{ups_name}"
|
||||
raw = r.lrange(key, 0, -1)
|
||||
now = int(time.time())
|
||||
out: List[Dict[str, Any]] = []
|
||||
out: list[dict[str, Any]] = []
|
||||
for item in raw:
|
||||
try:
|
||||
obj = json.loads(item)
|
||||
@@ -55,12 +66,12 @@ async def get_history(ups_name: str, since_seconds: int = RETENTION_SECONDS) ->
|
||||
out.append(obj)
|
||||
return out
|
||||
|
||||
|
||||
async def prune_old():
|
||||
r = get_redis()
|
||||
now = int(time.time())
|
||||
cutoff = now - RETENTION_SECONDS
|
||||
for key in r.scan_iter(f"{HIST_KEY_PREFIX}*"):
|
||||
# prune from left while older than cutoff
|
||||
while True:
|
||||
item = r.lindex(key, 0)
|
||||
if not item:
|
||||
|
||||
Reference in new issue
Block a user