Skip to content

feat: make log recalculation task cancellable - #5800

Merged
akshaydeo merged 2 commits into
devfrom
08-03-feat_make_log_recalculation_task_cancellable
Aug 11, 2026
Merged

feat: make log recalculation task cancellable#5800
akshaydeo merged 2 commits into
devfrom
08-03-feat_make_log_recalculation_task_cancellable

Conversation

@impoiler

@impoiler impoiler commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds the ability to cancel a running cost recalculation job from the logs header. Previously, once a recalculation was started it could not be stopped from the UI. This PR wires up a new POST /logs/recalculate-cost/cancel API endpoint, adds a cancelled terminal status to the job lifecycle, and updates the progress toast and "More actions" menu to expose a cancel control.

Changes

  • Added cancelRecalculateCostJob mutation to logsApi targeting POST /logs/recalculate-cost/cancel, which resolves with the job's post-cancel status.
  • Added "cancelled" as a terminal RecalcJobStatus status alongside completed and failed, with counters reflecting work committed before stopping.
  • Introduced isTerminalRecalcStatus helper and a shared RECALC_TOAST_ID constant to consolidate all recalculation lifecycle toast updates onto a single toast.
  • Added recalcCancelRequested state to track the window between the cancel request being sent and the job settling, preventing duplicate cancel clicks and avoiding progress toast overwrites during that window.
  • The in-progress toast now includes a Cancel action button; event.preventDefault() keeps the toast mounted so it can report the cancellation result rather than dismissing immediately.
  • The "More actions" menu item transforms into a Cancel recalculation control while a job is running, providing a fallback cancel path if the toast was dismissed. It is disabled (not hidden) while cancellation is in flight.
  • On a cancelled terminal status, an informational (non-error) toast reports the partial result, and logs/stats are refreshed since the job may have committed partial cost updates.

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (React)
  • Docs

How to test

  1. Navigate to the Logs view and open More actions.
  2. Click Recalculate costs to start a recalculation over a large log window.
  3. While the progress toast is visible, click the Cancel button on the toast. Verify:
    • The toast switches to "Cancelling cost recalculation…" with a description about finishing the current batch.
    • The "More actions" menu item shows "Cancelling…" and is disabled.
    • Once the job settles, an info toast appears reporting the partial result (rows updated/skipped before stopping).
    • The logs and stats views refresh.
  4. Repeat and cancel via the More actions menu item instead of the toast button.
  5. Dismiss the progress toast mid-run, then open More actions and verify Cancel recalculation is still available and functional.
  6. Verify that a completed or failed job still reports correctly and is unaffected by this change.
cd ui
pnpm i || npm i
pnpm build || npm run build

Breaking changes

  • Yes
  • No

Security considerations

No new auth surfaces. The cancel endpoint follows the same authentication pattern as the existing recalculate-cost endpoints.

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added the ability to cancel active cost recalculation jobs.
    • Added clear progress, cancellation, completion, and failure states.
    • Prevented duplicate cancellation requests.
  • Bug Fixes

    • Improved status updates and refresh behavior after partial job completion.
    • Added cancellation-specific notifications.
    • Ensured logs refresh correctly after recalculation jobs reach a terminal state.
    • Preserved completed work when a recalculation is cancelled.

Walkthrough

Recalculation jobs can now be cancelled from the logs workspace. The UI handles cancellation requests, cancelled terminal states, cancellation-specific toasts, polling stop, and post-completion refreshes.

Changes

Recalculation Cancellation

Layer / File(s) Summary
Cancellation contract and mutation
ui/lib/types/logs.ts, ui/lib/store/apis/logsApi.ts
RecalcJobStatus now includes cancelled. The API exposes cancelRecalculateCostJob and its generated hook.
Cancellation lifecycle and terminal handling
ui/app/workspace/logs/views/logsHeaderView.tsx
The logs header view tracks cancellation, updates toasts, handles cancelled jobs, stops polling, and refreshes logs and statistics.
Actions-menu cancellation controls
ui/app/workspace/logs/views/logsHeaderView.tsx
The actions menu cancels active jobs, prevents duplicate requests, and shows cancellation-specific labels and descriptions.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ActionsMenu
  participant logsHeaderView
  participant LogsAPI
  ActionsMenu->>logsHeaderView: Request cancellation
  logsHeaderView->>LogsAPI: Cancel recalculation job
  LogsAPI-->>logsHeaderView: Return cancellation status
  logsHeaderView->>ActionsMenu: Update toast and action state
Loading

Possibly related PRs

  • maximhq/bifrost#5801: Adds the backend cancellation endpoint and cancelled status used by this frontend and API client change.

Suggested reviewers: akshaydeo, pratham-mishra04

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely describes the main change: making log recalculation tasks cancellable.
Description check ✅ Passed The description explains the purpose, changes, testing steps, affected areas, breaking changes, and security considerations; screenshots and checklist confirmations are not included.
✨ 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 08-03-feat_make_log_recalculation_task_cancellable

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

@impoiler
impoiler changed the base branch from 08-03-feat_allow_oauth_reauth_docs to graphite-base/5800 August 3, 2026 13:15
@impoiler
impoiler force-pushed the graphite-base/5800 branch from a2fa02c to ce013ad Compare August 3, 2026 13:15
@impoiler
impoiler force-pushed the 08-03-feat_make_log_recalculation_task_cancellable branch from 8682338 to ffe386f Compare August 3, 2026 13:15
@impoiler
impoiler changed the base branch from graphite-base/5800 to 07-24-feat_show_logs_chain_on_table August 3, 2026 13:15
@impoiler
impoiler marked this pull request as ready for review August 3, 2026 14:45

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 3

🧹 Nitpick comments (1)
ui/app/workspace/logs/views/logsHeaderView.tsx (1)

237-246: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider data-testid on the new cancellation controls.

Neither the toast's Cancel action (Line 237-245) nor the actions-menu CommandItem that now doubles as a cancel control (Line 350-362) has a data-testid. The action: { label, onClick } shorthand does not accept a data-testid prop, but sonner supports passing JSX as the action value instead, which would allow adding one. Adding stable test ids to these new interactive elements would let E2E tests target the cancellation flow directly.

♻️ Example for the toast action (JSX form)
-			action: {
-				label: "Cancel",
-				// preventDefault keeps the toast mounted so it can report the cancellation;
-				// sonner otherwise dismisses a toast as soon as its action fires.
-				onClick: (event) => {
-					event.preventDefault();
-					void handleCancelRecalculate();
-				},
-			},
+			action: (
+				<button
+					data-testid="logs-recalc-cancel-btn"
+					onClick={(event) => {
+						event.preventDefault();
+						void handleCancelRecalculate();
+					}}
+				>
+					Cancel
+				</button>
+			),
As per path instructions, "Preserve existing UI conventions and data-testid attributes used by Playwright tests," and as per coding guidelines, "Add `data-testid` attributes to new interactive elements and preserve existing values because E2E tests depend on them."

Also applies to: 350-362

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ui/app/workspace/logs/views/logsHeaderView.tsx` around lines 237 - 246, Add
stable data-testid attributes to both new cancellation controls: the Sonner
action in the toast configuration and the actions-menu CommandItem cancel
control. Convert the toast action from the label/onClick shorthand to JSX so its
rendered element can receive a test id, while preserving the existing
cancellation behavior and UI labels.

Sources: Coding guidelines, Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ui/app/workspace/logs/views/logsHeaderView.tsx`:
- Around line 170-180: Guard the recalculation status/progress effect that
consumes recalcJobStatus so it returns immediately when recalcJobStatusError is
present, preventing stale non-terminal data from replacing the error toast.
Include recalcJobStatusError in that effect’s dependency list, while preserving
normal progress and terminal-status handling when the latest poll succeeds.
- Around line 151-168: Update the catch block in handleCancelRecalculate to use
RECALC_TOAST_ID for the cancellation failure toast instead of the separate
hardcoded ID, so it replaces the existing “Cancelling…” toast rather than
creating a second toast.

In `@ui/lib/store/apis/logsApi.ts`:
- Around line 434-443: The backend routing for cost recalculation must expose
POST /api/logs/recalculate-cost/cancel to match cancelRecalculateCostJob.
Register a cancel handler alongside the existing recalculation start and status
routes, reading the optional id from the query string and forwarding it to the
cancellation logic; alternatively, update both backend and
cancelRecalculateCostJob to use a request body consistently.

---

Nitpick comments:
In `@ui/app/workspace/logs/views/logsHeaderView.tsx`:
- Around line 237-246: Add stable data-testid attributes to both new
cancellation controls: the Sonner action in the toast configuration and the
actions-menu CommandItem cancel control. Convert the toast action from the
label/onClick shorthand to JSX so its rendered element can receive a test id,
while preserving the existing cancellation behavior and UI labels.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 90b7f5b2-1db7-431a-836d-c4d617399241

📥 Commits

Reviewing files that changed from the base of the PR and between ce013ad and ffe386f.

📒 Files selected for processing (3)
  • ui/app/workspace/logs/views/logsHeaderView.tsx
  • ui/lib/store/apis/logsApi.ts
  • ui/lib/types/logs.ts

Comment thread ui/app/workspace/logs/views/logsHeaderView.tsx
Comment thread ui/app/workspace/logs/views/logsHeaderView.tsx
@impoiler
impoiler force-pushed the 07-24-feat_show_logs_chain_on_table branch from ce013ad to 8c14bfc Compare August 3, 2026 15:58
@impoiler
impoiler force-pushed the 08-03-feat_make_log_recalculation_task_cancellable branch from ffe386f to 143f6db Compare August 3, 2026 15:58

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ui/lib/store/apis/logsApi.ts`:
- Around line 434-443: Update the cancelRecalculateCostJob mutation definition
to add invalidatesTags: ["Logs"], ensuring all Logs-tagged queries refresh after
cancellation while preserving its existing request configuration.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 19d6c5f0-4a52-4efd-abaf-8e015cce5576

📥 Commits

Reviewing files that changed from the base of the PR and between ffe386f and 143f6db.

📒 Files selected for processing (3)
  • ui/app/workspace/logs/views/logsHeaderView.tsx
  • ui/lib/store/apis/logsApi.ts
  • ui/lib/types/logs.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • ui/lib/types/logs.ts
  • ui/app/workspace/logs/views/logsHeaderView.tsx

Comment thread ui/lib/store/apis/logsApi.ts
@impoiler
impoiler force-pushed the 08-03-feat_make_log_recalculation_task_cancellable branch from 143f6db to f9fad16 Compare August 4, 2026 14:17
@impoiler
impoiler force-pushed the 07-24-feat_show_logs_chain_on_table branch from 8c14bfc to f873ca9 Compare August 4, 2026 14:17
@impoiler
impoiler force-pushed the 08-03-feat_make_log_recalculation_task_cancellable branch from f9fad16 to 5fe32e9 Compare August 4, 2026 14:47
coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 4, 2026
@impoiler
impoiler force-pushed the 08-03-feat_make_log_recalculation_task_cancellable branch from 5fe32e9 to ac36c68 Compare August 5, 2026 04:34
@impoiler
impoiler force-pushed the 07-24-feat_show_logs_chain_on_table branch from f873ca9 to 0ec20b4 Compare August 5, 2026 04:34
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

akshaydeo commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Merge activity

  • Aug 10, 7:17 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Aug 11, 6:07 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Aug 11, 6:08 AM UTC: @akshaydeo merged this pull request with Graphite.

@impoiler
impoiler changed the base branch from 07-24-feat_show_logs_chain_on_table to graphite-base/5800 August 10, 2026 07:33
@impoiler
impoiler force-pushed the 08-03-feat_make_log_recalculation_task_cancellable branch from bc50835 to d7b75a6 Compare August 10, 2026 07:36
@impoiler
impoiler force-pushed the graphite-base/5800 branch from 717a66d to ad74fed Compare August 10, 2026 07:36
@impoiler
impoiler changed the base branch from graphite-base/5800 to 07-24-feat_show_logs_chain_on_table August 10, 2026 07:37
@impoiler
impoiler force-pushed the 07-24-feat_show_logs_chain_on_table branch from ad74fed to d30dfd4 Compare August 10, 2026 17:51
@impoiler
impoiler force-pushed the 08-03-feat_make_log_recalculation_task_cancellable branch from d7b75a6 to c1ffea5 Compare August 10, 2026 17:51
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@impoiler
impoiler force-pushed the 07-24-feat_show_logs_chain_on_table branch from d30dfd4 to cf49fc5 Compare August 11, 2026 04:20
@impoiler
impoiler force-pushed the 08-03-feat_make_log_recalculation_task_cancellable branch from c1ffea5 to e27c8a7 Compare August 11, 2026 04:20
@akshaydeo
akshaydeo changed the base branch from 07-24-feat_show_logs_chain_on_table to graphite-base/5800 August 11, 2026 06:07
@akshaydeo
akshaydeo changed the base branch from graphite-base/5800 to dev August 11, 2026 06:07
@akshaydeo
akshaydeo dismissed coderabbitai[bot]’s stale review August 11, 2026 06:07

The base branch was changed.

@akshaydeo
akshaydeo merged commit ecc29ba into dev Aug 11, 2026
10 checks passed
@akshaydeo
akshaydeo deleted the 08-03-feat_make_log_recalculation_task_cancellable branch August 11, 2026 06:08
akshaydeo pushed a commit that referenced this pull request Aug 13, 2026
## Summary

Adds the ability to cancel a running cost recalculation job from the logs header. Previously, once a recalculation was started it could not be stopped from the UI. This PR wires up a new `POST /logs/recalculate-cost/cancel` API endpoint, adds a `cancelled` terminal status to the job lifecycle, and updates the progress toast and "More actions" menu to expose a cancel control.

## Changes

- Added `cancelRecalculateCostJob` mutation to `logsApi` targeting `POST /logs/recalculate-cost/cancel`, which resolves with the job's post-cancel status.
- Added `"cancelled"` as a terminal `RecalcJobStatus` status alongside `completed` and `failed`, with counters reflecting work committed before stopping.
- Introduced `isTerminalRecalcStatus` helper and a shared `RECALC_TOAST_ID` constant to consolidate all recalculation lifecycle toast updates onto a single toast.
- Added `recalcCancelRequested` state to track the window between the cancel request being sent and the job settling, preventing duplicate cancel clicks and avoiding progress toast overwrites during that window.
- The in-progress toast now includes a **Cancel** action button; `event.preventDefault()` keeps the toast mounted so it can report the cancellation result rather than dismissing immediately.
- The "More actions" menu item transforms into a **Cancel recalculation** control while a job is running, providing a fallback cancel path if the toast was dismissed. It is disabled (not hidden) while cancellation is in flight.
- On a `cancelled` terminal status, an informational (non-error) toast reports the partial result, and logs/stats are refreshed since the job may have committed partial cost updates.

## Type of change

- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [x] UI (React)
- [ ] Docs

## How to test

1. Navigate to the Logs view and open **More actions**.
2. Click **Recalculate costs** to start a recalculation over a large log window.
3. While the progress toast is visible, click the **Cancel** button on the toast. Verify:
   - The toast switches to "Cancelling cost recalculation…" with a description about finishing the current batch.
   - The "More actions" menu item shows "Cancelling…" and is disabled.
   - Once the job settles, an info toast appears reporting the partial result (rows updated/skipped before stopping).
   - The logs and stats views refresh.
4. Repeat and cancel via the **More actions** menu item instead of the toast button.
5. Dismiss the progress toast mid-run, then open **More actions** and verify **Cancel recalculation** is still available and functional.
6. Verify that a completed or failed job still reports correctly and is unaffected by this change.

```sh
cd ui
pnpm i || npm i
pnpm build || npm run build
```

## Breaking changes

- [ ] Yes
- [x] No

## Security considerations

No new auth surfaces. The cancel endpoint follows the same authentication pattern as the existing recalculate-cost endpoints.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
akshaydeo pushed a commit that referenced this pull request Aug 13, 2026
## Summary

Adds the ability to cancel a running cost recalculation job from the logs header. Previously, once a recalculation was started it could not be stopped from the UI. This PR wires up a new `POST /logs/recalculate-cost/cancel` API endpoint, adds a `cancelled` terminal status to the job lifecycle, and updates the progress toast and "More actions" menu to expose a cancel control.

## Changes

- Added `cancelRecalculateCostJob` mutation to `logsApi` targeting `POST /logs/recalculate-cost/cancel`, which resolves with the job's post-cancel status.
- Added `"cancelled"` as a terminal `RecalcJobStatus` status alongside `completed` and `failed`, with counters reflecting work committed before stopping.
- Introduced `isTerminalRecalcStatus` helper and a shared `RECALC_TOAST_ID` constant to consolidate all recalculation lifecycle toast updates onto a single toast.
- Added `recalcCancelRequested` state to track the window between the cancel request being sent and the job settling, preventing duplicate cancel clicks and avoiding progress toast overwrites during that window.
- The in-progress toast now includes a **Cancel** action button; `event.preventDefault()` keeps the toast mounted so it can report the cancellation result rather than dismissing immediately.
- The "More actions" menu item transforms into a **Cancel recalculation** control while a job is running, providing a fallback cancel path if the toast was dismissed. It is disabled (not hidden) while cancellation is in flight.
- On a `cancelled` terminal status, an informational (non-error) toast reports the partial result, and logs/stats are refreshed since the job may have committed partial cost updates.

## Type of change

- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [x] UI (React)
- [ ] Docs

## How to test

1. Navigate to the Logs view and open **More actions**.
2. Click **Recalculate costs** to start a recalculation over a large log window.
3. While the progress toast is visible, click the **Cancel** button on the toast. Verify:
   - The toast switches to "Cancelling cost recalculation…" with a description about finishing the current batch.
   - The "More actions" menu item shows "Cancelling…" and is disabled.
   - Once the job settles, an info toast appears reporting the partial result (rows updated/skipped before stopping).
   - The logs and stats views refresh.
4. Repeat and cancel via the **More actions** menu item instead of the toast button.
5. Dismiss the progress toast mid-run, then open **More actions** and verify **Cancel recalculation** is still available and functional.
6. Verify that a completed or failed job still reports correctly and is unaffected by this change.

```sh
cd ui
pnpm i || npm i
pnpm build || npm run build
```

## Breaking changes

- [ ] Yes
- [x] No

## Security considerations

No new auth surfaces. The cancel endpoint follows the same authentication pattern as the existing recalculate-cost endpoints.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
akshaydeo pushed a commit that referenced this pull request Aug 14, 2026
## Summary

Adds the ability to cancel a running cost recalculation job from the logs header. Previously, once a recalculation was started it could not be stopped from the UI. This PR wires up a new `POST /logs/recalculate-cost/cancel` API endpoint, adds a `cancelled` terminal status to the job lifecycle, and updates the progress toast and "More actions" menu to expose a cancel control.

## Changes

- Added `cancelRecalculateCostJob` mutation to `logsApi` targeting `POST /logs/recalculate-cost/cancel`, which resolves with the job's post-cancel status.
- Added `"cancelled"` as a terminal `RecalcJobStatus` status alongside `completed` and `failed`, with counters reflecting work committed before stopping.
- Introduced `isTerminalRecalcStatus` helper and a shared `RECALC_TOAST_ID` constant to consolidate all recalculation lifecycle toast updates onto a single toast.
- Added `recalcCancelRequested` state to track the window between the cancel request being sent and the job settling, preventing duplicate cancel clicks and avoiding progress toast overwrites during that window.
- The in-progress toast now includes a **Cancel** action button; `event.preventDefault()` keeps the toast mounted so it can report the cancellation result rather than dismissing immediately.
- The "More actions" menu item transforms into a **Cancel recalculation** control while a job is running, providing a fallback cancel path if the toast was dismissed. It is disabled (not hidden) while cancellation is in flight.
- On a `cancelled` terminal status, an informational (non-error) toast reports the partial result, and logs/stats are refreshed since the job may have committed partial cost updates.

## Type of change

- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [x] UI (React)
- [ ] Docs

## How to test

1. Navigate to the Logs view and open **More actions**.
2. Click **Recalculate costs** to start a recalculation over a large log window.
3. While the progress toast is visible, click the **Cancel** button on the toast. Verify:
   - The toast switches to "Cancelling cost recalculation…" with a description about finishing the current batch.
   - The "More actions" menu item shows "Cancelling…" and is disabled.
   - Once the job settles, an info toast appears reporting the partial result (rows updated/skipped before stopping).
   - The logs and stats views refresh.
4. Repeat and cancel via the **More actions** menu item instead of the toast button.
5. Dismiss the progress toast mid-run, then open **More actions** and verify **Cancel recalculation** is still available and functional.
6. Verify that a completed or failed job still reports correctly and is unaffected by this change.

```sh
cd ui
pnpm i || npm i
pnpm build || npm run build
```

## Breaking changes

- [ ] Yes
- [x] No

## Security considerations

No new auth surfaces. The cancel endpoint follows the same authentication pattern as the existing recalculate-cost endpoints.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
akshaydeo pushed a commit that referenced this pull request Aug 19, 2026
## Summary

Adds the ability to cancel a running cost recalculation job from the logs header. Previously, once a recalculation was started it could not be stopped from the UI. This PR wires up a new `POST /logs/recalculate-cost/cancel` API endpoint, adds a `cancelled` terminal status to the job lifecycle, and updates the progress toast and "More actions" menu to expose a cancel control.

## Changes

- Added `cancelRecalculateCostJob` mutation to `logsApi` targeting `POST /logs/recalculate-cost/cancel`, which resolves with the job's post-cancel status.
- Added `"cancelled"` as a terminal `RecalcJobStatus` status alongside `completed` and `failed`, with counters reflecting work committed before stopping.
- Introduced `isTerminalRecalcStatus` helper and a shared `RECALC_TOAST_ID` constant to consolidate all recalculation lifecycle toast updates onto a single toast.
- Added `recalcCancelRequested` state to track the window between the cancel request being sent and the job settling, preventing duplicate cancel clicks and avoiding progress toast overwrites during that window.
- The in-progress toast now includes a **Cancel** action button; `event.preventDefault()` keeps the toast mounted so it can report the cancellation result rather than dismissing immediately.
- The "More actions" menu item transforms into a **Cancel recalculation** control while a job is running, providing a fallback cancel path if the toast was dismissed. It is disabled (not hidden) while cancellation is in flight.
- On a `cancelled` terminal status, an informational (non-error) toast reports the partial result, and logs/stats are refreshed since the job may have committed partial cost updates.

## Type of change

- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [x] UI (React)
- [ ] Docs

## How to test

1. Navigate to the Logs view and open **More actions**.
2. Click **Recalculate costs** to start a recalculation over a large log window.
3. While the progress toast is visible, click the **Cancel** button on the toast. Verify:
   - The toast switches to "Cancelling cost recalculation…" with a description about finishing the current batch.
   - The "More actions" menu item shows "Cancelling…" and is disabled.
   - Once the job settles, an info toast appears reporting the partial result (rows updated/skipped before stopping).
   - The logs and stats views refresh.
4. Repeat and cancel via the **More actions** menu item instead of the toast button.
5. Dismiss the progress toast mid-run, then open **More actions** and verify **Cancel recalculation** is still available and functional.
6. Verify that a completed or failed job still reports correctly and is unaffected by this change.

```sh
cd ui
pnpm i || npm i
pnpm build || npm run build
```

## Breaking changes

- [ ] Yes
- [x] No

## Security considerations

No new auth surfaces. The cancel endpoint follows the same authentication pattern as the existing recalculate-cost endpoints.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
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