Skip to content

Fix fallback provision bucket assignment#692

Merged
chibie merged 3 commits intostablefrom
fix-fallback-provision-bucket-assignment
Feb 17, 2026
Merged

Fix fallback provision bucket assignment#692
chibie merged 3 commits intostablefrom
fix-fallback-provision-bucket-assignment

Conversation

@onahprosper
Copy link
Collaborator

@onahprosper onahprosper commented Feb 17, 2026

Description

Describe the purpose of this PR along with any background information and the impacts of the proposed change. For the benefit of the community, please do not assume prior context.

Provide details that support your chosen implementation, including: breaking changes, alternatives considered, changes to the API, contracts etc.

References

Include any links supporting this change such as a:

If there are no references, simply delete this section.

Testing

Describe how this can be tested by reviewers. Be specific about anything not tested and reasons why. If this project has unit and/or integration testing, tests should be added for new functionality and existing tests should complete without errors.

Please include any manual steps for testing end-to-end or functionality not covered by unit/integration tests.

Also include details of the environment this PR was developed in (language/platform/browser version).

  • This change adds test coverage for new/changed/fixed functionality

Checklist

  • I have added documentation and tests for new/changed functionality in this PR
  • All active GitHub checks for tests, formatting, and security are passing
  • The correct base branch is being used, if not main

By submitting a PR, I agree to Paycrest's Contributor Code of Conduct and Contribution Guide.

Summary by CodeRabbit

  • Bug Fixes

    • Improved reliability of fallback payment assignment with enhanced error handling and resolution logic for edge cases.
    • Added detailed error logging for fallback assignment failures.
  • Refactor

    • Optimized data loading for payment order processing to reduce database queries.

- Updated TryFallbackAssignment to eagerly load ProvisionBucket and Currency, reducing the need for separate fallback queries.
- Enhanced logic to resolve ProvisionBucket based on institution currency and fiat amount when not present, improving fallback assignment reliability.
- Improved error handling for missing ProvisionBucket and currency, ensuring clearer error messages during fallback operations.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 17, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The changes enhance the priority queue service to implement fallback bucket resolution when a ProvisionBucket is missing, inferring it from institution currency and fiat amount calculations. Error handling in stale operations is refactored to add structured logging for fallback assignment failures.

Changes

Cohort / File(s) Summary
Priority Queue Fallback Resolution
services/priority_queue.go
Replaces direct bucket load with eager-load query preloading ProvisionBucket and Currency. Adds fallback logic to resolve missing ProvisionBucket by loading institution currency, computing fiatAmount, and querying for matching bucket by min/max amounts and currency. Introduces error handling for missing currency on the bucket.
Stale Operations Logging
tasks/stale_ops.go
Refactors TryFallbackAssignment invocation from inline declaration to explicit error variable. Adds structured logging that emits OrderID and error details when fallback assignment fails, while preserving existing refund-cancellation logic.

Sequence Diagram(s)

sequenceDiagram
    participant TryFallback as TryFallbackAssignment
    participant DB as Database/Ent
    participant Resolve as Bucket Resolution
    
    TryFallback->>DB: Load PaymentOrder with eager-load<br/>(preload ProvisionBucket, Currency)
    DB-->>TryFallback: currentOrder with preloaded relations
    
    alt ProvisionBucket exists
        TryFallback->>TryFallback: Use currentOrder.Edges.ProvisionBucket
    else ProvisionBucket is nil
        TryFallback->>Resolve: Resolve missing bucket
        Resolve->>DB: Load Institution Currency
        DB-->>Resolve: currency data
        Resolve->>Resolve: Compute fiatAmount = order.Amount * order.Rate
        Resolve->>DB: Query ProvisionBucket by<br/>min/max amounts & currency
        DB-->>Resolve: matching bucket or nil
        alt Bucket found
            Resolve-->>TryFallback: resolved ProvisionBucket
        else Bucket not found or currency nil
            Resolve-->>TryFallback: descriptive error
        end
    end
    
    TryFallback->>TryFallback: Return result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • chibie
  • 5ran6

Poem

🐰 When buckets go missing, no need to despair,
We check the old rates and infer from the air,
Institution currency guides us back home,
Through fiat amounts and the queries we roam,
Fallbacks and logs keep our orders on track! 📊

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning PR description only includes the template boilerplate with no actual implementation details, context, or explanation of the changes. Add substantive description of the changes, including purpose, background, impacts, and references to linked issues.
Linked Issues check ⚠️ Warning The code changes optimize fallback bucket assignment and error handling, but do not implement the core requirement of saving and checking previous rates from Redis [#407]. Implement Redis _prev key logic in CreatePriorityQueueForBucket and AssignLockPaymentOrder to fully address issue #407 requirements.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed Title clearly identifies the main change: fixing fallback provision bucket assignment logic, which is the core modification in both files.
Out of Scope Changes check ✅ Passed The changes to TryFallbackAssignment and logging in RetryStaleUserOperations are focused improvements aligned with the fallback assignment objective and not out of scope.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-fallback-provision-bucket-assignment

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


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.

@chibie chibie changed the base branch from main to stable February 17, 2026 10:40
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: 1

🧹 Nitpick comments (1)
services/priority_queue.go (1)

776-797: Bucket resolution uses order.Amount and order.Rate from the original (potentially stale) order parameter.

Lines 778 and 782 reference order.Institution, order.Amount, and order.Rate — the raw *ent.PaymentOrder passed in — while the freshly loaded currentOrder is also available. If the rate or amount could have been updated since the caller fetched the order, using stale values could resolve to the wrong bucket.

This may be fine if the caller always passes a recently-fetched order, but worth noting for robustness. Consider using currentOrder.Amount and currentOrder.Rate for the bucket resolution query to be consistent with the state-check done against currentOrder above.

Proposed fix
-		fiatAmount := order.Amount.Mul(order.Rate)
+		fiatAmount := currentOrder.Amount.Mul(currentOrder.Rate)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@services/priority_queue.go` around lines 776 - 797, The bucket resolution is
using potentially stale values from the original order parameter
(order.Institution, order.Amount, order.Rate); update the logic that computes
fiatAmount and the provision bucket query to reference currentOrder (e.g.,
currentOrder.Amount, currentOrder.Rate, currentOrder.Institution) instead of
order so the ProvisionBucket resolution (fields.ProvisionBucket and the
storage.Client.ProvisionBucket query) uses the freshest loaded state.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@services/priority_queue.go`:
- Around line 778-781: The current return in the fallback bucket resolution
wraps instErr even when instErr is nil, causing fmt.Errorf to print %!w(<nil>)
when institution.Edges.FiatCurrency == nil; update the logic in the block that
calls utils.GetInstitutionByCode (and checks institution.Edges.FiatCurrency) to
return a distinct non-wrapped error when the currency edge is missing (e.g.,
create a new error value or format a message without %w) and only use %w to wrap
instErr when instErr is non-nil; adjust the return around fields.ID.String()
accordingly so the error for a missing fiat currency is clear and does not
attempt to wrap nil.

---

Nitpick comments:
In `@services/priority_queue.go`:
- Around line 776-797: The bucket resolution is using potentially stale values
from the original order parameter (order.Institution, order.Amount, order.Rate);
update the logic that computes fiatAmount and the provision bucket query to
reference currentOrder (e.g., currentOrder.Amount, currentOrder.Rate,
currentOrder.Institution) instead of order so the ProvisionBucket resolution
(fields.ProvisionBucket and the storage.Client.ProvisionBucket query) uses the
freshest loaded state.

chibie and others added 2 commits February 17, 2026 13:09
…ignment

- Introduced a new test case to validate the fallback assignment logic when the order rate does not match any provider in the queue but falls within the fallback provider's slippage.
- Enhanced setup for public and fallback provider tokens, ensuring proper rate and slippage configurations.
- Verified that the fallback assignment occurs correctly and that relevant fields are updated post-assignment.
- Improved error handling and assertions to ensure robust testing of fallback scenarios.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@chibie chibie merged commit 743b8e7 into stable Feb 17, 2026
2 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.

Save previous provider rates in priority queue to reduce order failures

2 participants

Comments