diff --git a/backend/main.py b/backend/main.py index 27539db..291be10 100644 --- a/backend/main.py +++ b/backend/main.py @@ -3,6 +3,7 @@ from fastapi.middleware.cors import CORSMiddleware import subprocess import time import json +import threading app = FastAPI() @@ -16,6 +17,7 @@ app.add_middleware( cache = {} CACHE_TTL = 300 # 5 minutes +cache_lock = threading.Lock() def run_kubectl(args, context=None): cmd = ["kubectl"] @@ -30,15 +32,45 @@ def get_cache_key(resource, namespace, context): def get_cached_items(resource, namespace, context): key = get_cache_key(resource, namespace, context) - if key in cache: - ts, items = cache[key] - if time.time() - ts < CACHE_TTL: - return items + with cache_lock: + if key in cache: + ts, items = cache[key] + if time.time() - ts < CACHE_TTL: + return items return None def set_cached_items(resource, namespace, context, items): key = get_cache_key(resource, namespace, context) - cache[key] = (time.time(), items) + with cache_lock: + cache[key] = (time.time(), items) + +def refresh_worker(resource, namespace, context, kubectl_args, item_mapper): + while True: + try: + result = run_kubectl(kubectl_args, context=context) + try: + obj = json.loads(result.stdout) + raw_items = obj.get("items", []) + except Exception: + raw_items = [] + items = [item_mapper(i) for i in raw_items] + set_cached_items(resource, namespace, context, items) + except Exception: + pass + time.sleep(240) # 4 minutes background renewal + +@app.on_event("startup") +def start_background_refresh(): + # Background renewal for common default namespace / no context + workers = [ + ("pods", "default", None, ["get", "pods", "-n", "default", "-o", "json"], lambda i: {"name": i.get("metadata", {}).get("name", "unknown"), "namespace": i.get("metadata", {}).get("namespace", "default")}), + ("nodes", "default", None, ["get", "nodes", "-o", "json"], lambda i: {"name": i.get("metadata", {}).get("name", "unknown"), "namespace": "-"}), + ("pvcs", "default", None, ["get", "pvc", "-n", "default", "-o", "json"], lambda i: {"name": i.get("metadata", {}).get("name", "unknown"), "namespace": i.get("metadata", {}).get("namespace", "default")}), + ("configmaps", "default", None, ["get", "configmaps", "-n", "default", "-o", "json"], lambda i: {"name": i.get("metadata", {}).get("name", "unknown"), "namespace": i.get("metadata", {}).get("namespace", "default")}), + ] + for res, ns, ctx, args, mapper in workers: + t = threading.Thread(target=refresh_worker, args=(res, ns, ctx, args, mapper), daemon=True) + t.start() @app.get("/") def root():