Skip to content

Show retry budget usage and why a retry was refused - #160

Merged
hamzahalq merged 2 commits into
mainfrom
hamza/fix/retry-total-attempts-cap
Aug 11, 2026
Merged

Show retry budget usage and why a retry was refused#160
hamzahalq merged 2 commits into
mainfrom
hamza/fix/retry-total-attempts-cap

Conversation

@hamzahalq

Copy link
Copy Markdown
Contributor

Adds a Budget usage panel to the retry policy page listing each integration's spent total, flagging exhausted ones, with per-row and bulk Reset — the only way back for a group that has hit its ceiling.

The xchange retry dialog now shows the policy's refusal reason, and the "Max attempts total" tooltip is corrected: the total is a lifetime ceiling counted per integration, not a shared one across all messages.

Adds a Budget usage panel to the retry policy page listing each integration's
spent total, flagging exhausted ones, with per-row and bulk Reset — the only
way back for a group that has hit its ceiling.

The xchange retry dialog now shows the policy's refusal reason, and the
"Max attempts total" tooltip is corrected: the total is a lifetime ceiling
counted per integration, not a shared one across all messages.
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: simplify9/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: cf504cae-2537-4a30-b047-d94ddc3d6479

📥 Commits

Reviewing files that changed from the base of the PR and between b6be888 and 0846a83.

📒 Files selected for processing (3)
  • src/client/apis/retryPoliciesApi.ts
  • src/components/RetryPolicies/RetryBudgetUsage.tsx
  • src/components/exchanges/RetryModal.tsx
📜 Recent review details
🧰 Additional context used
📓 Path-based instructions (1)
src/**

⚙️ CodeRabbit configuration file

src/**: Focus on correctness, security, maintainability, and testability.

Flag:

  • authentication bypasses
  • authorization gaps
  • injection risks
  • unsafe deserialization
  • insecure crypto
  • missing input validation
  • data leakage
  • race conditions
  • weak error handling
  • missing audit logging for sensitive actions
  • insufficient tests for changed behavior

Files:

  • src/components/exchanges/RetryModal.tsx
  • src/client/apis/retryPoliciesApi.ts
  • src/components/RetryPolicies/RetryBudgetUsage.tsx
🔇 Additional comments (6)
src/components/exchanges/RetryModal.tsx (2)

75-80: Add regression coverage for the blocked-retry states.

Test that a non-empty retryBlockedReason renders when no retry is scheduled, that the notice is hidden when scheduledRetryOn exists, and that null or empty reasons render nothing. This is the same unresolved finding from the previous review.

As per path instructions, changed behavior must have sufficient tests.

Source: Path instructions


14-17: LGTM!

src/components/RetryPolicies/RetryBudgetUsage.tsx (3)

85-94: Verify authorization for both reset controls.

The component relies entirely on Authorize and does not pass disabled to either Button. If Authorize still renders unauthorized children inside <section disabled>, a Viewer can invoke both reset(...) handlers. Make unauthorized children absent or pass an actual disabled state. Enforce the same role and policy checks, and audit both reset scopes on RetryPolicies/{id}/resetusage on the server.

As per path instructions, src/** changes must flag authorization gaps and missing audit logging for sensitive actions.

#!/bin/bash
set -euo pipefail

echo "== authorization and reset references =="
rg -n -C 6 -i \
  'resetusage|RetryPolicyResetUsage|Authorize|<section disabled|Admin|Member|audit' . \
  --glob '!node_modules' --glob '!dist' --glob '!build' || true

Also applies to: 101-107

Source: Path instructions


16-16: Verify regression coverage for the new usage-query states.

Cover a rejected query, the “Try again” action, and a successful empty response. Also verify that saving a policy invalidates the active usage query. No tests for these paths are included in the supplied context.

As per path instructions, src/** changes must include sufficient tests for changed behavior.

#!/bin/bash
set -euo pipefail

while IFS= read -r file; do
    if rg -q -E 'RetryBudgetUsage|useRetryPolicyUsageQuery|retryPolicyUsage|refetch|invalidatesTags' "$file"; then
        echo "FILE: $file"
        rg -n -C 4 -E \
          'RetryBudgetUsage|useRetryPolicyUsageQuery|retryPolicyUsage|refetch|invalidatesTags' \
          "$file" || true
    fi
done < <(
    git ls-files | rg '(^|/)(__tests__/|.*\.(test|spec)\.(ts|tsx|js|jsx)$)'
)

Also applies to: 32-45

Source: Path instructions


16-16: LGTM!

Also applies to: 32-38, 40-45

src/client/apis/retryPoliciesApi.ts (1)

7-8: LGTM!

Also applies to: 17-17, 45-46, 75-89, 103-104


📝 Walkthrough

Summary

  • Added retry-policy usage APIs, cache invalidation, and usage types.
  • Added a Budget usage panel with per-integration usage, exhaustion status, load-error retry, and per-row or bulk reset actions.
  • Refetches usage after policy updates.
  • Updated retry dialogs to show retryBlockedReason and encode quotation marks.
  • Corrected the “Max attempts total” tooltip to describe the lifetime limit per integration.

Risk

risk:medium — Reset actions change retry-budget state and depend on correct authorization and backend behavior. UI state can become stale if usage invalidation or refetching fails.

Security-sensitive areas

  • Per-integration and bulk usage reset mutations.
  • Reset controls are restricted to authorized users in the UI.
  • Server-side authorization must remain authoritative.
  • Retry refusal reasons are exposed in the exchange retry dialog and may contain operational details.

Test coverage impact

No test changes are described. Add coverage for usage loading, empty, error, and exhausted states; authorized and unauthorized reset actions; bulk reset behavior; policy-update refetching; API failures; and retry refusal messages with quotation marks.

Operational concerns

  • The deployed backend must support the usage and reset endpoints.
  • Confirm reset mutations are auditable and protected by server-side authorization.
  • No database migration is described.
  • Rollback requires reverting the UI and API client changes. Existing usage counters should remain unaffected by a UI rollback.

Walkthrough

Changes

Retry policy controls

Layer / File(s) Summary
Usage contracts and API endpoints
src/types/retryPolicies.ts, src/client/apis/retryPoliciesApi.ts
Adds usage and reset types, API endpoints, cache invalidation, and generated hooks.
Retry budget usage editor
src/components/RetryPolicies/RetryBudgetUsage.tsx, src/components/RetryPolicy.tsx, src/components/RetryPolicies/AddEditRetryGroupModal.tsx
Adds loading, error, empty, exhaustion, table, and reset states. Integrates the usage panel into the policy editor and updates retry-limit guidance.
Blocked retry feedback
src/types/xchange.ts, src/components/exchanges/ExchangeList.tsx, src/components/exchanges/RetryModal.tsx
Passes retry-block reasons to the modal and displays them when automatic retry is unavailable.

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

Possibly related PRs

  • simplify9/Bitween-UI#129: Shares retry-policy API, types, and RetryPolicy UI components but implements policy testing.

Suggested labels: risk:high

Suggested reviewers: mmalkhatib

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main changes: retry budget usage and retry refusal reasons.
Description check ✅ Passed The description accurately covers the usage panel, reset actions, refusal reason, and tooltip correction.
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.

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🤖 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 `@src/client/apis/retryPoliciesApi.ts`:
- Around line 74-88: Update the updateRetryPolicy mutation’s invalidatesTags
configuration to include retryPolicyUsage alongside retryPolicies, ensuring
mounted usage panels refresh after saving policy changes.

In `@src/components/exchanges/RetryModal.tsx`:
- Around line 75-80: Add regression tests for the RetryModal warning controlled
by hasScheduledRetry and retryBlockedReason: verify a non-empty reason renders
when no retry is scheduled, verify the warning is hidden when scheduledRetryOn
exists, and verify null or empty reasons render nothing. Use the existing
RetryModal test setup and preserve all other modal behavior.
- Line 78: Update the JSX text in RetryModal to encode the quotation marks
around Retry as &quot; entities, preserving the existing message and manual
retry instruction.

In `@src/components/RetryPolicies/RetryBudgetUsage.tsx`:
- Line 16: Update RetryBudgetUsage around useRetryPolicyUsageQuery to also
consume isError and refetch, rendering a distinct error state with a retry
action when the request fails. Only render the existing empty-state message when
the query succeeds with no usage data, while preserving the loading and
populated-data paths.
- Around line 77-99: Update the reset controls in RetryBudgetUsage to rely on
Authorize omitting unauthorized children rather than a disabled section, and
enforce the same Admin/Member authorization in both reset mutation handlers on
the backend. Ensure unauthorized users cannot invoke individual or “Reset all”
actions, and add coverage verifying those controls and mutations are rejected
for unauthorized roles.
- Around line 16-17: Update RetryBudgetUsage and its tests to cover query-error
rendering, per-row and bulk reset payloads, and cache refresh after resets.
Ensure query failures display an error state rather than “No budget spent,” and
make both reset actions unavailable to unauthorized roles by explicitly
disabling or gating the descendant buttons; verify the authorized and
unauthorized flows.
🪄 Autofix

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: Repository: simplify9/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a7756c6f-a4cc-475e-994d-bee8eef2e049

📥 Commits

Reviewing files that changed from the base of the PR and between 1f46fe6 and b6be888.

📒 Files selected for processing (8)
  • src/client/apis/retryPoliciesApi.ts
  • src/components/RetryPolicies/AddEditRetryGroupModal.tsx
  • src/components/RetryPolicies/RetryBudgetUsage.tsx
  • src/components/RetryPolicy.tsx
  • src/components/exchanges/ExchangeList.tsx
  • src/components/exchanges/RetryModal.tsx
  • src/types/retryPolicies.ts
  • src/types/xchange.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
src/**

⚙️ CodeRabbit configuration file

src/**: Focus on correctness, security, maintainability, and testability.

Flag:

  • authentication bypasses
  • authorization gaps
  • injection risks
  • unsafe deserialization
  • insecure crypto
  • missing input validation
  • data leakage
  • race conditions
  • weak error handling
  • missing audit logging for sensitive actions
  • insufficient tests for changed behavior

Files:

  • src/components/RetryPolicy.tsx
  • src/components/RetryPolicies/AddEditRetryGroupModal.tsx
  • src/types/retryPolicies.ts
  • src/components/exchanges/RetryModal.tsx
  • src/types/xchange.ts
  • src/components/exchanges/ExchangeList.tsx
  • src/components/RetryPolicies/RetryBudgetUsage.tsx
  • src/client/apis/retryPoliciesApi.ts
🪛 React Doctor (0.9.3)
src/components/exchanges/RetryModal.tsx

[warning] 78-78: " in JSX text can read as markup & confuse readers.

Replace bare ' / " / > / } characters with HTML entities so literal UI text is encoded consistently.

(no-unescaped-entities)

🔇 Additional comments (8)
src/types/xchange.ts (1)

42-43: LGTM!

src/components/exchanges/ExchangeList.tsx (1)

227-227: LGTM!

src/components/exchanges/RetryModal.tsx (1)

14-17: LGTM!

src/types/retryPolicies.ts (1)

100-116: LGTM!

src/client/apis/retryPoliciesApi.ts (1)

7-8: LGTM!

Also applies to: 17-17, 102-103

src/components/RetryPolicies/RetryBudgetUsage.tsx (1)

1-15: LGTM!

Also applies to: 19-20, 23-31, 37-75, 101-105

src/components/RetryPolicies/AddEditRetryGroupModal.tsx (1)

172-172: LGTM!

src/components/RetryPolicy.tsx (1)

10-10: LGTM!

Also applies to: 66-68

Comment thread src/client/apis/retryPoliciesApi.ts
Comment thread src/components/exchanges/RetryModal.tsx
Comment thread src/components/exchanges/RetryModal.tsx Outdated
Comment thread src/components/RetryPolicies/RetryBudgetUsage.tsx Outdated
Comment thread src/components/RetryPolicies/RetryBudgetUsage.tsx Outdated
Comment thread src/components/RetryPolicies/RetryBudgetUsage.tsx
A failed usage request fell through to "No budget spent", claiming every group
was untouched when the truth was unknown. Render an error with a retry action
instead, and keep the empty state for successful empty responses.

Refetch usage after a policy is saved, since saving drops the counters of any
removed group. Encode the quotation marks in the retry dialog.
@hamzahalq
hamzahalq merged commit 80f7f9c into main Aug 11, 2026
4 of 5 checks passed
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