Repository navigation
fix: load folder counts and access lazily to avoid rate limits - #245
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bourgeoa
requested review from
SharonStrats and
timea-solid
and removed request for
SharonStrats
October 24, 2026 13:10
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved backoff and lifecycle issues can resume requests prematurely or leave counts and access indicators missing.
4 open issues
What changed in this PR
This PR reduces request bursts in the folder pane by loading member counts and access indicators near the viewport through a shared request queue.
Changes:
- Adds bounded concurrency, 429 retries, and queue clearing.
- Integrates lazy detail loading with folder refresh and component lifecycle handling.
- Adds unit tests for queue behavior and rate-limit detection.
| File | Description |
|---|---|
test/requestQueue.test.js |
Tests concurrency, retries, clearing, and Retry-After parsing. |
src/requestQueue.ts |
Implements the advisory-request queue and backoff helpers. |
src/components/folder-pane-container/FolderPaneContainer.ts |
Queues detail requests and observes visible resource items. |
Review effort: Balanced
| } | ||
|
|
||
| private async loadMemberCount (resource: Resource, generation = this.resourceGeneration) { | ||
| if (!resource.isContainer || this.memberLoad.has(resource.id) || !this.browserContext) return |
| } | ||
|
|
||
| private observeResourceItems () { | ||
| const items = Array.from(this.renderRoot.querySelectorAll<HTMLElement>('[data-resource-id]')) |
Comment on lines
+92
to
+99
| if (taskGeneration === generation && isRateLimitedError(error) && item.retries < maxRetries) { | ||
| item.retries++ | ||
| // Retry first so it is not overtaken by tasks queued after it. | ||
| pending.unshift(item) | ||
| pause(getRetryAfterMs(error, defaultRetryAfterMs)) | ||
| } else { | ||
| item.reject(error) | ||
| } |
Comment on lines
+106
to
+114
| function pause (ms: number) { | ||
| if (pausedUntil) return | ||
| const pauseGeneration = generation | ||
| pausedUntil = wait(ms).then(() => { | ||
| if (pauseGeneration !== generation) return | ||
| pausedUntil = undefined | ||
| pump() | ||
| }) | ||
| } |
Contributor
|
@SharonStrats |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Requested by Jesse
Before: opening a folder sent a GET to every child container (for the item count) and a HEAD to every child (for the public/private indicator), all at once. With CORS preflights that is about four requests per child, so on pods with many folders solidcommunity.net's per-IP rate limit (Cloudflare, 50 requests / 10 s) answers 429 and no counts appear. Reported by @bourgeoa in the SolidOS channel.
After: counts and access indicators load only for items in or near the viewport (IntersectionObserver), at most four requests at a time. On a 429 the queue pauses for
Retry-After(10 s if absent) and retries. Pending requests are dropped when the folder changes or the view disconnects.How: a small
createRequestQueueinsrc/requestQueue.ts(unit tested), used byFolderPaneContainerfor member-count loads andfetchMetadatacalls. Without IntersectionObserver it falls back to loading all items through the queue.Checked in the pane sandbox against a stubbed pod with 60 folders behind a 50 req / 10 s limit:
staging🤖 Generated with Claude Code