Skip to content

Fixed the 429 error on Ranobes for Novels Fetching - #2387

Closed
D3ICIDE wants to merge 10 commits into
lnreader:masterfrom
D3ICIDE:master
Closed

Fixed the 429 error on Ranobes for Novels Fetching#2387
D3ICIDE wants to merge 10 commits into
lnreader:masterfrom
D3ICIDE:master

Conversation

@D3ICIDE

@D3ICIDE D3ICIDE commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

For #2345, implementing continuous pages leads to long delays for novels with large amount of chapters like 1000 since each page only has 25 chapters it would need 40 requests. And that still causes 429 so someone else needs to look at the site to see if that is possible. Not closing this issue.

Checklist

  • Update version code if an existing plugin was modified
  • Test changes in Plugin Playground or the app
  • Reference related issues in the PR body (e.g. Closes #xyz)

Copilot AI lite review requested due to automatic review settings August 5, 2026 18:26

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the Ranobes multi-source plugin to reduce HTTP 429 (“Too Many Requests”) errors during novel/page fetching by adding request throttling and basic retry handling, in the context of #2345’s discussion about high chapter counts causing many requests.

Changes:

  • Bumped the Ranobes plugin version to 2.0.3.
  • Added a global request throttle/queue and retry-on-429 logic (with Retry-After support).
  • Introduced an additional delay in popularNovels() prior to fetching.
Suppressed comments (2)

plugins/multisrc/ranobes/template.ts:56

  • Retry-After can be either seconds or an HTTP-date, and parseInt() can also yield NaN (e.g. non-numeric header). As written, waitMs may become NaN (causing an immediate retry loop) or an arbitrary number from a date string (e.g. "Wed, 21 Oct..." -> 21s). Parse both formats safely and fall back to a default delay.
      const retryAfter = r.headers.get('Retry-After');
      const waitMs = retryAfter ? parseInt(retryAfter, 10) * 1000 : 3000;
      await new Promise(res => setTimeout(res, waitMs));
      return this.safeFecth(url, init, retries - 1);

plugins/multisrc/ranobes/template.ts:201

  • popularNovels() adds an additional 1s delay even though safeFecth() is already throttled. This compounds latency (especially when paging) without improving rate limiting consistency (other endpoints don't do this). Prefer relying on the shared throttling logic so delays are centralized and predictable.
  async popularNovels(page: number): Promise<Plugin.NovelItem[]> {
    await new Promise(res => setTimeout(res, 1000));
    const link = `${this.site}/${this.options.path}/page/${page}/`;

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread plugins/multisrc/ranobes/template.ts

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.

Comment thread plugins/multisrc/ranobes/template.ts Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

Suppressed comments (2)

plugins/multisrc/ranobes/template.ts:36

  • In throttle(), release is typed as () => void but is assigned directly from the Promise resolver (res), which has a different call signature. This can cause a TypeScript type error. Also consider tracking a shared cooldown (e.g., from 429 Retry-After) so all subsequent requests are throttled consistently, not just by a fixed MIN_DELAY_MS.
  private static requestQueue: Promise<void> = Promise.resolve();
  private static lastRequestTime = 0;
  private static readonly MIN_DELAY_MS = 1200;

plugins/multisrc/ranobes/template.ts:82

  • The 429 handler waits locally and then retries, but it doesn't communicate the server-provided Retry-After delay to other concurrent callers. Setting a shared cooldown timestamp lets throttle() apply the cooldown globally so other requests don’t continue hammering the site while one call is backing off.
      await new Promise(res => setTimeout(res, waitMs));
      return this.safeFecth(url, init, retries - 1);
    }

@D3ICIDE D3ICIDE closed this Aug 6, 2026
@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Aug 9, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants