73 lines
1.8 KiB
Python
73 lines
1.8 KiB
Python
"""Redis-backed live render log for streaming task progress.
|
|
|
|
Each order line gets a Redis list keyed by render:log:{order_line_id}.
|
|
Entries are JSON objects with timestamp, level, and message.
|
|
Lists auto-expire after 1 hour.
|
|
"""
|
|
import json
|
|
import time
|
|
import logging
|
|
|
|
import redis
|
|
|
|
from app.config import settings
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
_LOG_TTL = 3600 # 1 hour
|
|
_MAX_ENTRIES = 500
|
|
|
|
|
|
def _redis() -> redis.Redis:
|
|
return redis.from_url(settings.redis_url, decode_responses=True)
|
|
|
|
|
|
def _key(order_line_id: str) -> str:
|
|
return f"render:log:{order_line_id}"
|
|
|
|
|
|
def emit(order_line_id: str, message: str, level: str = "info") -> None:
|
|
"""Push a log entry for a render job."""
|
|
entry = json.dumps({
|
|
"ts": time.time(),
|
|
"t": time.strftime("%H:%M:%S", time.gmtime()),
|
|
"level": level,
|
|
"msg": message,
|
|
})
|
|
try:
|
|
r = _redis()
|
|
key = _key(order_line_id)
|
|
r.rpush(key, entry)
|
|
r.ltrim(key, -_MAX_ENTRIES, -1)
|
|
r.expire(key, _LOG_TTL)
|
|
except Exception as exc:
|
|
logger.debug(f"render_log emit failed: {exc}")
|
|
|
|
|
|
def get_entries(order_line_id: str, after_index: int = 0) -> list[dict]:
|
|
"""Get log entries starting from after_index."""
|
|
try:
|
|
r = _redis()
|
|
raw = r.lrange(_key(order_line_id), after_index, -1)
|
|
return [json.loads(e) for e in raw]
|
|
except Exception:
|
|
return []
|
|
|
|
|
|
def count(order_line_id: str) -> int:
|
|
"""Get the number of log entries."""
|
|
try:
|
|
r = _redis()
|
|
return r.llen(_key(order_line_id))
|
|
except Exception:
|
|
return 0
|
|
|
|
|
|
def clear(order_line_id: str) -> None:
|
|
"""Clear log entries for a render job."""
|
|
try:
|
|
r = _redis()
|
|
r.delete(_key(order_line_id))
|
|
except Exception:
|
|
pass
|