Skip to content

Fix pauseLiveUpdate logic and remove currentEventHistory store#3404

Open
Alex-Tideman wants to merge 2 commits into
mainfrom
refresh-auto-load
Open

Fix pauseLiveUpdate logic and remove currentEventHistory store#3404
Alex-Tideman wants to merge 2 commits into
mainfrom
refresh-auto-load

Conversation

@Alex-Tideman
Copy link
Copy Markdown
Collaborator

@Alex-Tideman Alex-Tideman commented May 18, 2026

Description & motivation 💭

This PR updates workflow run loading so live polling respects pauseLiveUpdates.

When live updates are paused, workflow history and metadata requests are made without the live polling abort signal, which prevents the event history endpoint from using waitNewEvent=true. The layout also aborts any existing live polling controller when pause is enabled so an already-running long poll does not continue in the background.

It also removes currentEventHistory store: currentEventHistory was a workaround for the older behavior: keep the rendered event list frozen while fullEventHistory continued to update in the background. Now the fix is at the source: when pauseLiveUpdates is true, live polling is not started, and any in-flight polling controller is aborted. With the guard:

if (signal?.aborted) return;

The aborted fetch no longer writes [] back into $fullEventHistory.

Why

The history page correctly stopped updating when pauseLiveUpdates was enabled, but an in-flight workflow run poll could still continue after the user paused live updates. This caused background history refetch behavior even though the UI indicated auto refresh was off. Also, if a user refreshed the page with refresh_off=true, the history would not load, showing only pending events.

This change makes the pause state apply consistently to workflow details, metadata, and event history loading.

  • Verified /history?refresh_off=true still loads initial event history.
  • Verified pausing live updates stops live polling/refetch behavior.
  • Verified workflow details and history remain usable while live updates are
    paused.

Screenshots (if applicable) 📸

Design Considerations 🎨

Testing 🧪

Pause Live Updates during a running workflow and ensure no new events render and the workflow doesn't update.

Pause Live Updates during a running workflow and then unpause and ensur new events render and the workflow does update.

Pause Live Updates during a running workflow, wait, and refresh the page. Ensure new events are rendered from the pause to the refresh, but ensure no new events render.

How was this tested 👻

  • Manual testing
  • E2E tests added
  • Unit tests added

Steps for others to test: 🚶🏽‍♂️🚶🏽‍♀️

Checklists

Draft Checklist

Merge Checklist

Issue(s) closed

Docs

Any docs updates needed?

@Alex-Tideman Alex-Tideman requested a review from a team as a code owner May 18, 2026 15:08
@vercel
Copy link
Copy Markdown

vercel Bot commented May 18, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
holocene Ready Ready Preview, Comment May 18, 2026 3:08pm

Request Review

@temporal-cicd
Copy link
Copy Markdown
Contributor

temporal-cicd Bot commented May 18, 2026

Warnings
⚠️

📊 Strict Mode: 3 errors in 1 file (0.3% of 931 total)

src/lib/layouts/workflow-history-layout.svelte (3)
  • L197:10: Type 'boolean | null' is not assignable to type 'boolean | undefined'.
  • L238:2: Type 'string | undefined' is not assignable to type 'string'.
  • L239:2: Type 'string | undefined' is not assignable to type 'string'.

Generated by 🚫 dangerJS against daa8e2c

@Alex-Tideman Alex-Tideman changed the title Refresh auto load Fix pauseLiveUpdate logic and remove currentEventHistory store May 18, 2026
@Alex-Tideman Alex-Tideman requested a review from laurakwhit May 18, 2026 15:17
}

$fullEventHistory = await fetchAllEvents({
const events = await fetchAllEvents({
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we maybe want a try/catch here now? Same with getWorkflowMetadata above? Something that ignores the abort errors but rethrows anything else?

let workflowId = $derived(page.params.workflow);
let runId = $derived(page.params.run);
let showJson = $derived(page.url.searchParams.has('json'));
let pauseLiveUpdates = $derived(parseEventFilterParams(page.url).refresh_off);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we're still just setting $pauseLiveUpdates = false in workflow-hsitory-layout.svelte. Do we now need to update to something like this ⬇️ ?

      if (isNotPending && $pauseLiveUpdates) {
        updateEventFilterParams(page.url, { refresh_off: false }, goto);
      }

workflowRunController.abort();
}
untrack(() => {
getOnlyWorkflowWithPendingActivities(refreshValue, pause);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After pause (and abort) and then unpausing are we actually starting polling again? Or do we need to re-trigger getWorkflowAndEventHistory after it was paused and then unpaused?

In the network tab, it doesn't look the /history is being called again (just the workflow summary endpoint).

@@ -114,6 +110,7 @@
$workflowRun = { ...$workflowRun, workflow, workers, workersLoaded: true };

workflowRunController = new AbortController();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this scenario is any real cause for concern, but probably best practice to abort any existing controller before constructing a new one

Suggested change
workflowRunController = new AbortController();
workflowRunController?.abort();
workflowRunController = new AbortController();

Comment on lines 166 to 169
$fullEventHistory = [];
if (workflowRunController) {
workflowRunController.abort();
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: Abort and then clear.

Suggested change
if (workflowRunController) {
workflowRunController.abort();
}
$fullEventHistory = [];

Comment on lines +49 to +58
await mockWorkflowApis(page);
await page.goto(`${workflowUrl}?refresh_off=true`);

await expect(page.getByTestId('pause')).toContainText('Auto Refresh Off');
await expect(
page
.getByTestId('event-summary-row')
.filter({ hasText: 'Workflow Execution Started' })
.first(),
).toBeVisible();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: Could we also test for the mid-flight toggle path? Maybe something like this ⬇️?

Suggested change
await mockWorkflowApis(page);
await page.goto(`${workflowUrl}?refresh_off=true`);
await expect(page.getByTestId('pause')).toContainText('Auto Refresh Off');
await expect(
page
.getByTestId('event-summary-row')
.filter({ hasText: 'Workflow Execution Started' })
.first(),
).toBeVisible();
await mockWorkflowApis(page);
const longPollPromise = page.waitForRequest(
(req) => req.url().includes('waitNewEvent=true'),
{ timeout: 2000 },
).catch(() => null);
await page.goto(`${workflowUrl}?refresh_off=true`);
await expect(page.getByTestId('pause')).toContainText('Auto Refresh Off');
await expect(
page
.getByTestId('event-summary-row')
.filter({ hasText: 'Workflow Execution Started' })
.first(),
).toBeVisible();
const eventRows = await page.getByTestId('event-summary-row').count();
expect(eventRows).toBeGreaterThan(1);
expect(await longPollPromise).toBeNull();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants