feat: add background renewal caching with 5m ttl
Co-authored-by: aider (openrouter/thinkingmachines/inkling-small:free) <aider@aider.chat>
This commit is contained in:
1 parent
ea86194ce8
commit
5d10b660d6
1 file changed
+37
-5
+37
-5
@@ -3,6 +3,7 @@ from fastapi.middleware.cors import CORSMiddleware
|
|||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
import json
|
import json
|
||||||
|
import threading
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
|
|
||||||
@@ -16,6 +17,7 @@ app.add_middleware(
|
|||||||
|
|
||||||
cache = {}
|
cache = {}
|
||||||
CACHE_TTL = 300 # 5 minutes
|
CACHE_TTL = 300 # 5 minutes
|
||||||
|
cache_lock = threading.Lock()
|
||||||
|
|
||||||
def run_kubectl(args, context=None):
|
def run_kubectl(args, context=None):
|
||||||
cmd = ["kubectl"]
|
cmd = ["kubectl"]
|
||||||
@@ -30,15 +32,45 @@ def get_cache_key(resource, namespace, context):
|
|||||||
|
|
||||||
def get_cached_items(resource, namespace, context):
|
def get_cached_items(resource, namespace, context):
|
||||||
key = get_cache_key(resource, namespace, context)
|
key = get_cache_key(resource, namespace, context)
|
||||||
if key in cache:
|
with cache_lock:
|
||||||
ts, items = cache[key]
|
if key in cache:
|
||||||
if time.time() - ts < CACHE_TTL:
|
ts, items = cache[key]
|
||||||
return items
|
if time.time() - ts < CACHE_TTL:
|
||||||
|
return items
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def set_cached_items(resource, namespace, context, items):
|
def set_cached_items(resource, namespace, context, items):
|
||||||
key = get_cache_key(resource, namespace, context)
|
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("/")
|
@app.get("/")
|
||||||
def root():
|
def root():
|
||||||
|
|||||||
Reference in new issue
Block a user