Fix potential timeline hangs from cycles and refresh cascades
Add cycle detection and O(n) path building to getAllBranches, and a concurrency guard on timeline refresh to drop overlapping calls. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -986,18 +986,22 @@ function getAncestorIds(snapshotId, parentOf) {
|
|||||||
|
|
||||||
function getAllBranches(tree) {
|
function getAllBranches(tree) {
|
||||||
const branches = [];
|
const branches = [];
|
||||||
|
const visited = new Set();
|
||||||
function walk(nodeId, path) {
|
function walk(nodeId, path) {
|
||||||
|
if (visited.has(nodeId)) return; // cycle detection
|
||||||
|
visited.add(nodeId);
|
||||||
const record = tree.byId.get(nodeId);
|
const record = tree.byId.get(nodeId);
|
||||||
if (!record) return;
|
if (!record) return;
|
||||||
const currentPath = [...path, record];
|
path.push(record);
|
||||||
const children = tree.childrenOf.get(nodeId);
|
const children = tree.childrenOf.get(nodeId);
|
||||||
if (!children || children.length === 0) {
|
if (!children || children.length === 0) {
|
||||||
branches.push(currentPath);
|
branches.push([...path]);
|
||||||
} else {
|
} else {
|
||||||
for (const child of children) {
|
for (const child of children) {
|
||||||
walk(child.id, currentPath);
|
walk(child.id, path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
path.pop();
|
||||||
}
|
}
|
||||||
for (const root of tree.roots) {
|
for (const root of tree.roots) {
|
||||||
walk(root.id, []);
|
walk(root.id, []);
|
||||||
@@ -3720,9 +3724,14 @@ function buildTimeline() {
|
|||||||
return marker;
|
return marker;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let refreshPending = false;
|
||||||
async function refresh() {
|
async function refresh() {
|
||||||
if (!showTimeline) return;
|
if (!showTimeline) return;
|
||||||
|
if (refreshPending) return; // drop overlapping calls
|
||||||
|
refreshPending = true;
|
||||||
|
try { await _refreshInner(); } finally { refreshPending = false; }
|
||||||
|
}
|
||||||
|
async function _refreshInner() {
|
||||||
const wfKey = getWorkflowKey();
|
const wfKey = getWorkflowKey();
|
||||||
|
|
||||||
// Hide/show expand button based on branching
|
// Hide/show expand button based on branching
|
||||||
|
|||||||
Reference in New Issue
Block a user