fix(scheduler): support safe multi-instance scheduler recovery - #4713
Open
rain02333z-spec wants to merge 3 commits into
Open
fix(scheduler): support safe multi-instance scheduler recovery#4713rain02333z-spec wants to merge 3 commits into
rain02333z-spec wants to merge 3 commits into
Conversation
rain02333z-spec
marked this pull request as ready for review
August 6, 2026 10:41
rain02333z-spec
force-pushed
the
fix/scheduler-multi-worker-startup-gate
branch
from
August 6, 2026 10:46
0a60510 to
4cc3365
Compare
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.
Fixes #4694
Why
Every Gateway process starts
ScheduledTaskService. During startup, the scheduler treated everyqueuedorrunningscheduled-task run in the shared database as a local leftover. In a multi-Pod deployment, a newly started Pod could therefore interrupt a live run owned by another Pod, releaseuq_scheduled_task_run_active, and allow the next scheduler tick to launch a duplicate execution.This is especially harmful for
overlap_policy=skip: a peer restart can defeat the single-active-run guarantee even though the original run is still executing.What changed
scheduler.multi_instance: false.scheduler.multi_instance: true.run_ownership.heartbeat_enabled: true, andrun_events.backend: db.pending/runningrun lease and reclaim only terminated/recovered runs or expired leases through an atomicclaim_for_takeover()update.last_run_idvalues are ignored.scheduled_tasks.lease_owner/lease_expires_atdispatch lease. Multi-instance manual triggers acquire the same short lease before creating a scheduled run row.update_after_launch()fences stale Pods by expected lease owner, so delayed writes cannot overwrite a newer Pod's status or lease.max_concurrent_runsa shared global cap.FOR UPDATE SKIP LOCKEDclaims, the scheduled-run partial unique index, and run ownership leases remain the concurrency primitives; no leader-election service is introduced.Surface area
Screenshots / Recording
Not applicable; this change has no frontend UI.
Bug fix verification
backend/tests/test_scheduled_task_repository.py: live-peer preservation, expired-run takeover, queued dispatch lease, once-task recovery, metadata fallback, stale owner fencing, and global reservation accountingbackend/tests/test_scheduled_task_service.py::test_both_post_launch_association_writes_can_fail_without_releasing_slotbackend/tests/test_multi_worker_postgres_gate.py: single-instance gate plus unsafe multi-instance prerequisitesbackend/tests/test_scheduled_task_postgres.py: cross-Pod advisory-lock budget claim and Postgres metadata/takeover integration casesmainand green on this branch? Not rerun againstmainin this checkout. The branch-focused regression suite passes; the original startup-gate regression was verified red before the gate change.Validation
cd backend && uv run pytest --basetemp .pytest-tmp-final3 tests/test_multi_worker_postgres_gate.py tests/test_scheduled_task_service.py tests/test_scheduled_task_repository.py tests/test_scheduled_task_dispatch_race.py tests/test_scheduled_task_postgres.py -q- 72 passed, 2 skippedcd backend && uv run pytest --basetemp .pytest-tmp-final3 tests/test_reload_boundary.py -q- 10 passedcd backend && uv run ruff check .- passedcd backend && uv run ruff format --check .- 1094 files already formattedgit diff --check- passedTEST_POSTGRES_URIis unset; CI must provide that variable before treating the Postgres cases as executed.91 passed, 2 skipped, 1 failed; the sole failure is the existing Windows inability to executescripts/config-upgrade.shthroughbash(exit 127), unrelated to scheduler behavior.AI assistance
Tool(s) used: Codex
How you used it: Codex analyzed the startup recovery path for Issue #4694, implemented the lease-aware multi-instance scheduler fix, added regression tests and documentation, ran the focused and static validation suites, and updated this PR with the verified results.