Skip to content

Commit 8a7f439

Browse files
lewisbirkstimja
andauthored
reduce rerenders from run times (#842)
Co-authored-by: Tim Jacomb <timjacomb1+github@gmail.com>
1 parent 7b35329 commit 8a7f439

File tree

11 files changed

+77
-32
lines changed

11 files changed

+77
-32
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { useEffect, useState } from "react";
2+
3+
import { Total } from "./timings.tsx";
4+
5+
export default function LiveTotal({
6+
total,
7+
start,
8+
}: {
9+
total: number | undefined;
10+
start: number;
11+
}) {
12+
const sinceStart = () => Date.now() - start;
13+
const [duration, setDuration] = useState<number>(total ?? sinceStart());
14+
useEffect(() => {
15+
if (total == null) {
16+
const interval = setInterval(() => {
17+
setDuration(sinceStart());
18+
}, 3001); // to match step polling interval
19+
return () => clearInterval(interval);
20+
} else {
21+
setDuration(total);
22+
}
23+
}, [total]);
24+
25+
return <Total ms={duration} />;
26+
}

src/main/frontend/common/utils/run-estimator.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@ export default class RunEstimator {
2727
if (previous === undefined) {
2828
return 0; // No previous run, so no estimate
2929
}
30-
const previousTiming = previous.totalDurationMillis;
31-
const currentTiming = stage.totalDurationMillis;
30+
const previousTiming = previous.totalDurationMillis!;
31+
const currentTiming =
32+
stage.totalDurationMillis ?? Date.now() - stage.startTimeMillis;
3233
if (previousTiming <= currentTiming) {
3334
return 99; // Assume 99% complete if the previous run was longer than the current run
3435
}

src/main/frontend/pipeline-console-view/pipeline-console/main/ConsoleLogCard.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import StatusIcon from "../../../common/components/status-icon.tsx";
1111
import Tooltip from "../../../common/components/tooltip.tsx";
1212
import { LocalizedMessageKey, useMessages } from "../../../common/i18n";
1313
import { classNames } from "../../../common/utils/classnames.ts";
14-
import { Total } from "../../../common/utils/timings.tsx";
14+
import LiveTotal from "../../../common/utils/live-total.tsx";
1515
import {
1616
LOG_FETCH_SIZE,
1717
StepInfo,
@@ -122,7 +122,10 @@ export default function ConsoleLogCard(props: ConsoleLogCardProps) {
122122
fontWeight: "normal",
123123
}}
124124
>
125-
<Total ms={props.step.totalDurationMillis} />
125+
<LiveTotal
126+
total={props.step.totalDurationMillis}
127+
start={props.step.startTimeMillis}
128+
/>
126129
</span>
127130
</div>
128131
</a>

src/main/frontend/pipeline-console-view/pipeline-console/main/DataTreeView.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
import Filter from "../../../common/components/filter.tsx";
1212
import StatusIcon from "../../../common/components/status-icon.tsx";
1313
import { classNames } from "../../../common/utils/classnames.ts";
14-
import { Total } from "../../../common/utils/timings.tsx";
14+
import LiveTotal from "../../../common/utils/live-total.tsx";
1515
import {
1616
Result,
1717
StageInfo,
@@ -190,7 +190,10 @@ const TreeNode = memo(function TreeNode({
190190
{stage.name}
191191
</div>
192192
<div className="pgv-tree-item__description">
193-
<Total ms={stage.totalDurationMillis} />
193+
<LiveTotal
194+
start={stage.startTimeMillis}
195+
total={stage.totalDurationMillis}
196+
/>
194197
</div>
195198
</div>
196199
</div>

src/main/frontend/pipeline-console-view/pipeline-console/main/stage-details.tsx

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,8 @@ import StatusIcon, {
66
} from "../../../common/components/status-icon.tsx";
77
import { DOCUMENT } from "../../../common/components/symbols.tsx";
88
import Tooltip from "../../../common/components/tooltip.tsx";
9-
import {
10-
exact,
11-
Paused,
12-
Started,
13-
Total,
14-
} from "../../../common/utils/timings.tsx";
9+
import LiveTotal from "../../../common/utils/live-total.tsx";
10+
import { exact, Paused, Started } from "../../../common/utils/timings.tsx";
1511
import { StageInfo } from "../../../pipeline-graph-view/pipeline-graph/main/PipelineGraphModel.tsx";
1612
import StageNodeLink from "./StageNodeLink.tsx";
1713

@@ -39,7 +35,11 @@ export default function StageDetails({ stage }: StageDetailsProps) {
3935
</div>
4036
<ul>
4137
<li>
42-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
38+
<svg
39+
xmlns="http://www.w3.org/2000/svg"
40+
viewBox="0 0 512 512"
41+
aria-label={"Total duration"}
42+
>
4343
<path
4444
d="M112.91 128A191.85 191.85 0 0064 254c-1.18 106.35 85.65 193.8 192 194 106.2.2 192-85.83 192-192 0-104.54-83.55-189.61-187.5-192a4.36 4.36 0 00-4.5 4.37V152"
4545
fill="none"
@@ -53,7 +53,10 @@ export default function StageDetails({ stage }: StageDetailsProps) {
5353
fill="currentColor"
5454
/>
5555
</svg>
56-
<Total ms={stage.totalDurationMillis} />
56+
<LiveTotal
57+
total={stage.totalDurationMillis}
58+
start={stage.startTimeMillis}
59+
/>
5760
</li>
5861
<li>
5962
<Tooltip content={exact(stage.startTimeMillis)}>

src/main/frontend/pipeline-graph-view/pipeline-graph/main/PipelineGraphLayout.ts

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -401,20 +401,13 @@ function createTimings(
401401
}
402402
const stage = column.topStage;
403403

404-
const text = stage?.totalDurationMillis + "";
405-
if (!text) {
406-
// shouldn't happen
407-
continue;
408-
}
409-
const key = "l_t_" + node.key;
410-
411404
labels.push({
412405
x: column.centerX,
413406
y: node.y + 55,
414407
node,
415408
stage,
416-
text,
417-
key,
409+
text: "", // we take the duration from the stage itself at render time
410+
key: `l_t_${node.key}`,
418411
});
419412
}
420413

src/main/frontend/pipeline-graph-view/pipeline-graph/main/PipelineGraphModel.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export interface StageInfo {
5151
synthetic?: boolean;
5252
pauseDurationMillis: number;
5353
startTimeMillis: number;
54-
totalDurationMillis: number;
54+
totalDurationMillis?: number; // will be null if the stage is still running
5555
agent: string;
5656
url: string;
5757

src/main/frontend/pipeline-graph-view/pipeline-graph/main/support/labels.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { CSSProperties } from "react";
22

3-
import { Total } from "../../../../common/utils/timings.tsx";
3+
import LiveTotal from "../../../../common/utils/live-total.tsx";
44
import { sequentialStagesLabelOffset } from "../PipelineGraphLayout.ts";
55
import { LayoutInfo, NodeLabelInfo } from "../PipelineGraphModel.tsx";
66
import { TooltipLabel } from "./convertLabelToTooltip.tsx";
@@ -124,7 +124,10 @@ export function TimingsLabel({
124124

125125
return (
126126
<div className={classNames.join(" ")} style={style} key={details.key}>
127-
<Total ms={parseInt(details.text, 10)} />
127+
<LiveTotal
128+
total={details.stage?.totalDurationMillis}
129+
start={details.stage?.startTimeMillis ?? Date.now()}
130+
/>
128131
</div>
129132
);
130133
}

src/main/frontend/pipeline-graph-view/pipeline-graph/main/support/nodes.tsx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import StatusIcon, {
77
} from "../../../../common/components/status-icon.tsx";
88
import Tooltip from "../../../../common/components/tooltip.tsx";
99
import { classNames } from "../../../../common/utils/classnames.ts";
10-
import { Total } from "../../../../common/utils/timings.tsx";
10+
import LiveTotal from "../../../../common/utils/live-total.tsx";
1111
import { CounterNodeInfo } from "../PipelineGraphLayout.ts";
1212
import {
1313
LayoutInfo,
@@ -58,7 +58,10 @@ export function Node({
5858
/>
5959
{stage.name}
6060
<span style={{ color: "var(--text-color-secondary)" }}>
61-
<Total ms={stage.totalDurationMillis} />
61+
<LiveTotal
62+
total={stage.totalDurationMillis}
63+
start={stage.startTimeMillis}
64+
/>
6265
</span>
6366
</a>
6467
</li>
@@ -143,14 +146,20 @@ export function Node({
143146
<div className="pgv-node-tooltip">
144147
<div>{title}</div>
145148
<div>
146-
<Total ms={node.stage.totalDurationMillis} />
149+
<LiveTotal
150+
total={node.stage.totalDurationMillis}
151+
start={node.stage.startTimeMillis}
152+
/>
147153
</div>
148154
</div>
149155
);
150156
} else {
151157
tooltip = (
152158
<div className="pgv-node-tooltip">
153-
<Total ms={node.stage.totalDurationMillis} />
159+
<LiveTotal
160+
total={node.stage.totalDurationMillis}
161+
start={node.stage.startTimeMillis}
162+
/>
154163
</div>
155164
);
156165
}

src/main/java/io/jenkins/plugins/pipelinegraphview/utils/AbstractPipelineNode.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ public long getStartTimeMillis() {
3333
return timingInfo.getStartTimeMillis();
3434
}
3535

36-
public long getTotalDurationMillis() {
37-
return totalDurationMillis;
36+
public Long getTotalDurationMillis() {
37+
return state.isInProgress() ? null : totalDurationMillis;
3838
}
3939

4040
public String getId() {

0 commit comments

Comments
 (0)