From 3ad50eef9d5488a470379d94de38a7934cb9e4bc Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Sat, 27 Sep 2025 08:48:01 +0000 Subject: [PATCH] fix: improve performance of flow viewer --- .../FlowLoopIterationPreview.svelte | 6 +- .../lib/components/FlowStatusViewer.svelte | 2 +- .../components/flows/FlowProgressBar.svelte | 50 ++++--- .../graph/renderers/edges/EmptyEdge.svelte | 45 ++++--- .../components/progressBar/ProgressBar.svelte | 123 ++++++++++-------- 5 files changed, 132 insertions(+), 94 deletions(-) diff --git a/frontend/src/lib/components/FlowLoopIterationPreview.svelte b/frontend/src/lib/components/FlowLoopIterationPreview.svelte index 6c296d0804..7c9bc78fa0 100644 --- a/frontend/src/lib/components/FlowLoopIterationPreview.svelte +++ b/frontend/src/lib/components/FlowLoopIterationPreview.svelte @@ -67,7 +67,7 @@ let selectedJobStep: string | undefined = $state(undefined) let isRunning: boolean = $state(false) - let jobProgressReset: (() => void) | undefined = $state(undefined) + let progressBar: FlowProgressBar | undefined = $state(undefined) export function test() { runPreview(previewArgs, undefined) @@ -80,7 +80,7 @@ args: Record, restartedFrom: RestartedFrom | undefined ) { - jobProgressReset?.() + progressBar?.reset() const newFlow = { value: { modules }, summary: '' } jobId = await runFlowPreview(args, newFlow, $pathStore, restartedFrom) isRunning = true @@ -161,7 +161,7 @@
- +
diff --git a/frontend/src/lib/components/FlowStatusViewer.svelte b/frontend/src/lib/components/FlowStatusViewer.svelte index 7d5c1c4a12..70c331a80b 100644 --- a/frontend/src/lib/components/FlowStatusViewer.svelte +++ b/frontend/src/lib/components/FlowStatusViewer.svelte @@ -88,7 +88,7 @@ retryStatus.val = {} suspendStatus.val = {} globalRefreshes = {} - flowState.val = {} + flowState = {} localDurationStatuses = {} localModuleStates = {} } diff --git a/frontend/src/lib/components/flows/FlowProgressBar.svelte b/frontend/src/lib/components/flows/FlowProgressBar.svelte index 39ccbbf424..4837db5e43 100644 --- a/frontend/src/lib/components/flows/FlowProgressBar.svelte +++ b/frontend/src/lib/components/flows/FlowProgressBar.svelte @@ -2,18 +2,27 @@ import { type Job } from '$lib/gen' import ProgressBar from '../progressBar/ProgressBar.svelte' - export let job: Job | undefined = undefined - export let currentSubJobProgress: number | undefined = undefined + interface Props { + job?: Job | undefined + currentSubJobProgress?: number | undefined + class?: string + } - let error: number | undefined = undefined - let index = 0 - let subIndex: number | undefined = undefined - let subLength: number | undefined = undefined - let length = 1 - let nextInProgress = false - let subIndexIsPercent: boolean = false + let { + job = undefined, + currentSubJobProgress = $bindable(undefined), + class: className + }: Props = $props() - $: if (job) updateJobProgress(job) + let error: number | undefined = $state(undefined) + let index = $state(0) + let subIndex: number | undefined = $state(undefined) + let subLength: number | undefined = $state(undefined) + let length = $state(1) + let nextInProgress = $state(false) + let subIndexIsPercent: boolean = $state(false) + + let progressBar = $state(undefined) function updateJobProgress(job: Job) { const modules = job?.flow_status?.modules @@ -40,8 +49,8 @@ newError = maxDone maxDone = maxDone + 1 } - } - subIndexIsPercent = false; + } + subIndexIsPercent = false // Loop is still iterating if (module?.iterator) { @@ -54,12 +63,12 @@ } else if (module?.branchall) { subStepIndex = module.branchall.branch subStepLength = module.branchall.len - } else if (module?.progress) { + } else if (module?.progress) { const clamp = (num, min, max) => Math.min(Math.max(num, min), max) subStepIndex = clamp(module?.progress, subIndex ?? 0, 99) // Jitter protection >^^^^^^^^ subStepLength = 100 - subIndexIsPercent = true; + subIndexIsPercent = true currentSubJobProgress = subStepIndex } else { currentSubJobProgress = undefined @@ -73,26 +82,27 @@ nextInProgress = newNextInProgress } - let resetP: any - export function reset() { - resetP?.() + progressBar?.resetP() error = undefined subIndex = undefined subLength = undefined length = 1 index = 0 } + $effect(() => { + job && updateJobProgress(job) + }) diff --git a/frontend/src/lib/components/graph/renderers/edges/EmptyEdge.svelte b/frontend/src/lib/components/graph/renderers/edges/EmptyEdge.svelte index 6c8c70d9ed..47a099b7c8 100644 --- a/frontend/src/lib/components/graph/renderers/edges/EmptyEdge.svelte +++ b/frontend/src/lib/components/graph/renderers/edges/EmptyEdge.svelte @@ -4,28 +4,43 @@ import type { Writable } from 'svelte/store' import { twMerge } from 'tailwind-merge' - export let sourceX: number - export let sourceY: number - export let sourcePosition: Position - export let targetX: number - export let targetY: number - export let targetPosition: Position - export let markerEnd: string | undefined = undefined - export let data: { class?: string } = {} + interface Props { + sourceX: number + sourceY: number + sourcePosition: Position + targetX: number + targetY: number + targetPosition: Position + markerEnd?: string | undefined + data?: { class?: string } + } - const { useDataflow } = getContext<{ - useDataflow: Writable - }>('FlowGraphContext') - - $: [edgePath] = getBezierPath({ + let { sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition, - curvature: 0.25 - }) + markerEnd = undefined, + data = {} + }: Props = $props() + + const { useDataflow } = getContext<{ + useDataflow: Writable + }>('FlowGraphContext') + + let [edgePath] = $derived( + getBezierPath({ + sourceX, + sourceY, + sourcePosition, + targetX, + targetY, + targetPosition, + curvature: 0.25 + }) + ) - import { tweened } from 'svelte/motion' + import { Tween } from 'svelte/motion' import { linear } from 'svelte/easing' import { twMerge } from 'tailwind-merge' - function getTween(initialValue = 0, duration = 200) { - return tweened(initialValue, { - duration, - easing: linear - }) + // Remove padding/margin, border radius and titles + + interface Props { + error?: number | undefined + index: number + subIndex: number | undefined + subLength: number | undefined + nextInProgress?: boolean + // Used for displaying progress of subjob of flow + subIndexIsPercent?: boolean + // Used in individual job test runs + compact?: boolean + // Removes `Step 1` and replaces it with `Running` + hideStepTitle?: boolean + length: number + class?: string } - export let error: number | undefined = undefined - export let index: number - export let subIndex: number | undefined - export let subLength: number | undefined - export let nextInProgress: boolean = false - // Used for displaying progress of subjob of flow - export let subIndexIsPercent: boolean = false - // Remove padding/margin, border radius and titles - // Used in individual job test runs - export let compact: boolean = false - // Removes `Step 1` and replaces it with `Running` - export let hideStepTitle: boolean = false - - export let length: number + let { + error = undefined, + index, + subIndex, + subLength, + nextInProgress = false, + subIndexIsPercent = false, + compact = false, + hideStepTitle = false, + length, + class: className = '' + }: Props = $props() let duration = 200 - let percent = getTween(0, duration) + let percent = new Tween(0, { duration, easing: linear }) export function resetP() { - percent = getTween(0, duration) + percent.set(0, { duration: 0 }) } - $: percent.set( - (length - ? index / length + (subIndex && subLength ? subIndex / (subLength ?? 1) / length : 0) - : 0) * 100 - ) + $effect(() => { + percent.set( + (length + ? index / length + (subIndex && subLength ? subIndex / (subLength ?? 1) / length : 0) + : 0) * 100 + ) + }) function getPercent(partIndex: number, _pct: number) { if (!length) { return 0 } - const res = Math.min(($percent - (partIndex / length) * 100) * length, 100) + const res = Math.min((percent.current - (partIndex / length) * 100) * length, 100) return res } - $: finished = index == length + let finished = $derived(index == length) -
+
{#if !compact} -
- - {error != undefined - ? 'Error occured' - : finished - ? 'Done' - : hideStepTitle - ? `Running` - : subIndexIsPercent - ? `Step ${index + 1} (${subIndex !== undefined ? `${subIndex}%)` : ''}` - : `Step ${index + 1}${subIndex !== undefined ? `.${subIndex + 1}` : ''}`} - - - {$percent.toFixed(0)}% - -
+
+ + {error != undefined + ? 'Error occured' + : finished + ? 'Done' + : hideStepTitle + ? `Running` + : subIndexIsPercent + ? `Step ${index + 1} (${subIndex !== undefined ? `${subIndex}%)` : ''}` + : `Step ${index + 1}${subIndex !== undefined ? `.${subIndex + 1}` : ''}`} + + + {percent.current.toFixed(0)}% + +
{/if} -
+
{#each new Array(length) as _, partIndex (partIndex)}
{#if partIndex == index && nextInProgress} @@ -101,7 +114,7 @@ class="absolute left-0 bottom-0 h-full {error == partIndex ? 'bg-red-400' : 'bg-blue-400'}" - style="width: {getPercent(partIndex, $percent)}%" + style="width: {getPercent(partIndex, percent.current)}%" >
{/if}