Remove full graph node cap
Some checks failed
docker-build / build (push) Has been cancelled

This commit is contained in:
knight 2025-11-20 09:42:14 -05:00
parent 82c334b131
commit b0c9d319ef
2 changed files with 42 additions and 17 deletions

View File

@ -745,7 +745,7 @@ def create_app(config: AppConfig = CONFIG) -> Flask:
} }
def build_full_graph_payload( def build_full_graph_payload(
max_nodes: int, *, highlight_id: Optional[str] = None max_nodes: Optional[int], *, highlight_id: Optional[str] = None
) -> Dict[str, Any]: ) -> Dict[str, Any]:
""" """
Attempt to render the entire reference graph by gathering every video that Attempt to render the entire reference graph by gathering every video that
@ -776,7 +776,8 @@ def create_app(config: AppConfig = CONFIG) -> Flask:
nodes: Dict[str, Dict[str, Any]] = {} nodes: Dict[str, Dict[str, Any]] = {}
links: List[Dict[str, Any]] = [] links: List[Dict[str, Any]] = []
link_seen: Set[Tuple[str, str, str]] = set() link_seen: Set[Tuple[str, str, str]] = set()
batch_size = min(500, max(50, max_nodes * 2)) node_limit = max_nodes if max_nodes and max_nodes > 0 else None
batch_size = 500 if node_limit is None else min(500, max(50, node_limit * 2))
truncated = False truncated = False
def ensure_node(node_id: Optional[str], doc: Optional[Dict[str, Any]] = None) -> bool: def ensure_node(node_id: Optional[str], doc: Optional[Dict[str, Any]] = None) -> bool:
@ -799,7 +800,7 @@ def create_app(config: AppConfig = CONFIG) -> Flask:
if not existing.get("date") and doc.get("date"): if not existing.get("date") and doc.get("date"):
existing["date"] = doc.get("date") existing["date"] = doc.get("date")
return True return True
if len(nodes) >= max_nodes: if node_limit is not None and len(nodes) >= node_limit:
return False return False
channel_name = None channel_name = None
channel_id = None channel_id = None
@ -836,7 +837,7 @@ def create_app(config: AppConfig = CONFIG) -> Flask:
if not hits: if not hits:
break break
for hit in hits: for hit in hits:
if len(nodes) >= max_nodes: if node_limit is not None and len(nodes) >= node_limit:
truncated = True truncated = True
stop_fetch = True stop_fetch = True
break break
@ -996,14 +997,17 @@ def create_app(config: AppConfig = CONFIG) -> Flask:
depth = 1 depth = 1
depth = max(0, min(depth, 3)) depth = max(0, min(depth, 3))
try: if full_graph:
max_nodes = int(request.args.get("max_nodes", "200")) max_nodes = None
except ValueError: else:
max_nodes = 200 try:
max_nodes = max(10, min(max_nodes, 800 if full_graph else 400)) max_nodes = int(request.args.get("max_nodes", "200"))
except ValueError:
max_nodes = 200
max_nodes = max(10, min(max_nodes, 400))
if full_graph: if full_graph:
payload = build_full_graph_payload(max_nodes, highlight_id=video_id or None) payload = build_full_graph_payload(None, highlight_id=video_id or None)
else: else:
payload = build_graph_payload(video_id, depth, max_nodes) payload = build_graph_payload(video_id, depth, max_nodes)
if not payload["nodes"]: if not payload["nodes"]:
@ -1011,7 +1015,9 @@ def create_app(config: AppConfig = CONFIG) -> Flask:
jsonify({"error": f"Video '{video_id}' was not found in the index."}), jsonify({"error": f"Video '{video_id}' was not found in the index."}),
404, 404,
) )
payload["meta"]["max_nodes"] = max_nodes payload["meta"]["max_nodes"] = (
len(payload["nodes"]) if full_graph else max_nodes
)
return jsonify(payload) return jsonify(payload)
@app.route("/api/years") @app.route("/api/years")

View File

@ -135,6 +135,7 @@
let currentMaxNodes = sanitizeMaxNodes(maxNodesInput.value); let currentMaxNodes = sanitizeMaxNodes(maxNodesInput.value);
let currentSimulation = null; let currentSimulation = null;
let currentFullGraph = false; let currentFullGraph = false;
let previousMaxNodesValue = maxNodesInput ? maxNodesInput.value : "200";
function setStatus(message, isError = false) { function setStatus(message, isError = false) {
if (!statusEl) return; if (!statusEl) return;
@ -165,6 +166,18 @@
if (depthInput) { if (depthInput) {
depthInput.disabled = enabled; depthInput.disabled = enabled;
} }
if (maxNodesInput) {
if (enabled) {
previousMaxNodesValue = maxNodesInput.value || previousMaxNodesValue || "200";
maxNodesInput.value = "0";
maxNodesInput.disabled = true;
} else {
if (maxNodesInput.disabled) {
maxNodesInput.value = previousMaxNodesValue || "200";
}
maxNodesInput.disabled = false;
}
}
if (videoInput) { if (videoInput) {
if (enabled) { if (enabled) {
videoInput.removeAttribute("required"); videoInput.removeAttribute("required");
@ -181,10 +194,11 @@
} }
if (fullGraphMode) { if (fullGraphMode) {
params.set("full_graph", "1"); params.set("full_graph", "1");
params.set("max_nodes", "0");
} else { } else {
params.set("depth", String(depth)); params.set("depth", String(depth));
params.set("max_nodes", String(maxNodes));
} }
params.set("max_nodes", String(maxNodes));
const response = await fetch(`/api/graph?${params.toString()}`); const response = await fetch(`/api/graph?${params.toString()}`);
if (!response.ok) { if (!response.ok) {
const errorPayload = await response.json().catch(() => ({})); const errorPayload = await response.json().catch(() => ({}));
@ -445,8 +459,8 @@
setStatus("Please enter a video ID.", true); setStatus("Please enter a video ID.", true);
return; return;
} }
const safeDepth = wantsFull ? 0 : sanitizeDepth(depth); const safeDepth = wantsFull ? currentDepth || 1 : sanitizeDepth(depth);
const safeMaxNodes = sanitizeMaxNodes(maxNodes); const safeMaxNodes = wantsFull ? 0 : sanitizeMaxNodes(maxNodes);
if (updateInputs) { if (updateInputs) {
videoInput.value = sanitizedId; videoInput.value = sanitizedId;
@ -630,11 +644,12 @@
if (fullGraphMode) { if (fullGraphMode) {
next.searchParams.set("full_graph", "1"); next.searchParams.set("full_graph", "1");
next.searchParams.delete("depth"); next.searchParams.delete("depth");
next.searchParams.set("max_nodes", "0");
} else { } else {
next.searchParams.set("depth", String(depth)); next.searchParams.set("depth", String(depth));
next.searchParams.delete("full_graph"); next.searchParams.delete("full_graph");
next.searchParams.set("max_nodes", String(maxNodes));
} }
next.searchParams.set("max_nodes", String(maxNodes));
if (labelSize && labelSize !== "normal") { if (labelSize && labelSize !== "normal") {
next.searchParams.set("label_size", labelSize); next.searchParams.set("label_size", labelSize);
} else { } else {
@ -647,7 +662,11 @@
const params = new URLSearchParams(window.location.search); const params = new URLSearchParams(window.location.search);
const videoId = sanitizeId(params.get("video_id")); const videoId = sanitizeId(params.get("video_id"));
const depth = sanitizeDepth(params.get("depth") || ""); const depth = sanitizeDepth(params.get("depth") || "");
const maxNodes = sanitizeMaxNodes(params.get("max_nodes") || ""); const rawMaxNodes = params.get("max_nodes");
let maxNodes = sanitizeMaxNodes(rawMaxNodes || "");
if (rawMaxNodes && rawMaxNodes.trim() === "0") {
maxNodes = 0;
}
const labelSizeParam = params.get("label_size"); const labelSizeParam = params.get("label_size");
const fullGraphParam = params.get("full_graph"); const fullGraphParam = params.get("full_graph");
const viewFull = const viewFull =
@ -656,7 +675,7 @@
videoInput.value = videoId; videoInput.value = videoId;
} }
depthInput.value = String(depth); depthInput.value = String(depth);
maxNodesInput.value = String(maxNodes); maxNodesInput.value = String(viewFull ? 0 : maxNodes);
if (fullGraphToggle) { if (fullGraphToggle) {
fullGraphToggle.checked = !!viewFull; fullGraphToggle.checked = !!viewFull;
} }