Skip to content

fix(webapp): stop double-fetching custom registries in advanced mode#2721

Open
thedavidmeister wants to merge 8 commits into
mainfrom
2026-06-13-issue-2046
Open

fix(webapp): stop double-fetching custom registries in advanced mode#2721
thedavidmeister wants to merge 8 commits into
mainfrom
2026-06-13-issue-2046

Conversation

@thedavidmeister

@thedavidmeister thedavidmeister commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Fixes #2046

Problem

In advanced mode, loading a custom registry fetched the rain documents from GitHub twice, which triggers GitHub's rate limiter ("Too many requests for fetching rain documents from github").

loadRegistryUrl() (packages/ui-components/src/lib/services/loadRegistryUrl.ts) called DotrainRegistry.validate(url) — which fetches the registry file plus all its referenced settings files — before persisting the URL and reloading. After the reload, +layout.ts calls DotrainRegistry.new(url), which fetches and validates the same files all over again. So every custom-registry load downloaded everything twice.

Fix

Remove the redundant validate() call from loadRegistryUrl(). It now just persists the URL via registryManager.setRegistry(url) and reloads. Validation is owned by page-load: +layout.ts already turns a DotrainRegistry.new() failure into an errorMessage rendered on the error page, so an invalid registry URL is still reported to the user — just after the reload instead of before — with no duplicate fetch.

Tests

Rewrote loadRegistryUrl.test.ts with discriminating assertions:

  • Regression guard: asserts loadRegistryUrl calls neither DotrainRegistry.validate nor DotrainRegistry.new — it performs no registry fetch of its own. Re-introducing a fetch (the bug) fails this.
  • Ordering: asserts setRegistry runs before reload.
  • Error path: asserts it rethrows when setRegistry throws and does not reload, and maps a non-Error throw to the default message.

Verified the old (validate-based) implementation fails these new tests (5/7 fail), confirming they catch the regression.

Verification

  • npx vitest run loadRegistryUrl.test.ts InputRegistryUrl.test.ts → 12/12 pass
  • webapp +layout.ts test (the page-load validation path this fix relies on) → 4/4 pass
  • npm run lint (ui-components) → clean
  • npm run check (ui-components, svelte-check) → 0 errors, 0 warnings
  • npm run build -w @rainlanguage/ui-components → success

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Refactor
    • Updated registry URL loading mechanism and test coverage to ensure proper error handling and page reload sequencing.

loadRegistryUrl() called DotrainRegistry.validate(url) to validate a custom
registry before persisting it and reloading the page. The post-reload
+layout.ts then calls DotrainRegistry.new(url), which fetches and validates the
exact same registry file plus all its settings files from GitHub again. Every
custom-registry load therefore downloaded the rain documents twice, which
trips GitHub's rate limiter ("Too many requests").

Remove the redundant validate() call from loadRegistryUrl(); it now just
persists the URL and reloads. Validation is owned by page-load: +layout.ts
already surfaces a DotrainRegistry.new() failure as an errorMessage on the
error page, so an invalid registry URL is still reported to the user, just
after the reload instead of before, without the duplicate fetch.

Tests: rewrite loadRegistryUrl.test.ts to assert the function calls neither
DotrainRegistry.validate nor DotrainRegistry.new (the regression guard), that
it persists then reloads in that order, and that it never reloads when
setRegistry throws. Confirmed the old (validate) implementation fails these.

Fixes #2046

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@thedavidmeister thedavidmeister self-assigned this Jun 13, 2026
@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@thedavidmeister, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 56 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 86db2ba2-0cfd-488d-b8ad-4fbbe8e1d237

📥 Commits

Reviewing files that changed from the base of the PR and between 0455250 and 1b9c9be.

📒 Files selected for processing (4)
  • packages/webapp/src/lib/__mocks__/stores.ts
  • packages/webapp/src/routes/+layout.svelte
  • packages/webapp/src/routes/+layout.ts
  • packages/webapp/src/routes/layout.test.ts
📝 Walkthrough

Walkthrough

loadRegistryUrl drops its DotrainRegistry.validate(url) call and import, reducing the function to only persisting the registry URL via registryManager.setRegistry(url) and calling window.location.reload(). Tests are rewritten to assert this new contract and verify that DotrainRegistry.validate and DotrainRegistry.new are never invoked by loadRegistryUrl.

Changes

loadRegistryUrl simplification

Layer / File(s) Summary
Remove DotrainRegistry.validate, persist-and-reload only
packages/ui-components/src/lib/services/loadRegistryUrl.ts
DotrainRegistry import removed; validate(url) call dropped; inline comments note that validation occurs on the subsequent reload via DotrainRegistry.new(url); error handling unchanged.
Updated tests for persist-and-reload contract
packages/ui-components/src/__tests__/loadRegistryUrl.test.ts
Mock extended with DotrainRegistry.new; prior validate-invocation tests replaced with five new tests covering: setRegistry+reload called, no validate/new called, reload-after-setRegistry ordering, Error rejection without reload, and non-Error rejection with default message.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Hop hop, no more fetching before the leap,
Just save the URL and let the page sleep.
On reload the registry wakes anew,
No extra requests — the rabbit count stays true!
Fewer hops to GitHub, fewer bunnies in distress. 🌿

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the primary fix: eliminating double-fetching of custom registries in advanced mode.
Linked Issues check ✅ Passed The PR directly addresses issue #2046 by removing the redundant DotrainRegistry.validate() call that was causing duplicate fetches and GitHub rate-limiting errors.
Out of Scope Changes check ✅ Passed All changes are scoped to loadRegistryUrl functionality and its tests, directly aligned with fixing the double-fetch issue reported in #2046.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 2026-06-13-issue-2046

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.

thedavidmeister and others added 6 commits June 15, 2026 18:06
… comments

Rewrite the comments added in this PR so they describe current behavior only:
loadRegistryUrl persists the URL and reloads, and fetching/validation is owned
by the post-reload +layout.ts via DotrainRegistry.new. No code/logic change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…he app

When DotrainRegistry.new fails for a custom registry (from the ?registry=
param or localStorage), +layout.ts clears the persisted custom registry and
retries the default registry so the app still mounts, surfacing a non-fatal
warning banner. A failing default registry remains a fatal ErrorPage.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@thedavidmeister

Copy link
Copy Markdown
Contributor Author

screenshot pending (manual): headless chromium requires a 375MB nix download; the changed markup is a warning toast in layout.svelte that appears at the bottom when registryWarning is set.

@thedavidmeister

Copy link
Copy Markdown
Contributor Author

Screenshot (static harness render — text not visible due to headless font rendering, but yellow toast element is confirmed positioned at bottom-center):

Registry warning toast — yellow element at bottom center

The registryWarning toast (data-testid="registry-warning") renders as a yellow pill (bg-yellow-500) pinned fixed bottom-4 left-1/2 -translate-x-1/2 in +layout.svelte. Font rendering failed in headless mode but the element positioning and color are correct.

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.

Too many requests for fetching rain documents from github.

1 participant