Skip to content

fix(billing): auto credit reload ui and setting update#2409

Merged
baktun14 merged 8 commits intomainfrom
fix/styling-post-reskin
Dec 23, 2025
Merged

fix(billing): auto credit reload ui and setting update#2409
baktun14 merged 8 commits intomainfrom
fix/styling-post-reskin

Conversation

@baktun14
Copy link
Contributor

@baktun14 baktun14 commented Dec 22, 2025

closes #2408

Summary by CodeRabbit

  • New Features

    • Redesigned Account Overview: updated balance display, skeleton loading, enhanced auto-recharge info, and Add Funds action (disabled when no payment method).
  • Bug Fixes

    • More robust wallet auto-reload scheduling and job handling with clearer failure/logging and safer cancel/complete behavior.
  • Style

    • UI spacing and layout tweaks across billing views, sidebar, tabs, buttons, payment-methods card, slider visuals, and pie chart label colors.
  • Accessibility

    • Date-range clear control moved to a separate, keyboard-accessible button.

✏️ Tip: You can customize this high-level summary in your review settings.

@baktun14 baktun14 requested a review from a team as a code owner December 22, 2025 19:28
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 22, 2025

Walkthrough

Adds LoggerService to WalletReloadJobService and logs previous-job cleanup, creation failures, and scheduling success; callers pass an optional options.prevAction (used as { prevAction: "cancel" }). Job-queue cancel/complete are wrapped in try/catch to log and swallow terminal-state errors. Several UI layout/styling tweaks included.

Changes

Cohort / File(s) Summary
Wallet reload job
apps/api/src/billing/services/wallet-reload-job/wallet-reload-job.service.ts
Injects LoggerService, initializes logger context, logs previous-job cleanup (action, previousJobId, userId), applies { prevAction } handling (cancel vs complete), logs job creation failures and successes, and updates scheduleForWalletSetting signature to accept options?: { prevAction?: string }.
Job queue resilience
apps/api/src/core/services/job-queue/job-queue.service.ts
Wraps cancel and complete operations in try/catch; preserves INFO logs on success, logs WARN with error on terminal-state failures, and rethrows non-terminal errors. Adds isTerminalStateError(error) helper.
Wallet settings integration & tests
apps/api/src/billing/services/wallet-settings/wallet-settings.service.ts, apps/api/src/billing/services/wallet-settings/wallet-settings.service.spec.ts
Call sites updated to pass { prevAction: "cancel" } when scheduling on re-enable; unit tests updated to expect the new second parameter.
Billing UI — Account overview & related
apps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsx, apps/deploy-web/src/components/billing-usage/PaymentMethodsView/PaymentMethodsView.tsx, apps/deploy-web/src/components/billing-usage/BillingView/BillingView.tsx, apps/deploy-web/src/components/billing-usage/BillingUsageLayout.tsx
Layout refactor to card + skeletons, Add Funds button/tooltip/guarding, Export CSV sizing change, tab vertical spacing increase; visual and spacing changes only.
Layout, theme, and small UI tweaks
apps/deploy-web/src/components/providers/NetworkCapacity.tsx, packages/ui/components/slider.tsx, apps/deploy-web/src/components/layout/Sidebar.tsx, packages/ui/components/custom/date-range-picker.tsx, apps/deploy-web/src/components/layout/SidebarGroupMenu.tsx
Pie-chart label color now theme-aware, slider track styling class adjusted, deploy link wrapped in centered container with padding changes, date-range clear control moved to a separate button, and minor spacing adjustments.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant WalletSettings as WalletSettingsService
  participant ReloadService as WalletReloadJobService
  participant JobQueue as JobQueueService/pg-boss
  participant Logger as LoggerService

  Note over WalletSettings,ReloadService: User toggles auto-reload ON (re-enable)
  WalletSettings->>ReloadService: scheduleForWalletSetting(next, { prevAction: "cancel" })
  ReloadService->>Logger: log PREVIOUS_JOB_CLEANUP (action, previousJobId, userId)
  alt previous job exists and prevAction == "cancel"
    ReloadService->>JobQueue: cancel(previousJobId)
    JobQueue-->>ReloadService: success / throws
    opt success
      ReloadService->>Logger: log JOB_CANCELLED
    end
    opt throws
      JobQueue-->>ReloadService: error
      ReloadService->>Logger: log JOB_CANCEL_FAILED (error)
    end
  else previous job exists and prevAction != "cancel"
    ReloadService->>JobQueue: complete(previousJobId)
    JobQueue-->>ReloadService: success / throws
    opt success
      ReloadService->>Logger: log JOB_COMPLETED
    end
    opt throws
      JobQueue-->>ReloadService: error
      ReloadService->>Logger: log JOB_COMPLETE_FAILED (error)
    end
  end
  ReloadService->>JobQueue: schedule(newJobPayload)
  alt schedule success
    JobQueue-->>ReloadService: newJobId, startAfter
    ReloadService->>Logger: log JOB_SCHEDULED (jobId, userId, startAfter)
    ReloadService-->>WalletSettings: scheduled
  else schedule fail (duplicate)
    JobQueue-->>ReloadService: error (already exists)
    ReloadService->>Logger: log JOB_CREATION_FAILED (userId, attemptedJobId, previousJobId)
    ReloadService-->>WalletSettings: throw descriptive error
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • ygrishajev
  • stalniy

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Out of Scope Changes check ❓ Inconclusive Most changes directly address the auto reload scheduling error and related billing UI updates. However, styling changes in theme, slider, sidebar, date-picker, and tab spacing appear peripheral to the core issue fix. Clarify whether the styling changes in NetworkCapacity, slider, Sidebar, date-range-picker, SidebarGroupMenu, and BillingUsageLayout are necessary for the core fix or should be separated into a distinct PR.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(billing): auto credit reload ui and setting update' aligns with the PR's main changes addressing the auto credit reload error and UI updates for billing components.
Linked Issues check ✅ Passed The PR addresses issue #2408 by adding prevAction='cancel' parameter to cancel previous jobs when re-enabling auto reload, implementing try/catch for terminal errors, and updating UI components related to billing.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/styling-post-reskin

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5e2125c and 4207e28.

📒 Files selected for processing (1)
  • apps/api/src/core/services/job-queue/job-queue.service.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

**/*.{ts,tsx,js}: Never use type any or cast to type any. Always define the proper TypeScript types.
Never use deprecated methods from libraries.
Don't add unnecessary comments to the code.

Files:

  • apps/api/src/core/services/job-queue/job-queue.service.ts
🧠 Learnings (2)
📚 Learning: 2025-07-03T14:40:49.886Z
Learnt from: jzsfkzm
Repo: akash-network/console PR: 1498
File: apps/api/src/services/external/templates/template-fetcher.service.ts:0-0
Timestamp: 2025-07-03T14:40:49.886Z
Learning: In the TemplateFetcherService class in apps/api/src/services/external/templates/template-fetcher.service.ts, the error handling strategy should maintain process resilience by catching all errors and returning null rather than re-throwing critical errors, to avoid breaking the whole template fetching process.

Applied to files:

  • apps/api/src/core/services/job-queue/job-queue.service.ts
📚 Learning: 2025-07-24T17:00:52.361Z
Learnt from: baktun14
Repo: akash-network/console PR: 1725
File: apps/api/src/utils/constants.ts:5-5
Timestamp: 2025-07-24T17:00:52.361Z
Learning: In the Akash Network Console project, when cross-cutting concerns or broader refactoring issues are identified during PR review, the preferred approach is to create a separate GitHub issue to track the work rather than expanding the scope of the current PR. This maintains focus and allows for proper planning of architectural improvements.

Applied to files:

  • apps/api/src/core/services/job-queue/job-queue.service.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: test-build
  • GitHub Check: test-build
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: Validate local packages
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (3)
apps/api/src/core/services/job-queue/job-queue.service.ts (3)

101-121: Improved error handling addresses previous review concerns.

The implementation now differentiates between terminal-state errors (logged as warnings) and other errors (rethrown for alerting), which directly addresses the previous review feedback about preserving error propagation for non-terminal failures.


123-143: Consistent error handling implementation.

The error handling logic mirrors the cancel method appropriately, maintaining consistency across both operations.


145-161: Add integration tests to verify error message patterns match pg-boss 11.0.4 behavior.

The regex patterns assume specific error message formats from pg-boss (/job.+already.+completed/i, /job.+in.+terminal.+state/i, etc.). These patterns lack corresponding test coverage—the test file includes only a success case for cancel() with no error scenario tests. Verify these patterns against actual pg-boss 11.0.4 error messages through integration tests or consult pg-boss source/documentation to confirm the error message formats match, ensuring the terminal-state detection reliably catches intended errors without false negatives.


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

@codecov
Copy link

codecov bot commented Dec 22, 2025

Codecov Report

❌ Patch coverage is 23.40426% with 36 lines in your changes missing coverage. Please review.
✅ Project coverage is 50.91%. Comparing base (65d6f7e) to head (4207e28).
⚠️ Report is 5 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...i/src/core/services/job-queue/job-queue.service.ts 15.78% 15 Missing and 1 partial ⚠️
.../billing-usage/AccountOverview/AccountOverview.tsx 0.00% 13 Missing ⚠️
...ces/wallet-reload-job/wallet-reload-job.service.ts 50.00% 4 Missing ⚠️
apps/deploy-web/src/components/layout/Sidebar.tsx 0.00% 2 Missing ⚠️
...y-web/src/components/providers/NetworkCapacity.tsx 0.00% 1 Missing ⚠️

❌ Your patch status has failed because the patch coverage (15.78%) is below the target coverage (50.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2409      +/-   ##
==========================================
- Coverage   51.17%   50.91%   -0.27%     
==========================================
  Files        1072     1061      -11     
  Lines       29246    28940     -306     
  Branches     6434     6412      -22     
==========================================
- Hits        14968    14735     -233     
+ Misses      13864    13792      -72     
+ Partials      414      413       -1     
Flag Coverage Δ *Carryforward flag
api 80.06% <28.57%> (-0.15%) ⬇️
deploy-web 31.26% <15.78%> (+0.09%) ⬆️
log-collector ?
notifications 87.94% <ø> (ø) Carriedforward from 5e2125c
provider-console 81.48% <ø> (ø)
provider-proxy 84.35% <ø> (ø) Carriedforward from 5e2125c

*This pull request uses carry forward flags. Click here to find out more.

Files with missing lines Coverage Δ
...ervices/wallet-settings/wallet-settings.service.ts 96.96% <100.00%> (ø)
...rc/components/billing-usage/BillingUsageLayout.tsx 0.00% <ø> (ø)
...mponents/billing-usage/BillingView/BillingView.tsx 86.20% <100.00%> (ø)
...ng-usage/PaymentMethodsView/PaymentMethodsView.tsx 94.44% <100.00%> (+0.32%) ⬆️
...loy-web/src/components/layout/SidebarGroupMenu.tsx 45.45% <ø> (ø)
...y-web/src/components/providers/NetworkCapacity.tsx 0.00% <0.00%> (ø)
apps/deploy-web/src/components/layout/Sidebar.tsx 38.98% <0.00%> (ø)
...ces/wallet-reload-job/wallet-reload-job.service.ts 44.44% <50.00%> (+1.11%) ⬆️
.../billing-usage/AccountOverview/AccountOverview.tsx 0.00% <0.00%> (ø)
...i/src/core/services/job-queue/job-queue.service.ts 82.82% <15.78%> (-13.61%) ⬇️

... and 27 files with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
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 (1)
apps/deploy-web/src/components/providers/NetworkCapacity.tsx (1)

220-220: Fix typo: "emphemeral" → "ephemeral".

Pre-existing typo in storage labels. The correct spelling is "ephemeral."

🔎 Proposed fixes for the typos
     {
       id: "active-ephemeral",
-      label: "Active emphemeral",
+      label: "Active ephemeral",
       color: tw.theme.colors["primary"].DEFAULT,
       value: props.activeEphemeralStorage
     },
     {
       id: "available-emphemeral",
-      label: "Available emphemeral",
+      label: "Available ephemeral",
       color: resolvedTheme === "dark" ? tw.theme.colors.neutral[400] : tw.theme.colors.neutral[500],
       value: props.availableEphemeralStorage + props.pendingEphemeralStorage
     },

Also applies to: 232-232

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 62690c0 and 2afbf53.

📒 Files selected for processing (10)
  • apps/api/src/billing/services/wallet-reload-job/wallet-reload-job.service.ts
  • apps/api/src/billing/services/wallet-settings/wallet-settings.service.spec.ts
  • apps/api/src/billing/services/wallet-settings/wallet-settings.service.ts
  • apps/api/src/core/services/job-queue/job-queue.service.ts
  • apps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsx
  • apps/deploy-web/src/components/billing-usage/BillingUsageLayout.tsx
  • apps/deploy-web/src/components/billing-usage/BillingView/BillingView.tsx
  • apps/deploy-web/src/components/billing-usage/PaymentMethodsView/PaymentMethodsView.tsx
  • apps/deploy-web/src/components/providers/NetworkCapacity.tsx
  • packages/ui/components/slider.tsx
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

**/*.{ts,tsx,js}: Never use type any or cast to type any. Always define the proper TypeScript types.
Never use deprecated methods from libraries.
Don't add unnecessary comments to the code.

Files:

  • apps/deploy-web/src/components/billing-usage/BillingView/BillingView.tsx
  • apps/deploy-web/src/components/providers/NetworkCapacity.tsx
  • apps/deploy-web/src/components/billing-usage/BillingUsageLayout.tsx
  • packages/ui/components/slider.tsx
  • apps/api/src/core/services/job-queue/job-queue.service.ts
  • apps/api/src/billing/services/wallet-settings/wallet-settings.service.ts
  • apps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsx
  • apps/api/src/billing/services/wallet-reload-job/wallet-reload-job.service.ts
  • apps/deploy-web/src/components/billing-usage/PaymentMethodsView/PaymentMethodsView.tsx
  • apps/api/src/billing/services/wallet-settings/wallet-settings.service.spec.ts
**/*.spec.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/no-jest-mock.mdc)

Don't use jest.mock() in test files. Instead, use jest-mock-extended to create mocks and pass mocks as dependencies to the service under test

Use setup function instead of beforeEach in test files. The setup function must be at the bottom of the root describe block, should create an object under test and return it, accept a single parameter with inline type definition, avoid shared state, and not have a specified return type.

**/*.spec.{ts,tsx}: Use <Subject>.name in the root describe suite description instead of hardcoded class/service name strings to enable automated refactoring tools to find all references
Use either a method name or a condition starting with 'when' for nested suite descriptions in tests
Use present simple, 3rd person singular for test descriptions without prepending 'should'

Files:

  • apps/api/src/billing/services/wallet-settings/wallet-settings.service.spec.ts
🧠 Learnings (5)
📚 Learning: 2025-06-05T21:07:51.985Z
Learnt from: baktun14
Repo: akash-network/console PR: 1432
File: apps/deploy-web/src/components/deployments/DeploymentAlerts/DeploymentCloseAlert.tsx:38-38
Timestamp: 2025-06-05T21:07:51.985Z
Learning: The ContactPointSelect component in apps/deploy-web/src/components/alerts/ContactPointSelectForm/ContactPointSelect.tsx uses the useFormContext hook internally to connect to React Hook Form, so it doesn't need to be wrapped in a FormField component.

Applied to files:

  • apps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsx
📚 Learning: 2025-11-12T16:36:02.543Z
Learnt from: baktun14
Repo: akash-network/console PR: 2203
File: apps/deploy-web/src/components/onboarding/steps/PaymentMethodContainer/PaymentMethodContainer.tsx:161-168
Timestamp: 2025-11-12T16:36:02.543Z
Learning: In apps/deploy-web/src/components/onboarding/steps/PaymentMethodContainer/PaymentMethodContainer.tsx, the organization field captured during payment method setup is internal metadata. Errors from stripe.updateCustomerOrganization should be logged to Sentry but not surfaced to users, and the flow should continue even if the organization update fails, as it's non-critical and not something users can fix.

Applied to files:

  • apps/deploy-web/src/components/billing-usage/PaymentMethodsView/PaymentMethodsView.tsx
📚 Learning: 2025-09-18T07:50:31.224Z
Learnt from: baktun14
Repo: akash-network/console PR: 1933
File: apps/deploy-web/src/components/onboarding/steps/PaymentVerificationCard/PaymentVerificationCard.tsx:43-63
Timestamp: 2025-09-18T07:50:31.224Z
Learning: PaymentVerificationCard component is wrapped by Stripe Elements provider in its parent component PaymentMethodStep, so PaymentMethodForm inside PaymentVerificationCard has access to Stripe context without needing its own Elements wrapper.

Applied to files:

  • apps/deploy-web/src/components/billing-usage/PaymentMethodsView/PaymentMethodsView.tsx
📚 Learning: 2025-07-29T15:14:53.419Z
Learnt from: baktun14
Repo: akash-network/console PR: 1750
File: apps/deploy-web/src/components/onboarding/steps/PaymentVerificationCard/PaymentVerificationCard.tsx:33-37
Timestamp: 2025-07-29T15:14:53.419Z
Learning: CardDescription component renders as a p element, so nested content should use div elements instead of p elements to avoid invalid HTML structure (p > p is not allowed).

Applied to files:

  • apps/deploy-web/src/components/billing-usage/PaymentMethodsView/PaymentMethodsView.tsx
📚 Learning: 2025-07-29T15:14:53.419Z
Learnt from: baktun14
Repo: akash-network/console PR: 1750
File: apps/deploy-web/src/components/onboarding/steps/PaymentVerificationCard/PaymentVerificationCard.tsx:33-37
Timestamp: 2025-07-29T15:14:53.419Z
Learning: CardDescription from akashnetwork/ui/components renders as a <p> element, so any block-level content inside it should use <div> (not <p>) to avoid invalid HTML nesting.

Applied to files:

  • apps/deploy-web/src/components/billing-usage/PaymentMethodsView/PaymentMethodsView.tsx
🧬 Code graph analysis (2)
apps/deploy-web/src/components/billing-usage/BillingUsageLayout.tsx (1)
packages/ui/components/tabs.tsx (1)
  • Tabs (48-48)
apps/api/src/core/services/job-queue/job-queue.service.ts (1)
packages/logging/src/services/logger/logger.service.ts (1)
  • error (141-143)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: test-build
  • GitHub Check: test-build
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: Validate local packages
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (11)
apps/deploy-web/src/components/billing-usage/BillingView/BillingView.tsx (1)

174-177: LGTM!

Clean styling refinement that standardizes button sizing. The change from explicit height/gap to the component's size="sm" prop is a good pattern and maintains the same functionality and disabled state logic.

apps/deploy-web/src/components/billing-usage/BillingUsageLayout.tsx (1)

45-45: LGTM! Clean UI spacing improvement.

The increased vertical spacing (space-y-6 instead of space-y-4) improves the visual layout of the billing tabs without affecting any functionality.

packages/ui/components/slider.tsx (1)

11-11: LGTM: Visual refinement for slider track.

The background color change updates the slider track styling while preserving all functionality.

apps/api/src/billing/services/wallet-settings/wallet-settings.service.spec.ts (1)

86-92: LGTM: Test expectations updated for new scheduling API.

The tests correctly reflect the updated scheduleForWalletSetting signature, passing { prevAction: "cancel" } to ensure previous jobs are canceled when enabling auto-reload.

Also applies to: 145-151

apps/api/src/core/services/job-queue/job-queue.service.ts (1)

101-119: LGTM: Graceful error handling for terminal state operations.

The try/catch blocks appropriately handle scenarios where jobs are already in terminal states (completed, cancelled, failed). This directly addresses the reported error when toggling auto credit reload. The WARN-level logging provides observability without throwing errors that would disrupt the flow.

Also applies to: 121-139

apps/deploy-web/src/components/billing-usage/PaymentMethodsView/PaymentMethodsView.tsx (1)

5-5: LGTM: UI refinements for payment methods view.

The addition of the Plus icon and layout adjustments improve visual clarity and consistency. All changes are styling-only with no functional impact.

Also applies to: 71-101

apps/api/src/billing/services/wallet-settings/wallet-settings.service.ts (1)

126-127: LGTM: Explicit previous job cancellation on re-enable.

Passing prevAction: "cancel" ensures that any previously cancelled job is properly cleaned up before scheduling a new one, which directly addresses the scheduling conflict reported in issue #2408.

apps/api/src/billing/services/wallet-reload-job/wallet-reload-job.service.ts (3)

7-7: LGTM: LoggerService integration.

The logger dependency and context initialization follow standard patterns and improve observability for wallet reload job operations.

Also applies to: 14-18


35-51: LGTM: Flexible previous job cleanup with logging.

The configurable prevAction parameter (defaulting to "complete") provides flexibility for different scheduling scenarios. The logging enhances observability around job lifecycle management.


78-84: LGTM: Comprehensive logging for successful scheduling.

The JOB_SCHEDULED log includes all relevant context for tracking scheduled jobs.

apps/deploy-web/src/components/billing-usage/AccountOverview/AccountOverview.tsx (1)

1-202: LGTM: Comprehensive UI improvements for account overview.

The refactored component enhances UX with:

  • Proper skeleton loading states
  • Payment method availability checks and messaging
  • Conditional tooltips and disabled states
  • Clear calls-to-action for users without payment methods

All conditional logic correctly handles the various states (loading, no payment method, payment method available).

Copy link
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

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2afbf53 and 597d7b2.

📒 Files selected for processing (4)
  • apps/api/src/billing/services/wallet-reload-job/wallet-reload-job.service.ts
  • apps/api/src/billing/services/wallet-settings/wallet-settings.service.ts
  • apps/deploy-web/src/components/layout/Sidebar.tsx
  • packages/ui/components/custom/date-range-picker.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/api/src/billing/services/wallet-settings/wallet-settings.service.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

**/*.{ts,tsx,js}: Never use type any or cast to type any. Always define the proper TypeScript types.
Never use deprecated methods from libraries.
Don't add unnecessary comments to the code.

Files:

  • apps/api/src/billing/services/wallet-reload-job/wallet-reload-job.service.ts
  • apps/deploy-web/src/components/layout/Sidebar.tsx
  • packages/ui/components/custom/date-range-picker.tsx
🧠 Learnings (1)
📚 Learning: 2025-10-31T11:26:42.138Z
Learnt from: stalniy
Repo: akash-network/console PR: 2138
File: apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.ts:379-382
Timestamp: 2025-10-31T11:26:42.138Z
Learning: In TypeScript/JavaScript, the pattern of checking a cached value and then performing an async operation to fetch it without proper synchronization is race condition unsafe:
```typescript
private async getAddress() {
  if (!this.address) {
    this.address = await this.wallet.getFirstAddress();
  }
  return this.address;
}
```
Multiple concurrent calls can all pass the `if (!this.address)` check before any of them sets the value, leading to duplicate async operations. This should be flagged as a race condition. Proper synchronization (mutex, atomic promise caching, or guaranteed single-threaded execution) is required.

Applied to files:

  • apps/api/src/billing/services/wallet-reload-job/wallet-reload-job.service.ts
🧬 Code graph analysis (2)
apps/api/src/billing/services/wallet-reload-job/wallet-reload-job.service.ts (3)
apps/api/src/core/services/job-queue/job-queue.service.ts (1)
  • singleton (12-251)
apps/api/src/billing/services/wallet-balance-reload-check/wallet-balance-reload-check.handler.ts (1)
  • singleton (35-222)
apps/api/src/billing/repositories/wallet-settings/wallet-settings.repository.ts (1)
  • singleton (24-66)
apps/deploy-web/src/components/layout/Sidebar.tsx (3)
apps/provider-console/src/utils/styleUtils.ts (1)
  • cn (4-6)
packages/ui/components/button.tsx (1)
  • buttonVariants (46-46)
apps/deploy-web/src/utils/urlUtils.ts (1)
  • UrlService (16-96)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: test-build
  • GitHub Check: test-build
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: Validate local packages
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (5)
apps/deploy-web/src/components/layout/Sidebar.tsx (1)

308-321: LGTM! Clean UI refinement for the Deploy button.

The wrapper div with flex layout and conditional padding provides better control over the Deploy button's positioning and spacing. The addition of rounded-sm for the collapsed state improves the visual appearance when the sidebar is closed.

apps/api/src/billing/services/wallet-reload-job/wallet-reload-job.service.ts (4)

7-7: LGTM: Logger dependency properly integrated.

The LoggerService is correctly added via dependency injection and initialized with appropriate context, enabling better observability for job scheduling operations.

Also applies to: 14-18


73-78: LGTM: Success logging aids debugging.

The structured logging of successful job scheduling with relevant context (jobId, userId, startAfter) provides good observability for troubleshooting scheduling issues.


35-51: Good defensive cleanup before scheduling.

This cleanup logic is essential to the fix—by canceling or completing any previous job before creating a new one, it prevents the "job already exists" error when users toggle auto reload. The resilient error handling in JobQueueService ensures terminal-state jobs don't cause failures.

The autoReloadJobId field is correctly preserved in wallet settings when auto reload is disabled. The upsertWalletSetting implementation only updates fields present in WalletSettingInput (which excludes autoReloadJobId), allowing the job ID to persist so cleanup can be executed. The #arrangeSchedule method confirms this design—it checks for an existing autoReloadJobId when autoReloadEnabled becomes false and cancels the job accordingly.


62-71: Error throwing is correct but consider if callers will retry indefinitely.

Throwing when createdJobId is null properly ensures transaction rollback and database consistency. However, without query-and-reuse logic (as suggested in the past review), calling code that retries could enter a loop if the same condition recurs:

  1. After successful cleanup (lines 35-51): This scenario should rarely occur since the cleanup removes existing jobs before creation. A null return suggests either a concurrent race or an orphaned job.
  2. Concurrent race condition: If two requests both pass the cleanup check and attempt to create with the same singletonKey, the loser will throw here and potentially retry.

The transaction rollback ensures data consistency, but consider whether the calling code has retry logic that should be adjusted or whether the frequency of this error warrants logging additional diagnostics (e.g., job IDs that may exist in pg-boss but not in the database).

Copy link
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: 0

🧹 Nitpick comments (1)
packages/ui/components/custom/date-range-picker.tsx (1)

233-257: Consider unifying date format and button styling across mobile/desktop variants.

There are minor inconsistencies between the mobile and desktop implementations:

  • Date format: Mobile uses MMM dd, yyyy (e.g., "Dec 22, 2024") while desktop uses LLL dd, y (e.g., "December 22, 2024")
  • Clear button sizing: Mobile explicitly sets h-12 w-12 while desktop relies on size="icon" without explicit dimensions

These differences may be intentional for responsive design, but consider standardizing them for consistency unless there's a specific UX reason for the variation.

Also applies to: 373-395

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 597d7b2 and a3ad495.

📒 Files selected for processing (3)
  • apps/api/src/billing/services/wallet-reload-job/wallet-reload-job.service.ts
  • apps/deploy-web/src/components/billing-usage/BillingView/BillingView.tsx
  • packages/ui/components/custom/date-range-picker.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/deploy-web/src/components/billing-usage/BillingView/BillingView.tsx
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

**/*.{ts,tsx,js}: Never use type any or cast to type any. Always define the proper TypeScript types.
Never use deprecated methods from libraries.
Don't add unnecessary comments to the code.

Files:

  • packages/ui/components/custom/date-range-picker.tsx
  • apps/api/src/billing/services/wallet-reload-job/wallet-reload-job.service.ts
🧠 Learnings (1)
📚 Learning: 2025-10-31T11:26:42.138Z
Learnt from: stalniy
Repo: akash-network/console PR: 2138
File: apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.ts:379-382
Timestamp: 2025-10-31T11:26:42.138Z
Learning: In TypeScript/JavaScript, the pattern of checking a cached value and then performing an async operation to fetch it without proper synchronization is race condition unsafe:
```typescript
private async getAddress() {
  if (!this.address) {
    this.address = await this.wallet.getFirstAddress();
  }
  return this.address;
}
```
Multiple concurrent calls can all pass the `if (!this.address)` check before any of them sets the value, leading to duplicate async operations. This should be flagged as a race condition. Proper synchronization (mutex, atomic promise caching, or guaranteed single-threaded execution) is required.

Applied to files:

  • apps/api/src/billing/services/wallet-reload-job/wallet-reload-job.service.ts
🧬 Code graph analysis (2)
packages/ui/components/custom/date-range-picker.tsx (2)
packages/ui/components/button.tsx (1)
  • Button (46-46)
apps/provider-console/src/utils/styleUtils.ts (1)
  • cn (4-6)
apps/api/src/billing/services/wallet-reload-job/wallet-reload-job.service.ts (2)
apps/api/src/billing/services/wallet-settings/wallet-settings.service.ts (1)
  • singleton (18-145)
apps/api/src/billing/repositories/wallet-settings/wallet-settings.repository.ts (1)
  • singleton (24-66)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: test-build
  • GitHub Check: test-build
  • GitHub Check: Validate local packages
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (5)
packages/ui/components/custom/date-range-picker.tsx (1)

233-257: UI restructuring looks good – clear button properly separated.

The refactoring successfully moves the clear action from being nested within the trigger to a separate button, avoiding the nested interactive elements issue flagged in previous reviews. The clear button has proper accessibility with aria-label, and the layout with flex items-center gap-2 provides appropriate spacing.

apps/api/src/billing/services/wallet-reload-job/wallet-reload-job.service.ts (4)

7-7: Logging integration improves observability.

Adding structured logging with context-specific events (PREVIOUS_JOB_CLEANUP, JOB_CREATION_FAILED, JOB_SCHEDULED) will significantly help diagnose issues like #2408. The logger context is properly initialized in the constructor.

Also applies to: 14-18


72-78: Success logging provides valuable audit trail.

The JOB_SCHEDULED event with jobId, userId, and startAfter details will be helpful for tracking scheduled jobs and correlating with execution events.


35-50: Verify singleton lock behavior when cancel/complete operations fail or race conditions occur.

The concern is theoretically valid: singletonKey ensures only one job can be queued or active, but relies on jobs properly transitioning to terminal states. If cancel or complete operations fail silently (as the comment acknowledges is possible), the previous job may remain in active state, blocking new job creation. When the enqueue call at line 55 returns null due to this constraint, the error at line 69 will be thrown.

This scenario is plausible when toggling auto-reload off then back on, if:

  • The cancel/complete operation doesn't fully transition the job to a terminal state
  • The singleton constraint isn't released before attempting the new enqueue
  • Silent failures prevent awareness of incomplete cleanup

Consider explicitly handling the case where job cleanup doesn't release the lock, or ensure cancel/complete operations are properly awaited with error handling to confirm job state transitions.


52-70: Review transaction handling between wallet settings update and job enqueue operations.

The transaction wrapper at line 34 does protect against the worst-case scenario where jobId is persisted but no job exists. When createdJobId is null, the error thrown at line 69 triggers a rollback of the database update at line 53.

However, there is a fundamental architectural limitation: pg-boss supports creating jobs within an existing database transaction, but the current implementation does not leverage this. The JobQueueService creates its own PgBoss instance with a separate connectionString and does not accept or use transaction context from TxService. This means jobQueueService.enqueue() at line 55 executes on a separate database connection pool and does not participate in the drizzle transaction.

While the error handling prevents the invalid jobId from persisting when job creation fails, a race condition remains: if the job is created in pg-boss but the subsequent transaction fails for an unrelated reason, the job exists without a corresponding database record. Consider refactoring to either:

  1. Pass the active transaction context to JobQueueService.enqueue() so pg-boss operations participate in the same transaction, or
  2. Document this limitation and implement compensating logic (e.g., polling or cleanup jobs) to handle inconsistent states.

Copy link
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: 0

🧹 Nitpick comments (1)
apps/deploy-web/src/components/layout/Sidebar.tsx (1)

307-308: Verify the nested padding structure.

Both the outer container (line 307) and inner centered container (line 308) apply top padding (pt-4). This creates cumulative spacing:

  • When isNavOpen: outer has p-4 (includes top) + inner has pt-4 = 2rem total top spacing
  • When !isNavOpen: outer has pt-4 + inner has pt-4 = 2rem total top spacing

Confirm this is the intended design, as it might result in more spacing than expected.

💡 Consider consolidating padding if excessive spacing is unintended

If the double padding creates excessive spacing, consider applying pt-4 only to the outer container:

-      <div className={cn("flex w-full flex-col items-center justify-between", { ["p-4"]: isNavOpen, ["pt-4"]: !isNavOpen })}>
-        <div className={cn("flex w-full items-center justify-center pt-4")}>
+      <div className={cn("flex w-full flex-col items-center justify-between", { ["p-4"]: isNavOpen, ["pt-4"]: !isNavOpen })}>
+        <div className={cn("flex w-full items-center justify-center")}>
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2594eea and 5e2125c.

📒 Files selected for processing (1)
  • apps/deploy-web/src/components/layout/Sidebar.tsx
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

**/*.{ts,tsx,js}: Never use type any or cast to type any. Always define the proper TypeScript types.
Never use deprecated methods from libraries.
Don't add unnecessary comments to the code.

Files:

  • apps/deploy-web/src/components/layout/Sidebar.tsx
🧬 Code graph analysis (1)
apps/deploy-web/src/components/layout/Sidebar.tsx (3)
apps/provider-console/src/utils/styleUtils.ts (1)
  • cn (4-6)
packages/ui/components/button.tsx (1)
  • buttonVariants (46-46)
apps/deploy-web/src/utils/urlUtils.ts (1)
  • UrlService (16-96)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: test-build
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: test-build
  • GitHub Check: Validate local packages
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (1)
apps/deploy-web/src/components/layout/Sidebar.tsx (1)

309-321: Deploy button implementation looks good.

The responsive button sizing and conditional styling are correctly implemented. The use of aria-disabled (line 316) instead of the disabled prop is appropriate for accessibility—it allows screen readers to announce the disabled state while keeping the element in the tab order. Ensure that click handling properly respects the settings.isBlockchainDown state to prevent unintended navigation.

stalniy
stalniy previously approved these changes Dec 23, 2025
@baktun14 baktun14 merged commit d0f0fb8 into main Dec 23, 2025
64 of 66 checks passed
@baktun14 baktun14 deleted the fix/styling-post-reskin branch December 23, 2025 18:53
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.

ERROR (88921): Failed to schedule wallet balance reload check

2 participants

Comments