Skip to content

fix(automation): keep a vanished job lock contended instead of stale - #739

Merged
ScriptedAlchemy merged 1 commit into
masterfrom
fix/automation-lock-steal
Aug 27, 2026
Merged

fix(automation): keep a vanished job lock contended instead of stale#739
ScriptedAlchemy merged 1 commit into
masterfrom
fix/automation-lock-steal

Conversation

@ScriptedAlchemy

Copy link
Copy Markdown
Owner

The Windows double-execution flake

jobs::concurrent_manual_job_triggers_do_not_double_execute flaked on the 2026-08-04 master run (Test Windows shard 2): backend.calls was 2, and nextest is configured fail-on-flaky.

Race: a manual trigger loses the create_new race; the winner finishes the job and releases (deletes) the lock before the loser's staleness reads complete. lock_created_at then finds no file, lock_is_stale returned true for the missing timestamp, and the loser "reclaimed" the just-released lock and ran the job a second time. Windows' slower file I/O widens the window (the test's backend also blocks the runtime for 200ms, so the loser's checks resume exactly when the winner is finishing).

Fix: a lock with no readable creation timestamp is aged by its on-disk mtime and reported stale only when provably older than the stale window; a vanished lock stays contended. Crash recovery is preserved: dead-pid locks with payload age by created_at as before, and an empty crash leftover ages by mtime — both pinned by new regression tests (task_lock_does_not_steal_fresh_empty_lock_file, task_lock_reclaims_empty_lock_file_older_than_stale_window).

Verification: full automation_runner_test suite 154/154 locally; scoped clippy -D warnings clean on both changed targets; cargo fmt --check clean.

Note for #707: crates/tracedecay-agent-hosts/src/automation/scheduler.rs on the V2 branch has the same create_new + stale-reclaim pattern and needs the same port.

🤖 Generated with Claude Code

https://claude.ai/code/session_01A2BarcJk3iuv77aJQwHvnx

Root cause of the Windows flake in
jobs::concurrent_manual_job_triggers_do_not_double_execute (seen on the
2026-08-04 master run, Test Windows shard 2): when a manual trigger loses
the create_new race and the winner finishes and releases the lock before
the loser's staleness reads complete, lock_created_at reports no
timestamp and lock_is_stale treated that as stale. The loser then
"reclaimed" the released lock and executed the job a second time.

A lock with no readable creation timestamp is now aged by its on-disk
mtime and reported stale only when provably old; a vanished lock stays
contended. Crash leftovers still get reclaimed: a dead-pid lock with
payload ages by created_at, and an empty crash leftover ages by mtime
(both covered by new regression tests).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A2BarcJk3iuv77aJQwHvnx
@changeset-bot

changeset-bot Bot commented Aug 27, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: b44015f

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@ScriptedAlchemy
ScriptedAlchemy merged commit 316c121 into master Aug 27, 2026
16 checks passed
ScriptedAlchemy added a commit that referenced this pull request Aug 27, 2026
Absorbs the master-side CI stabilization. Delete-side conflicts resolve to
this branch: the V2 resolver (lifecycle/identity.rs reject_split_identity_cutover)
already fails closed on populated duplicate shards, path_layout.rs is already
restructured past the clippy lint, and the automation lock code is rewritten
here (the vanished-lock reclaim guard from #739 still needs a V2 port — see
the PR #707 comment from 2026-08-27). Tree is identical to the previous
branch head.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A2BarcJk3iuv77aJQwHvnx
@ScriptedAlchemy
ScriptedAlchemy deleted the fix/automation-lock-steal branch August 27, 2026 07:37
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.

1 participant