Skip to content

Use registry-provided token list URL instead of hardcoded constant#59

Open
findolor wants to merge 3 commits intomainfrom
use-registry-token-url
Open

Use registry-provided token list URL instead of hardcoded constant#59
findolor wants to merge 3 commits intomainfrom
use-registry-token-url

Conversation

@findolor
Copy link
Collaborator

@findolor findolor commented Mar 4, 2026

Dependent PRs

Motivation

The token list URL was hardcoded as a constant in src/routes/tokens.rs, pointing to a specific GitHub raw file commit. This made it impossible to change the token list source without redeploying the API. Now that RaindexClient exposes get_remote_tokens() (PR #2490), the URL can be read from the registry YAML's using-tokens-from field, making it configurable via the registry.

Solution

  • Updated rain.orderbook submodule to 4df6e7dfb to pick up the get_remote_tokens() API
  • Added get_remote_token_urls() to RaindexProvider which delegates to the submodule's RaindexClient::get_remote_tokens() to extract URLs from the registry YAML
  • Rewrote the get_tokens handler to resolve the token list URL from SharedRaindexProvider at request time instead of using a hardcoded constant
  • Removed TOKEN_LIST_URL constant, TokensConfig struct, its fairing, and the fairing attachment in main.rs
  • Updated test helpers: removed token_list_url builder method and mock_token_list_url(); mock_raindex_registry_url() now accepts an optional token URL to embed as using-tokens-from in the mock registry YAML, so tests exercise the full registry-based resolution path

Checks

By submitting this for review, I'm confirming I've done the following:

  • made this PR as small as possible
  • unit-tested any new functionality
  • linked any relevant issues or PRs
  • included screenshots (if this involves a front-end change)

Summary by CodeRabbit

  • Bug Fixes

    • Enhanced error handling for missing token list URL configuration.
  • Chores

    • Simplified server initialization by removing unnecessary middleware components.
    • Updated internal token URL retrieval mechanism.

findolor added 3 commits March 4, 2026 10:37
Pick up the commit that exposes `get_remote_tokens()` from
`RaindexClient`, which parses the `using-tokens-from` field
in the registry YAML.
Replace the hardcoded TOKEN_LIST_URL and TokensConfig fairing with
a dynamic lookup via RaindexProvider.get_remote_token_urls(), which
reads the using-tokens-from field from the registry YAML.

The handler now takes SharedRaindexProvider as a Rocket state
parameter, resolves the first configured URL at request time, and
fetches the token list with a fresh reqwest client.
Remove token_list_url from TestClientBuilder and mock_token_list_url().
Instead, mock_raindex_registry_url() now accepts an optional token URL
and embeds it as using-tokens-from in the mock registry YAML, so tests
exercise the full registry-based URL resolution path.
@findolor findolor self-assigned this Mar 4, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 4, 2026

📝 Walkthrough

Walkthrough

The changes refactor token URL retrieval from a configuration-based approach (TokensConfig fairing) to a registry-backed approach using SharedRaindexProvider. This includes removing the tokens fairing from Rocket initialization, adding a new method to fetch remote token URLs, and updating token routes and test infrastructure accordingly.

Changes

Cohort / File(s) Summary
Submodule Update
lib/rain.orderbook
Updated submodule pointer from 0aab416... to 4df6e7d...; no behavioral changes.
Rocket Initialization
src/main.rs
Removed tokens fairing attachment from server initialization sequence.
Raindex Provider
src/raindex/config.rs
Added get_remote_token_urls method to initialize raindex client, fetch remote tokens, and return URLs as Vec\<String\>, with ClientInit error mapping.
Token Routes Refactoring
src/routes/tokens.rs
Removed TokensConfig struct, fairing, and default initialization; switched from local config-based URL to SharedRaindexProvider registry lookup; added NoTokenListUrl error variant; updated get_tokens signature and control flow to fetch URL dynamically.
Test Infrastructure
src/routes/admin.rs, src/test_helpers.rs
Removed token_list_url field and TokensConfig wiring from TestClientBuilder; renamed builder method to raindex_registry_url; parameterized mock_raindex_registry_url to optionally include token-list URL; updated test calls with explicit None argument.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Handler as GET /tokens Handler
    participant Provider as SharedRaindexProvider
    participant Registry as Raindex Registry Client
    participant Remote as Remote Token Service

    Client->>Handler: GET /tokens
    Handler->>Provider: get_remote_token_urls()
    Provider->>Registry: initialize client from registry
    Registry-->>Provider: client ready
    Provider->>Registry: get_remote_tokens()
    Registry-->>Provider: token configs with urls
    Provider->>Provider: extract & collect URLs
    Provider-->>Handler: Vec<String> (urls)
    Handler->>Handler: select first URL or error
    Handler->>Remote: HTTP GET token list
    Remote-->>Handler: token list JSON
    Handler->>Handler: deserialize & respond
    Handler-->>Client: 200 OK with tokens
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • 0xgleb
  • hardyjosh

Poem

🐰 No more hardcoded tokens in the air,
Registry lookup answers our prayer!
Fairings removed, the flow shines so bright,
Dynamic and nimble—configuration done right! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 47.83% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: moving from a hardcoded token list URL constant to a registry-provided one, which is the primary objective across all file modifications.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch use-registry-token-url

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.

@findolor findolor requested a review from hardyjosh March 4, 2026 07:41
Copy link

@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 (2)
src/routes/tokens.rs (1)

130-136: Add a regression test for the missing-token-URL path.

The new NoTokenListUrl branch is introduced but not covered in this test module. Add one test that uses mock_raindex_registry_url(None) and asserts the expected API error contract.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/routes/tokens.rs` around lines 130 - 136, Add a regression test to cover
the NoTokenListUrl branch by creating a client with
mock_raindex_registry_url(None) instead of Some(token_url): write a new async
test (in the same module) that calls build_client_with_token_url-equivalent
setup but passes None to mock_raindex_registry_url, uses
TestClientBuilder::new().raindex_registry_url(registry_url).build().await to
obtain the client, invokes the relevant endpoint (same API route exercised by
other tests in this file), and asserts the API returns the expected error
contract for missing token URL (status code and JSON error shape) to verify the
NoTokenListUrl path is exercised.
src/test_helpers.rs (1)

87-89: Quote the injected token URL in YAML for robustness.

Unquoted URLs can become fragile with special characters (for example #), so quoting reduces parser edge cases in tests.

🧪 Optional hardening diff
-        Some(url) => format!("\nusing-tokens-from:\n  - {url}\n"),
+        Some(url) => format!("\nusing-tokens-from:\n  - \"{url}\"\n"),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/test_helpers.rs` around lines 87 - 89, The YAML fragment built in the
match for token_list_url (the using_tokens variable) must quote the injected URL
to avoid parser issues with characters like #; change the Some(url) branch to
wrap the URL in double quotes (e.g. " {url} ") and escape any embedded quotes in
url (url.replace("\"", "\\\"")) before formatting so the produced YAML is robust
against special characters.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/routes/tokens.rs`:
- Around line 52-55: The registry URL resolution using
shared_raindex.read().await and raindex.get_remote_token_urls() which can return
TokenError::NoTokenListUrl must be moved inside the instrumented/request-scoped
block that logs "request received" so tracing always records the request before
any fallible operations; locate the code referencing shared_raindex and
get_remote_token_urls() in tokens.rs and move it into the block where the
request is instrumented/logged (the area around the "request received" tracing
call), ensure you drop the read guard after use, and keep error handling
(TokenError::NoTokenListUrl) unchanged but after the initial log so
request-level tracing is always emitted.

---

Nitpick comments:
In `@src/routes/tokens.rs`:
- Around line 130-136: Add a regression test to cover the NoTokenListUrl branch
by creating a client with mock_raindex_registry_url(None) instead of
Some(token_url): write a new async test (in the same module) that calls
build_client_with_token_url-equivalent setup but passes None to
mock_raindex_registry_url, uses
TestClientBuilder::new().raindex_registry_url(registry_url).build().await to
obtain the client, invokes the relevant endpoint (same API route exercised by
other tests in this file), and asserts the API returns the expected error
contract for missing token URL (status code and JSON error shape) to verify the
NoTokenListUrl path is exercised.

In `@src/test_helpers.rs`:
- Around line 87-89: The YAML fragment built in the match for token_list_url
(the using_tokens variable) must quote the injected URL to avoid parser issues
with characters like #; change the Some(url) branch to wrap the URL in double
quotes (e.g. " {url} ") and escape any embedded quotes in url (url.replace("\"",
"\\\"")) before formatting so the produced YAML is robust against special
characters.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c51c3557-f21c-4cbb-8c2a-26fa927cca62

📥 Commits

Reviewing files that changed from the base of the PR and between e6e8108 and 1759178.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • lib/rain.orderbook
  • src/main.rs
  • src/raindex/config.rs
  • src/routes/admin.rs
  • src/routes/tokens.rs
  • src/test_helpers.rs
💤 Files with no reviewable changes (1)
  • src/main.rs

Comment on lines +52 to +55
let raindex = shared_raindex.read().await;
let urls = raindex.get_remote_token_urls()?;
let url = urls.first().ok_or(TokenError::NoTokenListUrl)?.to_string();
drop(raindex);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Ensure request logging happens before fallible registry URL resolution.

Line [52]-Line [55] can fail before the "request received" log at Line [58], so some requests may return without required request-level tracing. Move URL resolution inside the instrumented block after initial request logging.

🔧 Proposed fix
 pub async fn get_tokens(
     _global: GlobalRateLimit,
     _key: AuthenticatedKey,
     span: TracingSpan,
     shared_raindex: &State<SharedRaindexProvider>,
 ) -> Result<Json<TokenListResponse>, ApiError> {
-    let raindex = shared_raindex.read().await;
-    let urls = raindex.get_remote_token_urls()?;
-    let url = urls.first().ok_or(TokenError::NoTokenListUrl)?.to_string();
-    drop(raindex);
-
     async move {
         tracing::info!("request received");
+        let url = {
+            let raindex = shared_raindex.read().await;
+            let urls = raindex.get_remote_token_urls()?;
+            urls.first().cloned().ok_or_else(|| {
+                tracing::warn!("no token list URL configured in registry");
+                TokenError::NoTokenListUrl
+            })?
+        };
 
         tracing::info!(url = %url, timeout_secs = TOKEN_LIST_TIMEOUT_SECS, "fetching token list");
As per coding guidelines, “Every route handler must log appropriately using tracing (request received, errors, key decisions)”.

Also applies to: 57-60

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/routes/tokens.rs` around lines 52 - 55, The registry URL resolution using
shared_raindex.read().await and raindex.get_remote_token_urls() which can return
TokenError::NoTokenListUrl must be moved inside the instrumented/request-scoped
block that logs "request received" so tracing always records the request before
any fallible operations; locate the code referencing shared_raindex and
get_remote_token_urls() in tokens.rs and move it into the block where the
request is instrumented/logged (the area around the "request received" tracing
call), ensure you drop the read guard after use, and keep error handling
(TokenError::NoTokenListUrl) unchanged but after the initial log so
request-level tracing is always emitted.

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.

1 participant