Skip to content

Commit bb19985

Browse files
authored
Fix tailing in stage (#1133)
1 parent cccc415 commit bb19985

File tree

1 file changed

+49
-32
lines changed

1 file changed

+49
-32
lines changed

src/main/frontend/pipeline-console-view/pipeline-console/main/hooks/use-steps-poller.ts

Lines changed: 49 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -176,23 +176,45 @@ export function useStepsPoller(props: RunPollerProps) {
176176
run.stages = refreshStagesFromSteps(run.stages, steps);
177177

178178
const [openStageId, setOpenStageId] = useState("");
179+
const openStage = useMemo(() => {
180+
const findStage = (stages: StageInfo[]): StageInfo | null => {
181+
for (const stage of stages) {
182+
if (String(stage.id) === openStageId) return stage;
183+
if (stage.children.length > 0) {
184+
const result = findStage(stage.children);
185+
if (result) return result;
186+
}
187+
}
188+
return null;
189+
};
190+
return openStageId ? findStage(run.stages) : null;
191+
}, [run.stages, openStageId]);
179192
const [expandedSteps, setExpandedSteps] = useState<string[]>([]);
180193
const collapsedSteps = useRef(new Set<string>());
181-
const currentDefaultStep = useRef("");
194+
const tailStep = useRef("");
182195

183196
const [tailLogs, setTailLogs] = useState(true);
197+
const [tailStage, setTailStage] = useState("");
184198
// Make the latest tailLogs state available without a re-render.
185199
const tailLogsRef = useRef(tailLogs);
186200
const startTailingLogs = useCallback(() => {
187201
history.replaceState({}, "", "?"); // Unset query parameters.
188202
scrollToStepOnce.current = ""; // Unset from manually selected node.
189203
tailLogsRef.current = true;
190204
setTailLogs(true);
191-
}, []);
205+
if (openStage?.state === "running") {
206+
// Keep tailing in the current stage.
207+
setTailStage(openStageId);
208+
} else {
209+
// Select the next best stage using the default step.
210+
setTailStage("");
211+
}
212+
}, [openStageId, openStage?.state]);
192213
const stopTailingLogs = useCallback(() => {
193214
scrollToStepOnce.current = "";
194215
tailLogsRef.current = false;
195216
setTailLogs(false);
217+
setTailStage("");
196218
}, []);
197219

198220
// "scroll" events do not have a flag for telling "user has scrolled" vs programmatic "element.scrollIntoView()" apart.
@@ -241,7 +263,7 @@ export function useStepsPoller(props: RunPollerProps) {
241263
const scrollToTail = useCallback(
242264
(stepId: string, element: HTMLDivElement) => {
243265
const scrollDefaultStep =
244-
tailLogsRef.current && stepId === currentDefaultStep.current;
266+
tailLogsRef.current && stepId === tailStep.current;
245267
if (!scrollDefaultStep) {
246268
if (stepId !== scrollToStepOnce.current) return;
247269
const stepBuffer = stepBuffersRef.current.get(stepId);
@@ -325,32 +347,41 @@ export function useStepsPoller(props: RunPollerProps) {
325347
}, [steps, expandLastStageStep, stopTailingLogs]);
326348

327349
useEffect(() => {
328-
const defaultStep = getDefaultSelectedStep(steps, runIsComplete);
350+
let defaultStep;
351+
if (tailStage) {
352+
defaultStep = steps.filter((s) => s.stageId === tailStage).pop() || null;
353+
if (
354+
defaultStep &&
355+
defaultStep.state !== "running" &&
356+
stepBuffersRef.current.get(defaultStep.id)?.stopTailing
357+
) {
358+
// Tailed in full. Let the user resume tailing in another stage.
359+
stopTailingLogs();
360+
}
361+
} else {
362+
defaultStep = getDefaultSelectedStep(steps, runIsComplete);
363+
}
329364
if (!defaultStep) return;
330-
currentDefaultStep.current = defaultStep.id;
365+
tailStep.current = defaultStep.id;
331366
if (!tailLogsRef.current) return;
332367
setOpenStageId(defaultStep.stageId);
333368
if (collapsedSteps.current.has(defaultStep.id)) return;
334369
setExpandedSteps((prev) => {
335370
if (prev.includes(defaultStep.id)) return prev;
336371
return [...prev, defaultStep.id];
337372
});
338-
}, [steps, tailLogs, runIsComplete]);
373+
}, [steps, tailLogs, runIsComplete, tailStage, stopTailingLogs]);
339374

340-
const handleStageSelect = useCallback(
341-
(nodeId: string) => {
342-
stopTailingLogs();
343-
344-
if (!nodeId) return;
345-
if (nodeId === openStageId) return; // skip if already selected
375+
const handleStageSelect = useCallback((nodeId: string) => {
376+
if (!nodeId) return;
346377

378+
setTailStage(nodeId);
379+
setOpenStageId((openStageId) => {
380+
if (nodeId === openStageId) return openStageId; // skip if already selected
347381
history.replaceState({}, "", `?selected-node=` + nodeId);
348-
349-
setOpenStageId(nodeId);
350-
expandLastStageStep(steps, nodeId);
351-
},
352-
[openStageId, steps, stopTailingLogs, expandLastStageStep],
353-
);
382+
return nodeId;
383+
});
384+
}, []);
354385

355386
const onStepToggle = useCallback(
356387
(nodeId: string) => {
@@ -372,20 +403,6 @@ export function useStepsPoller(props: RunPollerProps) {
372403
return steps.filter((step) => step.stageId === openStageId);
373404
}, [steps, openStageId]);
374405

375-
const openStage = useMemo(() => {
376-
const findStage = (stages: StageInfo[]): StageInfo | null => {
377-
for (const stage of stages) {
378-
if (String(stage.id) === openStageId) return stage;
379-
if (stage.children.length > 0) {
380-
const result = findStage(stage.children);
381-
if (result) return result;
382-
}
383-
}
384-
return null;
385-
};
386-
return openStageId ? findStage(run.stages) : null;
387-
}, [run.stages, openStageId]);
388-
389406
return {
390407
openStage,
391408
openStageSteps,

0 commit comments

Comments
 (0)