Skip to content

feat(scheduler): add group priority and tiered retry fallback - #825

Merged
tbphp merged 3 commits into
mainfrom
tbphp/group-priority-scheduling
Oct 5, 2026
Merged

tbphp merged 3 commits into
mainfrom
tbphp/group-priority-scheduling

Conversation

@tbphp

@tbphp tbphp commented Oct 5, 2026

Copy link
Copy Markdown
Owner

关联 Issue / Related Issue

Closes #613

变更内容 / Change Content

  • Bug 修复 / Bug fix
  • 新功能 / New feature
  • 其他改动 / Other changes

Add signed group priority to support preferred and backup upstreams. Higher values run first; the default of 0 preserves existing scheduling when all groups share a tier.

  • Select priority before native/converted preference, affinity and weighted rotation. Retryable failures move to the next available lower tier; the lowest tier continues with untried credentials. Preserve the shared retry budget, credential deduplication, OAuth refresh replay and bound sessions.
  • Recalibrate all credentials when an existing group's priority changes, with revision checks preventing stale requests from clearing pending admission. Keep the checkpoint format unchanged.
  • Expose priority in both management UIs, group APIs and route inspection. Add migration 0029_group_priority for SQLite, MySQL and PostgreSQL; existing groups receive 0, and default create-request idempotency remains compatible.

The retry policy deliberately skips untried peers in higher tiers to reach backups sooner. Priority edits can change relative scheduling history across all credentials. Local concurrency, RPM and quota rejection rules remain unchanged.

Validation: make check passed, including the complete Go suite, frontend lint, type checks and builds. Added scheduling, retry-budget, affinity/binding, API/idempotency and migration regressions. Real MySQL/PostgreSQL migration validation is covered by the existing CI matrix and remains pending.

The design specification was updated locally under the intentionally ignored docs/ directory. No public documentation or release notes were changed.

自查清单 / Checklist

  • 我已运行 make check,或在说明中写明无法运行的原因和未验证范围。 / I ran make check, or documented why it could not run and what remains unverified.
  • 本 PR 范围聚焦,未包含无关改动。 / This PR is focused and contains no unrelated changes.
  • 我已更新必要的公开文档或发布说明。 / I updated any required public documentation or release notes.
  • 我已确认提交、日志和测试数据不包含敏感信息。 / I confirmed that commits, logs, and fixtures contain no sensitive data.
  • 如适用,我已说明兼容性或数据迁移影响。 / Where applicable, I documented compatibility or data-migration impact.

Add signed group priority with a backward-compatible zero default. Select the
highest eligible tier before route-mode preference, affinity and weighted
rotation, then descend on retry without resetting the shared attempt budget.

Preserve bound sessions and refresh replay, recalibrate priority edits with
revision-safe pending admission, and expose priority in both management UIs.
Add migration 0029 with SQLite and external database contract coverage.

Validation: make check and focused scheduling, retry, affinity, API and
migration regressions passed. Real MySQL/PostgreSQL validation runs in CI.
Copilot AI balanced review requested due to automatic review settings October 5, 2026 06:39

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

📝 Walkthrough

Walkthrough

组新增默认值为 0 的 int32 优先级,并通过数据库迁移、运行时配置和控制接口传递。调度器在最高可用优先级层选择候选,并在可重试失败时推进到较低层。经典版和新版界面新增优先级创建、编辑、校验及展示;路由检查界面也展示优先级层信息。

Priority: ➖ Normal

Merge Risk: 🟡 Moderate · up to 49961

Clearing a group's priority in the classic settings form can silently reset it to zero and change which upstream receives traffic. Fix the input handling before merging.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 49961

Routing changes remain restricted to administrators, and inspected retry paths retain existing access and identity limits. No new security bypass was established. Cross-database upgrade validation and deployment rollback assumptions remain unconfirmed.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — An authorized administrator can change relative routing across configured groups, with recalibration extending across shared credential scheduling state. A data-plane caller can encounter lower-tier destinations through retryable failures, but the inspected path confines selection to eligible credentials. Deployment-wide replica, tenant, and environment exposure cannot be determined from the supplied topology evidence.

Security Findings and Attack Paths

  • observed — The inspected mutation path is authenticated control input to persisted priority and runtime routing policy. Access-key principals cannot invoke the settings PUT route. Retry-induced destination changes retain credential eligibility and identity checks; these inspected paths did not establish a new privilege or authorization bypass.

Trust Boundaries and Controls

  • observed — Bound retries preserve credential ID, group ID, identity generation, and proxy identity rather than treating a higher-priority group as authority to replace the session credential. The new priority policy does not override this identity boundary in the inspected recovery path.

Resilience and Maintainability Implications

  • observed — Configuration writes are serialized locally and validated before transaction commit. Idempotent creation records durable publication stages, retries incomplete stages, and conditionally advances the stored stage after successful work. Priority uses these existing containment and recovery mechanisms; distributed writer coordination is not established.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.26% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 47 functions across 48 files. (11 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 标题清晰概括了主要变更:新增组优先级和分层重试回退。
Description check ✅ Passed 描述包含关联 Issue、变更内容、自查清单、验证结果和迁移影响。公开文档与发布说明的清单项未勾选,但已说明未更新。
Linked Issues check ✅ Passed #613 要求可配置渠道优先级、同优先级沿用权重调度,并在高优先级渠道异常时回退。调度器按优先级选择候选,并通过 AdvancePriority 在可重试失败后转向低优先级;新增测试覆盖分层回退、同档权重和重试预算。持久化、API、管理界面及迁移支持该功能,现有组默认值为 0。Issue 提到较小数值可表示更高优先级,但这是建议用法;本 PR 采用较大数值优先,不改变按用户设置的优先级顺序调度…
Out of Scope Changes check ✅ Passed 变更均服务于 #613:包括调度与重试、优先级存储和迁移、API 与路由检查、管理界面及相应回归测试。未发现与该功能无关的改动。
Full details: Docstring Coverage

Explanation

Docstring coverage is 4.26% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 47 functions across 48 files. (11 skipped: 11 unsupported.)

  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: QUIET
  • Plan: Advanced
  • Run ID: 0ea55332-73bb-4deb-829a-24c1d1a92df0
📥 Commits

Reviewing files that changed from the base of the PR and between d3257cf and 49961f6.

📒 Files selected for processing (59)
  • internal/control/group_collection.go
  • internal/control/group_create.go
  • internal/control/group_idempotency.go
  • internal/control/group_priority_test.go
  • internal/control/group_settings.go
  • internal/control/group_update.go
  • internal/control/modern_groups.go
  • internal/control/route_inspect.go
  • internal/gateway/handler.go
  • internal/gateway/handler_test.go
  • internal/gateway/live.go
  • internal/gateway/mistral_realtime.go
  • internal/gateway/priority_retry_test.go
  • internal/gateway/websocket_priority_test.go
  • internal/gateway/websocket_turn.go
  • internal/scheduler/fair.go
  • internal/scheduler/inspect.go
  • internal/scheduler/priority_test.go
  • internal/scheduler/scheduler.go
  • internal/state/loader/loader.go
  • internal/state/scheduling.go
  • internal/state/snapshot.go
  • internal/storage/database_integration_test.go
  • internal/storage/db_test.go
  • internal/storage/group_priority_migration_test.go
  • internal/storage/migration.go
  • internal/storage/migration_test.go
  • internal/storage/migrations/0003_remove_observation_fresh_until_test.go
  • internal/storage/migrations/0029_group_priority.go
  • internal/storage/models/group.go
  • web/src/frontends/classic/api/control/types.ts
  • web/src/frontends/classic/app/resources/groups.ts
  • web/src/frontends/classic/app/resources/route-inspection.ts
  • web/src/frontends/classic/features/groups/GroupsView.vue
  • web/src/frontends/classic/features/groups/settings/GroupSettingsBaseForm.vue
  • web/src/frontends/classic/features/groups/settings/GroupSettingsTab.vue
  • web/src/frontends/classic/features/groups/settings/group-settings-patch.ts
  • web/src/frontends/classic/features/import/ImportConnectionSection.vue
  • web/src/frontends/classic/features/import/NewGroupImport.vue
  • web/src/frontends/classic/features/import/import-recovery.ts
  • web/src/frontends/classic/features/import/model-draft.ts
  • web/src/frontends/classic/features/monitor/InspectorTab.vue
  • web/src/frontends/classic/i18n/locales/en-US/group.ts
  • web/src/frontends/classic/i18n/locales/en-US/monitor.ts
  • web/src/frontends/classic/i18n/locales/ja-JP/group.ts
  • web/src/frontends/classic/i18n/locales/ja-JP/monitor.ts
  • web/src/frontends/classic/i18n/locales/zh-CN/group.ts
  • web/src/frontends/classic/i18n/locales/zh-CN/monitor.ts
  • web/src/frontends/modern/api/group-create.ts
  • web/src/frontends/modern/api/groups.ts
  • web/src/frontends/modern/api/inspector.ts
  • web/src/frontends/modern/features/groups/GroupBasicsForm.vue
  • web/src/frontends/modern/features/groups/GroupCreatePanel.vue
  • web/src/frontends/modern/features/groups/GroupListRow.vue
  • web/src/frontends/modern/features/groups/GroupsView.vue
  • web/src/frontends/modern/features/inspector/RouteInspector.vue
  • web/src/frontends/modern/features/inspector/inspection-display.ts
  • web/src/frontends/modern/i18n/locales/groups.ts
  • web/src/shared/group-priority.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.

Comment thread web/src/frontends/classic/features/groups/settings/GroupSettingsBaseForm.vue Outdated
@tbphp tbphp self-assigned this Oct 5, 2026
@tbphp tbphp added the enhancement New feature or request label Oct 5, 2026
@tbphp tbphp added this to the v2.0.0 milestone Oct 5, 2026
@tbphp
tbphp merged commit b88b395 into main Oct 5, 2026
12 checks passed
@tbphp
tbphp deleted the tbphp/group-priority-scheduling branch October 5, 2026 10:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

希望在权重控制基础上增加优先级

2 participants