VNEWS / shorts_cache.py
bep40's picture
Add shorts_cache.py - runtime cache module for external updater
8bea5bd verified
Raw
History Blame
2.85 kB
"""
VNEWS Shorts Runtime Cache - External Updater Module
GitHub Actions fetches YouTube shorts via yt-dlp -> POST to /api/shorts/update
Space saves to RAM cache + persistent file if /data available
"""
import os
import json
import time
import threading
# Runtime cache (RAM)
_shorts_runtime_cache = None
_shorts_cache_ts = 0
_shorts_cache_lock = threading.Lock()
# Secret for authenticating update requests
SHORTS_UPDATE_SECRET = os.environ.get("SHORTS_UPDATE_SECRET", "vnews-shorts-2026")
# Paths
SHORTS_CACHE_FILE = "/data/shorts_runtime_cache.json" if os.path.isdir("/data") else "/app/shorts_runtime_cache.json"
def get_runtime_cache():
"""Get cached shorts (from RAM or file fallback)"""
global _shorts_runtime_cache, _shorts_cache_ts
with _shorts_cache_lock:
if _shorts_runtime_cache is not None:
age = time.time() - _shorts_cache_ts
if age < 7200: # 2h fresh
return _shorts_runtime_cache
# Try file fallback
try:
if os.path.exists(SHORTS_CACHE_FILE):
with open(SHORTS_CACHE_FILE, "r", encoding="utf-8") as f:
data = json.load(f)
age = time.time() - data.get("ts", 0)
if age < 86400: # 24h stale limit
items = data.get("items", [])
with _shorts_cache_lock:
_shorts_runtime_cache = items
_shorts_cache_ts = data.get("ts", time.time())
return items
except Exception as e:
print(f"[cache] read error: {e}")
return None
def set_runtime_cache(items):
"""Update runtime cache from external data"""
global _shorts_runtime_cache, _shorts_cache_ts
ts = time.time()
with _shorts_cache_lock:
_shorts_runtime_cache = items
_shorts_cache_ts = ts
# Also write to file (persistent if /data mounted)
try:
os.makedirs(os.path.dirname(SHORTS_CACHE_FILE), exist_ok=True)
payload = {"items": items, "ts": ts, "count": len(items)}
with open(SHORTS_CACHE_FILE, "w", encoding="utf-8") as f:
json.dump(payload, f, ensure_ascii=False, indent=2)
print(f"[cache] saved {len(items)} shorts to {SHORTS_CACHE_FILE}")
except Exception as e:
print(f"[cache] write skipped: {e}")
return len(items)
def get_cache_status():
"""Return status dict for the cache"""
cache = None
with _shorts_cache_lock:
if _shorts_runtime_cache is not None:
cache = _shorts_runtime_cache
age = int(time.time() - _shorts_cache_ts)
else:
age = -1
return {
"cached": cache is not None,
"count": len(cache) if cache else 0,
"age_seconds": age,
"has_persistent": os.path.isdir("/data"),
"cache_file_exists": os.path.exists(SHORTS_CACHE_FILE),
}