Skip to content

Fix JobStatus polling for completed jobs (Issue #363)#364

Merged
rogermt merged 3 commits into
mainfrom
v0.16.3
Mar 24, 2026
Merged

Fix JobStatus polling for completed jobs (Issue #363)#364
rogermt merged 3 commits into
mainfrom
v0.16.3

Conversation

@rogermt
Copy link
Copy Markdown
Owner

@rogermt rogermt commented Mar 23, 2026

Problem

When a user clicks on a completed job in the Jobs view, the JobStatus component starts polling even though the job is already completed. This causes unnecessary API requests and can lead to intermittent "infinite polling" behavior.

Root Cause

JobStatus.tsx:23 always initialized pollStatus to "pending" on every mount:

const [pollStatus, setPollStatus] = useState<Status>("pending");

When the component remounts (view switch, React re-render), polling restarts until the first fetch confirms the job is completed.

Solution

  1. Added initialStatus prop to JobStatus component
  2. Initialize pollStatus from initialStatus instead of hardcoded "pending"
  3. Pass initialStatus from App.tsx for selectedJob and uploadResult

Changes

JobStatus.tsx:

  • Added initialStatus?: Status prop
  • Changed: useState<Status>(initialStatus || "pending")

App.tsx:

  • Pass initialStatus={selectedJob.status} in Jobs view
  • Pass initialStatus={uploadResult.status} in Upload view
  • Pass initialStatus={uploadResult.status} in Video Upload view

Tests Added

  • should NOT poll when initialStatus is 'completed'
  • should NOT poll when initialStatus is 'failed'
  • should poll when initialStatus is 'pending' (default behavior)
  • should work without initialStatus prop (backward compatibility)

TEST-CHANGE JUSTIFICATION

Tests added to verify the new initialStatus prop behavior:

  • Prevents unnecessary API polling for terminal job states
  • Ensures backward compatibility when prop is omitted
  • TDD approach: tests written first, verified to fail, then implementation fixed

Fixes #363

Summary by CodeRabbit

  • New Features

    • Job status accepts an optional initial status so known completed/failed jobs skip immediate background polling.
    • Job list honours a view mode and re-fetches when the view mode changes.
  • Bug Fixes

    • Prevents unnecessary polling when job status is already terminal.
  • Tests

    • Added tests for job-status polling behaviour and view-mode-driven job-list fetching.
  • Documentation

    • Added frontend state-flow documentation detailing state transitions and polling behaviour.

- Add initialStatus prop to JobStatus component
- Initialize pollStatus from initialStatus instead of hardcoded "pending"
- Pass initialStatus from App.tsx for selectedJob and uploadResult
- Add tests for initialStatus prop behavior

This prevents unnecessary polling when a completed job is selected
from the Jobs view. Previously, JobStatus always initialized pollStatus
to "pending" on mount, causing polling to start even for terminal states.

Fixes #363
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 23, 2026

Walkthrough

Introduces an optional initialStatus prop for JobStatus so it can initialise polling state from a known job status; App.tsx and call sites now pass job.status. Adds tests for initial-status behaviour and a design doc; JobList gains an optional viewMode prop affecting fetch behaviour.

Changes

Cohort / File(s) Summary
JobStatus core implementation
web-ui/src/components/JobStatus.tsx
Add optional initialStatus?: Status prop; initialise internal polling state from it (instead of always "pending"), allowing immediate terminal-state handling and avoiding unnecessary polling.
JobStatus tests
web-ui/src/components/JobStatus.test.tsx
New tests for Issue #363: assert no HTTP polling when initialStatus is terminal ("completed"/"failed"), polling occurs for "pending", and default behaviour is preserved when prop omitted.
App call sites
web-ui/src/App.tsx
Updated JobStatus invocations to pass initialStatus={...status} for uploadResult and selectedJob; JobList render now includes viewMode={viewMode}.
JobList implementation & tests
web-ui/src/components/JobList.tsx, web-ui/src/components/JobList.test.tsx
Add optional viewMode?: string prop; fetch early-returns when viewMode is set and not "jobs", and useEffect depends on viewMode. Tests added to cover fetch-on-viewMode changes and previous default behaviour.
Documentation
docs/design/frontend-state-flow.md
New design doc describing frontend state model, polling locations, identified polling overlap issues, the initialStatus fix, and recommended action items.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant App as App (parent)
participant JobStatus as JobStatus (component)
participant API as apiClient
participant WS as WebSocket
App->>JobStatus: render(jobId, initialStatus)
alt initialStatus is terminal
JobStatus-->>API: no polling; render terminal UI
else initialStatus non-terminal or omitted
JobStatus->>WS: attempt websocket subscribe
alt websocket available
WS-->>JobStatus: status updates (render)
else websocket unavailable
JobStatus->>API: start polling (interval)
loop every n seconds
API-->>JobStatus: job status
alt status becomes terminal
JobStatus-->>API: stop polling
break
end
end
end
end

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

bug

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes an out-of-scope change: frontend-state-flow.md documentation file (484 lines added) is not required by Issue #363 and extends beyond the problem scope defined in the linked issue. Remove or move frontend-state-flow.md to a separate documentation PR, as it is not necessary to fix the JobStatus polling issue and should be addressed in its own change request.
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix JobStatus polling for completed jobs (Issue #363)' directly and accurately summarizes the main change, clearly indicating the problem being solved and the affected component.
Description check ✅ Passed The description covers the problem, root cause, solution, and changes clearly. It includes the required TEST CHANGE JUSTIFICATION section explaining why tests were added and what they protect.
Linked Issues check ✅ Passed The PR fully addresses Issue #363 requirements: adds initialStatus prop to JobStatus, initializes pollStatus from it, passes status from App.tsx for Jobs/Upload/Video views, includes comprehensive tests for terminal states and backward compatibility.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch v0.16.3

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
web-ui/src/components/JobStatus.test.tsx (2)

500-504: Consider using fake timers instead of real setTimeout.

The 100ms delay with setTimeout could cause flaky tests in CI environments. Vitest's fake timers provide more reliable timing control:

♻️ Suggested improvement
+  beforeEach(() => {
+    vi.useFakeTimers();
+  });
+
+  afterEach(() => {
+    vi.useRealTimers();
+  });

   it("should NOT poll when initialStatus is 'completed'", async () => {
     // ... setup ...

     render(<JobStatus jobId="job-123" initialStatus="completed" />);

     expect(screen.getByText(/completed/i)).toBeInTheDocument();

-    await new Promise((resolve) => setTimeout(resolve, 100));
+    await vi.advanceTimersByTimeAsync(100);

     expect(mockGetJob).not.toHaveBeenCalled();
   });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web-ui/src/components/JobStatus.test.tsx` around lines 500 - 504, Replace the
real 100ms delay in JobStatus.test.tsx with Vitest fake timers: wrap the test or
the specific section with vi.useFakeTimers(), replace the await new
Promise((resolve) => setTimeout(resolve, 100)) with advancing the fake timers
(e.g., vi.advanceTimersByTime or vi.runAllTimers) so that mockGetJob is
deterministically not called, then restore timers with vi.useRealTimers() (or
vi.resetAllTimers()) after the assertion; reference the test’s mockGetJob
expectation and the setTimeout call to locate where to apply
vi.useFakeTimers()/vi.advanceTimersByTime()/vi.useRealTimers().

475-505: Consider adding test for WebSocket connection prevention.

The tests verify HTTP polling is prevented, but the useJobProgress hook is still called unconditionally. If you address the WebSocket connection issue in JobStatus.tsx, consider adding a test to verify useJobProgress receives null for terminal states:

it("should not connect WebSocket when initialStatus is terminal", () => {
  render(<JobStatus jobId="job-123" initialStatus="completed" />);
  
  // Verify useJobProgress was called with null (no connection)
  expect(mockUseJobProgress).toHaveBeenCalledWith(null);
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web-ui/src/components/JobStatus.test.tsx` around lines 475 - 505, The
useJobProgress hook is being invoked unconditionally causing unwanted WebSocket
connections even when initialStatus is a terminal state; update JobStatus to
determine terminal statuses (e.g., "completed", "failed") and call
useJobProgress with null instead of the jobId when initialStatus is terminal (so
change the hook invocation in JobStatus from useJobProgress(jobId) to
useJobProgress(initialStatusIsTerminal ? null : jobId)), and add a test
asserting mockUseJobProgress was called with null when rendering <JobStatus
jobId="job-123" initialStatus="completed" /> to prevent WebSocket connection.
web-ui/src/components/JobStatus.tsx (1)

13-20: WebSocket still connects for terminal jobs.

While the initialStatus fix correctly prevents HTTP polling for completed/failed jobs, the useJobProgress(jobId) hook is called unconditionally and will still open a WebSocket connection. According to the context snippet from useJobProgress.ts (lines 64-194), connect() is called immediately when jobId changes, with no guard for terminal states.

Consider passing initialStatus to the hook or conditionally calling it:

-  const {
-    progress: wsProgress,
-    status: wsStatus,
-    error: wsError,
-    isConnected,
-  } = useJobProgress(jobId);
+  const skipWebSocket = initialStatus === "completed" || initialStatus === "failed";
+  const {
+    progress: wsProgress,
+    status: wsStatus,
+    error: wsError,
+    isConnected,
+  } = useJobProgress(skipWebSocket ? null : jobId);

This prevents unnecessary WebSocket connections for jobs that are already in a terminal state.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web-ui/src/components/JobStatus.tsx` around lines 13 - 20, The JobStatus
component currently calls useJobProgress(jobId) unconditionally which lets the
hook (whose connect() runs when jobId changes) open a WebSocket for terminal
jobs; update JobStatus to either pass the initialStatus into useJobProgress
(e.g., useJobProgress(jobId, initialStatus) and have the hook skip connect()
when initialStatus is terminal) or only call useJobProgress when initialStatus
is not a terminal state (e.g., check initialStatus/terminal enum before invoking
useJobProgress) so that connect() in the hook is never invoked for
completed/failed jobs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@web-ui/src/components/JobStatus.test.tsx`:
- Around line 500-504: Replace the real 100ms delay in JobStatus.test.tsx with
Vitest fake timers: wrap the test or the specific section with
vi.useFakeTimers(), replace the await new Promise((resolve) =>
setTimeout(resolve, 100)) with advancing the fake timers (e.g.,
vi.advanceTimersByTime or vi.runAllTimers) so that mockGetJob is
deterministically not called, then restore timers with vi.useRealTimers() (or
vi.resetAllTimers()) after the assertion; reference the test’s mockGetJob
expectation and the setTimeout call to locate where to apply
vi.useFakeTimers()/vi.advanceTimersByTime()/vi.useRealTimers().
- Around line 475-505: The useJobProgress hook is being invoked unconditionally
causing unwanted WebSocket connections even when initialStatus is a terminal
state; update JobStatus to determine terminal statuses (e.g., "completed",
"failed") and call useJobProgress with null instead of the jobId when
initialStatus is terminal (so change the hook invocation in JobStatus from
useJobProgress(jobId) to useJobProgress(initialStatusIsTerminal ? null :
jobId)), and add a test asserting mockUseJobProgress was called with null when
rendering <JobStatus jobId="job-123" initialStatus="completed" /> to prevent
WebSocket connection.

In `@web-ui/src/components/JobStatus.tsx`:
- Around line 13-20: The JobStatus component currently calls
useJobProgress(jobId) unconditionally which lets the hook (whose connect() runs
when jobId changes) open a WebSocket for terminal jobs; update JobStatus to
either pass the initialStatus into useJobProgress (e.g., useJobProgress(jobId,
initialStatus) and have the hook skip connect() when initialStatus is terminal)
or only call useJobProgress when initialStatus is not a terminal state (e.g.,
check initialStatus/terminal enum before invoking useJobProgress) so that
connect() in the hook is never invoked for completed/failed jobs.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1d4cdad5-adfd-4178-8757-8dd542aa2131

📥 Commits

Reviewing files that changed from the base of the PR and between 3fb7d78 and 669f9d7.

📒 Files selected for processing (3)
  • web-ui/src/App.tsx
  • web-ui/src/components/JobStatus.test.tsx
  • web-ui/src/components/JobStatus.tsx

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
docs/design/frontend-state-flow.md (2)

91-91: Use “auto-populated” for compound consistency.

Line 91 can be normalised to the preferred compound form reported by the linter.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/design/frontend-state-flow.md` at line 91, Change the phrase on line 91
to use the linter-preferred compound form: replace "auto-populated" with "auto
populated" in the text referencing App.selectedTools so the sentence reads
"App.selectedTools auto populated with first tool" (update the documentation
string that mentions App.selectedTools to match the preferred compound style).

48-54: Add language identifiers to fenced code blocks (markdownlint MD040).

Multiple fenced blocks are missing a language tag. Please label them (text, typescript, etc.) to satisfy lint and improve readability.

Also applies to: 72-80, 102-108, 202-213, 237-249, 275-281, 306-312, 338-350, 353-361, 440-474

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/design/frontend-state-flow.md` around lines 48 - 54, The fenced code
blocks in docs/design/frontend-state-flow.md (e.g., the PluginSelector mount
block showing "useEffect([]) → apiClient.getPlugins()" and similar blocks at the
other ranges) lack language identifiers and trigger markdownlint MD040; update
each triple-backtick fence to include an appropriate language tag (for instance
use ```text for plain flow diagrams or ```typescript/```json where the block
contains code/config) so all blocks (including those around lines 72-80,
102-108, 202-213, 237-249, 275-281, 306-312, 338-350, 353-361, 440-474) have
language specifiers.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/design/frontend-state-flow.md`:
- Around line 36-38: The doc currently states JobStatus.pollStatus is always
initialized to "pending" which is outdated after the initialStatus fix; update
the JobStatus initial-state descriptions so they say pollStatus is initialized
from initialStatus (or can reflect the job's configured/previous status) rather
than hardcoding "pending". Edit all occurrences that describe pollStatus (search
for JobStatus and pollStatus in the doc) and replace the fixed `"pending"`
initial-state text with a note that pollStatus is set from initialStatus (or the
resolved initial value) so the state model is consistent with the runtime
behavior.
- Around line 478-483: The checklist item "Add tests for polling stop
conditions" under "Action Items" is stale; update that checklist entry to
reflect that the PR added those tests by changing "3. **[ ] Add tests for
polling stop conditions**" to a completed checkbox "3. **[x] Add tests for
polling stop conditions**" (or alternatively reword it to "Add additional/future
coverage for polling stop conditions" if you prefer to indicate ongoing work),
and include a short note referencing the PR that introduced the tests for
clarity.

---

Nitpick comments:
In `@docs/design/frontend-state-flow.md`:
- Line 91: Change the phrase on line 91 to use the linter-preferred compound
form: replace "auto-populated" with "auto populated" in the text referencing
App.selectedTools so the sentence reads "App.selectedTools auto populated with
first tool" (update the documentation string that mentions App.selectedTools to
match the preferred compound style).
- Around line 48-54: The fenced code blocks in
docs/design/frontend-state-flow.md (e.g., the PluginSelector mount block showing
"useEffect([]) → apiClient.getPlugins()" and similar blocks at the other ranges)
lack language identifiers and trigger markdownlint MD040; update each
triple-backtick fence to include an appropriate language tag (for instance use
```text for plain flow diagrams or ```typescript/```json where the block
contains code/config) so all blocks (including those around lines 72-80,
102-108, 202-213, 237-249, 275-281, 306-312, 338-350, 353-361, 440-474) have
language specifiers.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 59db84bc-6f4a-418e-bd34-d7c138a8cc8b

📥 Commits

Reviewing files that changed from the base of the PR and between 669f9d7 and 5aa71c3.

📒 Files selected for processing (1)
  • docs/design/frontend-state-flow.md

Comment on lines +36 to +38
| `JobStatus` | `pollProgress` | `number \| null` | `null` |
| `JobStatus` | `pollStatus` | `Status` | **`"pending"`** |
| `JobStatus` | `pollError` | `string \| null` | `null` |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Update the JobStatus initial-state description to match current behaviour.

Line 37, Line 170, Line 192, and Line 471 still describe pollStatus as always initialised to "pending". That is now inaccurate after the initialStatus fix and makes the state model contradictory inside the same document.

Suggested doc patch
-| `JobStatus` | `pollStatus` | `Status` | **`"pending"`** |
+| `JobStatus` | `pollStatus` | `Status` | `initialStatus ?? "pending"` |

-const [pollStatus, setPollStatus] = useState<Status>("pending"); // ALWAYS "pending" on mount!
+const [pollStatus, setPollStatus] = useState<Status>(initialStatus ?? "pending");

-**BUG:** `pollStatus` initializes to `"pending"` on EVERY mount/remount!
+**Previous bug (fixed in PR `#364`):** `pollStatus` used to initialise to `"pending"` on every mount/remount.

-              │  │ pollStatus="pending" │◄── BUG: Always "pending"!
+              │  │ pollStatus=initialStatus ?? "pending" │

Also applies to: 167-195, 471-472

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/design/frontend-state-flow.md` around lines 36 - 38, The doc currently
states JobStatus.pollStatus is always initialized to "pending" which is outdated
after the initialStatus fix; update the JobStatus initial-state descriptions so
they say pollStatus is initialized from initialStatus (or can reflect the job's
configured/previous status) rather than hardcoding "pending". Edit all
occurrences that describe pollStatus (search for JobStatus and pollStatus in the
doc) and replace the fixed `"pending"` initial-state text with a note that
pollStatus is set from initialStatus (or the resolved initial value) so the
state model is consistent with the runtime behavior.

Comment on lines +478 to +483
## Action Items

1. **[x] Fix JobStatus initialStatus** - Add prop, pass from parent ✅ PR #364
2. **[ ] Fix JobList fetch-once bug** - Re-fetch on viewMode change (Issue #365)
3. **[ ] Add tests for polling stop conditions** - TDD approach
4. **[x] Document polling behavior** - This document
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Action item status is stale for test coverage.

Line 482 says polling stop-condition tests are still pending, but this PR explicitly adds those tests. Please mark this item as completed (or reword it to future coverage work only).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/design/frontend-state-flow.md` around lines 478 - 483, The checklist
item "Add tests for polling stop conditions" under "Action Items" is stale;
update that checklist entry to reflect that the PR added those tests by changing
"3. **[ ] Add tests for polling stop conditions**" to a completed checkbox "3.
**[x] Add tests for polling stop conditions**" (or alternatively reword it to
"Add additional/future coverage for polling stop conditions" if you prefer to
indicate ongoing work), and include a short note referencing the PR that
introduced the tests for clarity.

- Add viewMode prop to JobList component
- Only fetch jobs when viewMode === 'jobs'
- Re-fetch when viewMode changes to 'jobs'
- Pass viewMode from App.tsx
- Add tests for viewMode prop behavior

This fixes the "failed to fetch" stuck state after single-tool video upload.
Previously, JobList only fetched once on mount with useEffect([]), causing
it to get stuck in error state if the initial fetch failed.

Fixes #365
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@web-ui/src/components/JobList.tsx`:
- Around line 19-20: The effect in JobList.tsx exits early when viewMode !==
"jobs" but never clears the component's initial loading state, leaving loading
true; update the effect that checks viewMode (the conditional using viewMode !==
undefined && viewMode !== "jobs") to set loading to false before returning so
the component doesn't stay stuck, and apply the same change to the other
identical early-return in the file (the other viewMode check around line 38) so
both branches clear loading when skipping the fetch.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ee8db8c1-89ad-4ae9-8f15-624d07623f3a

📥 Commits

Reviewing files that changed from the base of the PR and between 5aa71c3 and ee5d26f.

📒 Files selected for processing (3)
  • web-ui/src/App.tsx
  • web-ui/src/components/JobList.test.tsx
  • web-ui/src/components/JobList.tsx

Comment on lines +19 to +20
// Issue #365: Only fetch when viewMode is 'jobs' (or not provided for backward compat)
if (viewMode !== undefined && viewMode !== "jobs") return;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Non-jobs branch can leave the component stuck in loading state.

When viewMode is not "jobs", the effect returns immediately, but loading stays true from initial state. If this component is mounted outside the Jobs view, it can show “Loading jobs...” indefinitely.

Suggested fix
 useEffect(() => {
-    // Issue `#365`: Only fetch when viewMode is 'jobs' (or not provided for backward compat)
-    if (viewMode !== undefined && viewMode !== "jobs") return;
+    // Issue `#365`: Only fetch when viewMode is 'jobs' (or not provided for backward compat)
+    if (viewMode !== undefined && viewMode !== "jobs") {
+        setLoading(false);
+        return;
+    }
+
+    setLoading(true);

     const loadJobs = async () => {
         try {
             const data = await apiClient.listJobs();
             setJobs(data);
             setError(null);

Also applies to: 38-38

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web-ui/src/components/JobList.tsx` around lines 19 - 20, The effect in
JobList.tsx exits early when viewMode !== "jobs" but never clears the
component's initial loading state, leaving loading true; update the effect that
checks viewMode (the conditional using viewMode !== undefined && viewMode !==
"jobs") to set loading to false before returning so the component doesn't stay
stuck, and apply the same change to the other identical early-return in the file
(the other viewMode check around line 38) so both branches clear loading when
skipping the fetch.

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.

Fix JobStatus polling for completed jobs

1 participant