Skip to content

fix: load folder counts and access lazily to avoid rate limits - #245

Merged
SharonStrats merged 1 commit into
SolidOS:stagingfrom
jeswr:fix/lazy-folder-details
Oct 24, 2026
Merged

SharonStrats merged 1 commit into
SolidOS:stagingfrom
jeswr:fix/lazy-folder-details

Conversation

@jeswr

@jeswr jeswr commented Oct 24, 2026

Copy link
Copy Markdown

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 createRequestQueue in src/requestQueue.ts (unit tested), used by FolderPaneContainer for member-count loads and fetchMetadata calls. 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:

429s counts shown max in flight
staging 71 0 / 60 49
this PR (16 folders on screen) 0 16, rest load on scroll 4
this PR (all 60 on screen) 2, retried 60 / 60 4

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@jeswr jeswr self-assigned this Oct 24, 2026
@bourgeoa
bourgeoa requested review from SharonStrats and timea-solid and removed request for SharonStrats October 24, 2026 13:10

@SharonStrats SharonStrats 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.

Thank you!

@SharonStrats
SharonStrats marked this pull request as ready for review October 24, 2026 20:24
Copilot AI balanced review requested due to automatic review settings October 24, 2026 20:24
@SharonStrats
SharonStrats merged commit c53cf4f into SolidOS:staging Oct 24, 2026
8 checks passed

Copilot AI 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.

🟡 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 thread src/requestQueue.ts
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 thread src/requestQueue.ts
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()
})
}
@bourgeoa

Copy link
Copy Markdown
Contributor

@SharonStrats
I think this did not really solved the issue and ended breaking https://solidcommunity.net with 999 error.
Which is worse than 429

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.

4 participants