v9.13: restore stream_instances endpoint (accidentally removed in v9.12)

This commit is contained in:
Naeel
2026-04-16 15:54:35 +03:00
parent 2813d52d3b
commit a662be9c12
2 changed files with 54 additions and 1 deletions
+1 -1
View File
@@ -15,7 +15,7 @@ spec:
spec:
containers:
- name: cloud-dashboard
image: naeel/cloud-dashboard:v9.12
image: naeel/cloud-dashboard:v9.13
imagePullPolicy: Always
ports:
- containerPort: 8080
+53
View File
@@ -1,8 +1,10 @@
from fastapi import FastAPI, Header, HTTPException, Request
from fastapi.responses import StreamingResponse
from fastapi.staticfiles import StaticFiles
import httpx
from typing import Annotated
import asyncio
import json
import time
app = FastAPI()
@@ -256,6 +258,57 @@ async def get_graph(
}
@app.get("/api/instances/stream")
async def stream_instances(
request: Request,
x_deck_token: Annotated[str | None, Header()] = None,
x_deck_env: Annotated[str | None, Header()] = None,
):
if not x_deck_token:
raise HTTPException(status_code=401, detail="Token required")
_, deck_api = resolve_deck_api(x_deck_env)
all_instances = await fetch_all_instances(x_deck_token, deck_api)
uid_to_inst = {
i.get("instanceUid"): i
for i in all_instances
if i.get("instanceUid")
}
async def generate():
sem = asyncio.Semaphore(20)
queue: asyncio.Queue = asyncio.Queue()
total = len(uid_to_inst)
async def fetch_one(uid: str, client: httpx.AsyncClient):
async with sem:
try:
r = await client.get(
f"{deck_api}/index.cfm/instances/{uid}",
headers=auth_headers(x_deck_token),
)
detail = None if r.status_code >= 400 else r.json().get("instance")
except Exception:
detail = None
await queue.put((uid, detail))
async with httpx.AsyncClient(timeout=25) as shared_client:
tasks = [
asyncio.create_task(fetch_one(uid, shared_client))
for uid in uid_to_inst
]
for _ in range(total):
uid, detail = await queue.get()
row = dict(uid_to_inst.get(uid, {}))
if detail:
row["_detail"] = detail
yield json.dumps(row, ensure_ascii=False) + "\n"
yield json.dumps({"_done": True, "total": total}, ensure_ascii=False) + "\n"
return StreamingResponse(generate(), media_type="application/x-ndjson")
@app.get("/api/instances/{uid}")
async def get_instance(
request: Request,