Skip to content

perf: add bounded oracle HTTP client - #2825

Merged
graphite-app[bot] merged 1 commit into
mainfrom
arda/oracle-http-primitives
Aug 11, 2026
Merged

perf: add bounded oracle HTTP client#2825
graphite-app[bot] merged 1 commit into
mainfrom
arda/oracle-http-primitives

Conversation

@findolor

@findolor findolor commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

Why

Oracle-backed quote preparation currently creates a fresh HTTP client for every
pair and has no reusable bounded execution primitive. This adds connection-pool
reuse and a conservative per-origin limit before the quote sweep is made
concurrent.

What changed

  • add a reusable OracleClient backed by one native/WASM-compatible reqwest
    connection pool
  • cap oracle POSTs at eight in flight per origin across independently created clients
  • add ordered bounded execution that avoids head-of-line blocking
  • route the existing single and batch APIs through the shared client without
    changing their signatures, timeout, response validation, or status handling
  • add deterministic tests for the concurrency bound, shared limiter, positional
    stability, partial failure isolation, and slow-leading-request behavior

Intentionally unchanged

  • configured oracle URLs are not assumed to support batch request bodies
  • no retries are added for 429/503 or other failures because the endpoint
    contract does not declare POST idempotency
  • signed-context and chain quote behavior are unchanged in this prerequisite PR

Local verification

  • cargo test -p raindex_quote --lib — 63 passed
  • cargo clippy -p raindex_quote --all-targets --all-features -- -D warnings -D clippy::all
  • cargo fmt --all -- --check
  • nix develop .#wasm-shell -c bash -c 'CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER=wasm-bindgen-test-runner cargo test --target wasm32-unknown-unknown --lib -p raindex_quote'
  • rainix-rs-static

Review focus

Please pay particular attention to the per-origin limit of eight, indexed
buffer_unordered ordering restoration, and native/WASM client reuse.

Summary by CodeRabbit

  • Performance

    • Oracle requests now reuse shared HTTP resources for improved efficiency.
    • Concurrent requests are bounded, with configurable limits for improved stability under load.
  • Reliability

    • Batch results preserve their original request order.
    • Individual request errors are reported without blocking other requests.
    • Requests now validate endpoints, apply timeouts, and redact sensitive URL details from errors.
    • Response handling and request validation are more consistent.

findolor commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator Author

How to use the Graphite Merge Queue

Add the label Raindex-queue to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Oracle request handling now uses a reusable OracleClient with shared HTTP and per-origin concurrency limits. Single, batch, and multi-request APIs use common validation, decoding, timeout, and bounded execution logic. Tests cover ordering, error isolation, and shared limits.

Changes

Oracle client concurrency

Layer / File(s) Summary
Shared request infrastructure
crates/quote/src/oracle.rs
Adds OracleClient, OracleRequest, shared HTTP client and per-origin semaphore state, URL validation, configurable limits, and sanitized request errors.
Request execution and API delegation
crates/quote/src/oracle.rs
Adds timed POST execution, response decoding, single, batch, and bounded multi-request methods, and routes existing fetch functions through OracleClient.
Concurrency validation
crates/quote/src/oracle.rs
Adds tests for request validation, error redaction, ordered failures, bounded execution, slow-task progress, shared limits, and caller-specific limits.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant OracleClient
  participant OriginSemaphore
  participant ReqwestClient
  Caller->>OracleClient: fetch_signed_contexts(requests)
  OracleClient->>OriginSemaphore: acquire bounded origin permits
  OracleClient->>ReqwestClient: send oracle POST requests
  ReqwestClient-->>OracleClient: return response bodies
  OracleClient-->>Caller: ordered SignedContextV1 results
Loading

Suggested reviewers: juanirios

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding a bounded Oracle HTTP client for performance.
✨ 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 arda/oracle-http-primitives

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
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 `@crates/quote/src/oracle.rs`:
- Around line 195-200: Move timeout configuration out of build_http_client and
apply it to each request in fetch_responses using RequestBuilder::timeout,
ensuring wasm and non-wasm requests both enforce the 10-second limit; remove the
cfg-gated ClientBuilder timeout.
🪄 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: 40732961-24eb-438b-ad73-2f0df163ebed

📥 Commits

Reviewing files that changed from the base of the PR and between a665ea9 and 29be9b8.

📒 Files selected for processing (1)
  • crates/quote/src/oracle.rs

Comment thread crates/quote/src/oracle.rs
@findolor
findolor force-pushed the arda/oracle-http-primitives branch 2 times, most recently from 0653da3 to f663494 Compare July 31, 2026 16:13
@findolor findolor self-assigned this Aug 3, 2026
@findolor
findolor requested review from 0xgleb and JuaniRios August 5, 2026 18:47
Comment thread crates/quote/src/oracle.rs Outdated
Comment thread crates/quote/src/oracle.rs Outdated
Comment thread crates/quote/src/oracle.rs Outdated
Comment thread crates/quote/src/oracle.rs Outdated
Comment thread crates/quote/src/oracle.rs Outdated
Comment thread crates/quote/src/oracle.rs Outdated
Comment thread crates/quote/src/oracle.rs Outdated
Comment thread crates/quote/src/oracle.rs Outdated
@findolor
findolor force-pushed the arda/oracle-http-primitives branch from f663494 to e8df26e Compare August 6, 2026 06:39
@coderabbitai

coderabbitai Bot commented Aug 6, 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.

@findolor
findolor requested a review from 0xgleb August 6, 2026 06:43
@findolor
findolor requested a review from JuaniRios August 7, 2026 07:16
{
let request_semaphore = self.request_semaphore(url);
let _permit = request_semaphore
.acquire()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

minor: acquire() waits outside the 10s reqwest timeout, so under same-origin contention a call can sit in the semaphore queue for much longer than ORACLE_REQUEST_TIMEOUT before send() even starts. Cancellation still works if the parent drops, and other origins stay isolated, but the constant is not an end-to-end bound. Worth documenting that, or giving acquire its own deadline once the concurrent sweep lands.

@graphite-app

graphite-app Bot commented Aug 11, 2026

Copy link
Copy Markdown

Merge activity

## Why

Oracle-backed quote preparation currently creates a fresh HTTP client for every
pair and has no reusable bounded execution primitive. This adds connection-pool
reuse and a conservative per-origin limit before the quote sweep is made
concurrent.

## What changed

- add a reusable `OracleClient` backed by one native/WASM-compatible reqwest
  connection pool
- cap oracle POSTs at eight in flight per origin across independently created clients
- add ordered bounded execution that avoids head-of-line blocking
- route the existing single and batch APIs through the shared client without
  changing their signatures, timeout, response validation, or status handling
- add deterministic tests for the concurrency bound, shared limiter, positional
  stability, partial failure isolation, and slow-leading-request behavior

## Intentionally unchanged

- configured oracle URLs are not assumed to support batch request bodies
- no retries are added for 429/503 or other failures because the endpoint
  contract does not declare POST idempotency
- signed-context and chain quote behavior are unchanged in this prerequisite PR

## Local verification

- `cargo test -p raindex_quote --lib` — 63 passed
- `cargo clippy -p raindex_quote --all-targets --all-features -- -D warnings -D clippy::all`
- `cargo fmt --all -- --check`
- `nix develop .#wasm-shell -c bash -c 'CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER=wasm-bindgen-test-runner cargo test --target wasm32-unknown-unknown --lib -p raindex_quote'`
- `rainix-rs-static`

## Review focus

Please pay particular attention to the per-origin limit of eight, indexed
`buffer_unordered` ordering restoration, and native/WASM client reuse.

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

* **Performance**
  * Oracle requests now reuse shared HTTP resources for improved efficiency.
  * Concurrent requests are bounded, with configurable limits for improved stability under load.

* **Reliability**
  * Batch results preserve their original request order.
  * Individual request errors are reported without blocking other requests.
  * Requests now validate endpoints, apply timeouts, and redact sensitive URL details from errors.
  * Response handling and request validation are more consistent.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
@graphite-app
graphite-app Bot force-pushed the arda/oracle-http-primitives branch from eb53ceb to 19bf215 Compare August 11, 2026 11:14
graphite-app Bot pushed a commit that referenced this pull request Aug 11, 2026
## Why

Quote-target construction currently awaits each oracle POST inside the nested order/input/output loops. Production evidence from the st0x REST API showed about 49.6 oracle requests and about 9.7 seconds of target-build latency per cache miss, while the subsequent batched chain quote usually took only 100–600 ms.

## What changed

- prepare every valid pair and its established single-pair oracle request body in positional order
- execute oracle POSTs through the shared process-wide client with a conservative global concurrency limit of 8
- restore results to their original request slots before composing quote targets
- preserve oracle-before-injector signed-context order
- isolate an oracle error to only its corresponding pair response
- keep the chain quote as one `BatchQuoteTarget::do_quote` operation
- add tracing for oracle request, endpoint, success/failure, concurrency-limit, batching, and duration data
- add a deterministic end-to-end test that asserts exact oracle request bodies, partial failure isolation, exact ordered RPC multicall contents, signed-context composition, distinct RPC-result slot mapping, and a single chain RPC request

## Deliberate constraints

- The existing batch encoder/API is not used automatically because order metadata exposes only an oracle URL and does not declare that the configured endpoint accepts the batch ABI body.
- Requests remain individual POSTs and are bounded globally at 8; there is no unbounded fan-out.
- No retry/backoff was added because the endpoint contract does not declare POST idempotency. Existing 429/503 status handling remains a per-pair failure.
- Public response contracts, native/WASM support, timeout behavior, and chain RPC batching semantics are unchanged.

## Verification

- `cargo test -p raindex_quote --lib`
- `cargo clippy -p raindex_quote --all-targets --all-features -- -D warnings -D clippy::all`
- `cargo fmt --all -- --check`
- `nix develop .#wasm-shell -c bash -c 'CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER=wasm-bindgen-test-runner cargo test --target wasm32-unknown-unknown --lib -p raindex_quote'`
- `nix develop .#wasm-shell -c rainix-rs-static`
- `git diff --check`

## Stack

Depends on #2825, which adds the reusable shared HTTP client and bounded ordered oracle-request primitive.
@graphite-app
graphite-app Bot merged commit 19bf215 into main Aug 11, 2026
19 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

@coderabbitai assess this PR size classification for the totality of the PR with the following criterias and report it in your comment:

S/M/L PR Classification Guidelines:

This guide helps classify merged pull requests by effort and complexity rather than just line count. The goal is to assess the difficulty and scope of changes after they have been completed.

Small (S)

Characteristics:

  • Simple bug fixes, typos, or minor refactoring
  • Single-purpose changes affecting 1-2 files
  • Documentation updates
  • Configuration tweaks
  • Changes that require minimal context to review

Review Effort: Would have taken 5-10 minutes

Examples:

  • Fix typo in variable name
  • Update README with new instructions
  • Adjust configuration values
  • Simple one-line bug fixes
  • Import statement cleanup

Medium (M)

Characteristics:

  • Feature additions or enhancements
  • Refactoring that touches multiple files but maintains existing behavior
  • Breaking changes with backward compatibility
  • Changes requiring some domain knowledge to review

Review Effort: Would have taken 15-30 minutes

Examples:

  • Add new feature or component
  • Refactor common utility functions
  • Update dependencies with minor breaking changes
  • Add new component with tests
  • Performance optimizations
  • More complex bug fixes

Large (L)

Characteristics:

  • Major feature implementations
  • Breaking changes or API redesigns
  • Complex refactoring across multiple modules
  • New architectural patterns or significant design changes
  • Changes requiring deep context and multiple review rounds

Review Effort: Would have taken 45+ minutes

Examples:

  • Complete new feature with frontend/backend changes
  • Protocol upgrades or breaking changes
  • Major architectural refactoring
  • Framework or technology upgrades

Additional Factors to Consider

When deciding between sizes, also consider:

  • Test coverage impact: More comprehensive test changes lean toward larger classification
  • Risk level: Changes to critical systems bump up a size category
  • Team familiarity: Novel patterns or technologies increase complexity

Notes:

  • the assessment must be for the totality of the PR, that means comparing the base branch to the last commit of the PR
  • the assessment output must be exactly one of: S, M or L (single-line comment) in format of: SIZE={S/M/L}
  • do not include any additional text, only the size classification
  • your assessment comment must not include tips or additional sections
  • do NOT tag me or anyone else on your comment

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

SIZE=L

You are interacting with an AI system.

graphite-app Bot pushed a commit to ST0x-Technology/st0x.rest.api that referenced this pull request Aug 12, 2026
## Dependent PRs

- Raindex bounded oracle HTTP client (merge first): rainlanguage/raindex#2825
- Raindex batched oracle context preparation (merge second): rainlanguage/raindex#2826

## Motivation

The REST application's order-quote passes can require many oracle contexts at once. Issuing one HTTP request per context adds avoidable connection and request overhead even when the contexts share the same oracle endpoint.

## Solution

- Bump `lib/rain.orderbook` from `0fa60a6` to `4ae9e1a02`.
- Send one ABI batch request per exact oracle URL and scatter the returned contexts back to their quote pairs.
- Preserve bounded concurrency across distinct oracle endpoints with a limit of 8.
- Remove the previous per-context concurrent HTTP request path while leaving chain quote batching unchanged.

## Verification

- `nix develop -c cargo check`
- Upstream quote crate test suite — 63 passed
- Upstream strict Clippy checks
- Repository pre-commit hooks
- `git diff --check`
- Live local REST API validation against Base:
  - `/v2/swap/quote` returned HTTP 200 and `fullyFilled: true` for wtCOIN, wtNVDA, and wtMSTR.
  - Batch telemetry reduced 55 oracle contexts to 2 HTTP requests; 54 contexts succeeded and one legacy oracle endpoint returned HTTP 404.
  - A request-scoped quote recorded one oracle context in one batch request and completed successfully.
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.

3 participants