Repository navigation
Outdated runs, and deploys that don't wait for them (#397, #390) - #406
Merged
Merged
Conversation
A run's heartbeat asks whether a newer version leads (its pipeline is registered with other code, or its scheduler drains) and keeps the answer for morca.outdated(), code_version() and desired_code_version(); the run page, its JSON and morca status mark it. Nothing stops it: the drain has no limit unless MORCA_DRAIN_SECONDS is set. With overlap, deploy.sh returns once the new scheduler leads: old schedulers drain as scheduler-old-<time>, each removed by a reaper once it exits, check reports them as information, and the next deploy overlaps beside them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017TycszSbyw92Efu4ZeCYL6
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017TycszSbyw92Efu4ZeCYL6
winding-lines
enabled auto-merge
November 12, 2026 20:16
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017TycszSbyw92Efu4ZeCYL6
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.
First slice of #397 and #390: deploys stop waiting on long runs. A run may last months; a deploy doesn't wait for it and morca never stops it. Morca tells the run it's outdated, the run ignores that by default, and its code decides when to end.
The signal, through the heartbeat (
morca.handover)PgBeat, which already beatsorca.runsand runs the cancel/timeout watchdog) also asks, on the same connection and beat, whether the run is outdated (outdated_sql). A worker's run gets the same answer in the reply to itsbeatstore call (HttpBeat); a UI from before this says nothing, and the run is never outdated. The answer goes into a process-wide atomic (_get_global), somorca.outdated()is a load.orca.pipelines.versionvsorca.runs.version, compared by commit, dirtiness and registry hash) or its scheduler instance drains (draining_since/drain_asked, while it lists the run). No migration: both are in the schema.morca.outdated() -> Bool,morca.code_version(),morca.desired_code_version(),morca.outdated_why(). False/empty until the first beat and for runs without a heartbeat (memory, SQLite).The code version is the
orca.pipeline_versionsrow thatmorca registerand every run already record (morca.source): the commitdescribereports (-D MORCA_COMMIT), its dirtiness and the registry hash; shown as the commit's first 12 characters (+dirty), orcode <hash>without a commit. Not the registry hash alone (orca.code): it covers the DAG, not step bodies, so a fix to a poll loop wouldn't change it. Not the image: a registration's image is the remote-run--image, a run's the one it ran in, so they differ for the same code. Builds without a commit are told apart by registry hash, and during an overlap by the draining condition (which also covers a redeploy of the same code with new settings).Shown
The run page (Status card, "Version":
<code> outdated (newer version X is leading)), its JSON and every running row of the pipeline JSON (code_version,desired_code_version,outdated), andmorca status <pipeline>((outdated: newer version X is leading)). There is nomorca runscommand;morca status <pipeline>is the run list.Deploys don't wait
MORCA_DRAIN_SECONDSunset now means no drain limit (was 3600, which killed runs after an hour).morca-stack apply --overlaprenames the old schedulerscheduler-old-<UTC time>(notscheduler-old), so a deploy while one still drains overlaps again, each old one under its own name; none shadows another.can-overlapno longer says no for a draining old scheduler (the binary's floor check still covers every live instance, draining ones included).morca-stack drain-oldasks every old scheduler to drain and returns, leaving a reaper (morca-stack reap-old NAME, nohup/setsid,$STATE/reap-NAME.log) that removes the container once it exits after its last run.--waitwaits as before;--timeoutwaits and stops.deploy.shcallsdrain-oldwithout waiting; it returns once the new scheduler leads and is registered.morca-stack checkreportsinfo scheduler-old-<time>: draining N run(s) (outdated), not a failure (ascheduler-nextleft behind still fails);statuslists them too.applystill removes exited ones (a legacyscheduler-oldcounts).Not in this slice (follow-ups)
DRAIN_SECONDSin hetzner.env, hard error when missing, deploy.sh checking it).mojo_liveacross versions) and the waiting-run limit.Tests
tests/outdated.sh(new,pixi run test-outdated, intest-scheduler-ui): three real instances on one Postgres. A's two runs (commit aaaa…) aren't outdated; B leads and commit bbbb… is registered: the heartbeat says so, the run that hands over returns and succeeds, the one that ignores it runs on (heartbeat fresh, A still up), shown outdated inmorca status, the pipeline JSON, the run JSON and page, and succeeds once it returns with one start and one attempt, no audit rows, nothing killed; A exits only then. C joins with the same code: B's run is outdated because B drains.tests/hetzner.sh: an overlapping deploy returns while the old scheduler drains (checkinfo,status, reaper started, not stopped); a second deploy while it drains overlaps beside it with its own name; each reaper removes its container once it exits;drain-old --timeout 0stops one; a legacyscheduler-oldstill draining doesn't block the next overlap; check passes beside a draining old scheduler and fails on ascheduler-next.tests/overlap.shunchanged and passing (it setsMORCA_DRAIN_SECONDS=3for its run-out case).Docs: docs/overlap.md (Outdated runs, Deploys that don't overlap, Not in this slice, the stack), docs/hetzner.md (overlapping schedulers, the check, the dev checklist), README ("Long runs across deploys", with the poll-loop example).
Refs #397, #390.
🤖 Generated with Claude Code
https://claude.ai/code/session_017TycszSbyw92Efu4ZeCYL6