Skip to content

feat: add ModelScope provider-specific 429 handling and retry logic - #2202

Merged
diegosouzapw merged 5 commits into
cheaper-inference:release/v3.8.0from
InkshadeWoods:main
May 12, 2026
Merged

diegosouzapw merged 5 commits into
cheaper-inference:release/v3.8.0from
InkshadeWoods:main

Conversation

@InkshadeWoods

Copy link
Copy Markdown
Contributor

Description
Add ModelScope (魔搭) provider-specific 429 error handling and retry logic to improve reliability when using ModelScope-hosted models.

Changes:

  • Add modelscopePolicy.ts: centralized ModelScope rate limit parsing and 429 classification
  • Support dual provider detection: provider ID and baseURL domain matching
  • Implement per-model lock on quota exhaustion (not connection-wide)
  • Add automatic retry with backoff for rate-limited requests (max 3 attempts)
  • Parse Modelscope-Ratelimit-* headers for accurate quota tracking
  • Fix Docker build: add build tools for native module compilation
  • Fix .dockerignore: allow docs/openapi.yaml for container build

Summary

When using ModelScope as a provider, 429 rate limit errors are now automatically detected and retried (up to 3 attempts) instead of immediately failing. The system correctly distinguishes between rate limiting (retryable) and quota exhaustion (not retryable) using ModelScope's response headers.

Related Issues

  • Closes #
  • Related to #

Validation

  • npm run lint
  • npm run test:unit
  • npm run test:coverage
  • Coverage is still >= 60% for statements, lines, functions, and branches
  • SonarQube PR analysis is green or any remaining issues are explicitly documented below

Tests Added Or Updated

No new tests added. The changes are isolated to ModelScope-specific 429 handling logic in existing files (open-sse/handlers/chatCore.ts and open-sse/services/modelscopePolicy.ts). The functionality was manually tested with a live ModelScope provider (DeepSeek-V4-Flash) and verified working.

Coverage Notes

Changes are in open-sse/handlers/chatCore.ts and open-sse/services/modelscopePolicy.ts. These files handle request routing and error classification. Existing tests for chatCore.ts should cover the new ModelScope branch.

Reviewer Notes

The ModelScope-specific logic is isolated in modelscopePolicy.ts and only activates when the provider is identified as ModelScope. No breaking changes to existing functionality. Docker build fixes are included to ensure the project builds successfully in containerized environments.

diegosouzapw and others added 3 commits May 10, 2026 23:36
* "Claude PR Assistant workflow"

* "Claude Code Review workflow"
Bumps [mermaid](https://github.com/mermaid-js/mermaid) from 11.14.0 to 11.15.0.
- [Release notes](https://github.com/mermaid-js/mermaid/releases)
- [Commits](https://github.com/mermaid-js/mermaid/compare/mermaid@11.14.0...mermaid@11.15.0)

---
updated-dependencies:
- dependency-name: mermaid
  dependency-version: 11.15.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
- Add modelscopePolicy.ts: centralized ModelScope rate limit parsing and 429 classification
- Support dual provider detection: provider ID and baseURL domain matching
- Implement per-model lock on quota exhaustion (not connection-wide)
- Add automatic retry with backoff for rate-limited requests (max 3 attempts)
- Parse Modelscope-Ratelimit-* headers for accurate quota tracking
- Fix Docker build: add build tools for native module compilation
- Fix .dockerignore: allow docs/openapi.yaml for container build

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request introduces specialized handling for the ModelScope provider, including a new policy service to classify 429 errors and manage retries. It also updates the Docker build environment with necessary dependencies and integrates ModelScope-specific rate-limiting and locking logic into the chat handler. Feedback suggests optimizing the reading of 429 response bodies with size limits or timeouts to ensure efficiency and recommends a future refactor to centralize the fragmented model-locking logic.

Comment on lines +2866 to +2869
const bodyPeek = await res.response
.clone()
.text()
.catch(() => "");

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.

medium

Cloning the response and reading the full body as text for every 429 error can be inefficient, especially if the upstream response is large. While 429 bodies are typically small, it's safer to limit the read size or ensure this only happens for ModelScope. Since isModelScope() is already checked, this is acceptable, but consider adding a timeout or size limit to the text() call if possible in this environment.

Comment on lines +3320 to +3324
if (isModelScope() && connectionId) {
lockModel(provider, connectionId, model, "quota_exhausted", quotaCooldownMs);
console.warn(
`[provider] Node ${connectionId} ModelScope model quota exhausted (${statusCode}) for ${model} - ${Math.ceil(quotaCooldownMs / 1000)}s (connection stays active)`
);

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.

medium

The explicit check for isModelScope() here to trigger lockModel bypasses the hasPerModelQuota logic in accountFallback.ts. While necessary because hasPerModelQuota lacks access to credentials for URL-based detection, this creates a slight fragmentation of model-locking logic. Consider if hasPerModelQuota could be updated to accept providerSpecificData in a future refactor to centralize this policy.

@diegosouzapw
diegosouzapw changed the base branch from main to release/v3.8.0 May 12, 2026 19:38
# Conflicts:
#	.github/workflows/claude-code-review.yml
#	.github/workflows/claude.yml
@diegosouzapw

Copy link
Copy Markdown
Collaborator

Thanks @InkshadeWoods. I synced this branch with release/v3.8.0, removed unrelated workflow/docker/package-lock changes, tightened the ModelScope 429 classifier so temporary rate-limit headers remain retryable, added policy coverage, and validated locally with:\n\n- node --import tsx/esm --test tests/unit/modelscope-policy.test.ts\n- targeted npx eslint on the changed TS files\n- npm run typecheck:core\n\nI'll merge this through GitHub so the contribution is credited correctly.

@diegosouzapw
diegosouzapw merged commit e6aee3d into cheaper-inference:release/v3.8.0 May 12, 2026
3 checks passed
HouMinXi pushed a commit to HouMinXi/OmniRoute that referenced this pull request Aug 2, 2026
…heaper-inference#2202)

Integrated into release/v3.8.0 after syncing the contributor branch, removing unrelated workflow/docker/package-lock changes, tightening ModelScope 429 classification, and validating policy coverage locally.
Poid-ZA pushed a commit to Poid-ZA/OmniRoute that referenced this pull request Aug 5, 2026
…heaper-inference#2202)

Integrated into release/v3.8.0 after syncing the contributor branch, removing unrelated workflow/docker/package-lock changes, tightening ModelScope 429 classification, and validating policy coverage locally.
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…heaper-inference#2202)

Integrated into release/v3.8.0 after syncing the contributor branch, removing unrelated workflow/docker/package-lock changes, tightening ModelScope 429 classification, and validating policy coverage locally.
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.

3 participants