Skip to content

Prevent late DELETE requests from resurrecting deleted jobs - #910

Open
LoopedBard3 wants to merge 1 commit into
dotnet:mainfrom
LoopedBard3:loopedbard3-crank-late-delete-bug
Open

LoopedBard3 wants to merge 1 commit into
dotnet:mainfrom
LoopedBard3:loopedbard3-crank-late-delete-bug

Conversation

@LoopedBard3

Copy link
Copy Markdown
Member

Summary

A late or repeated DELETE can change retained job metadata from Deleted back to Deleting after its run group has finished. The worker selects new groups through New jobs, so the old run need not be processed again even though cleanup has already completed.

  • Make DELETE a state-preserving no-op for already-deleted jobs while retaining existing 202/Location and missing-ID 204 responses.
  • Synchronize its guarded mutation with the worker's terminal publication using the same per-job monitor. Capture the previous state under that monitor and log afterward, with no cleanup or await inside the critical section.
  • Add focused regressions for late/repeated requests, all current non-Deleted states, missing IDs, and both orderings of the real production transitions. A small internal worker transition helper avoids reflection-heavy worker setup in tests.

Verification

Reproduced the defect against freshly fetched upstream main at 0d35cad5102892b091d9a88a52ea1f7a91bb1381. The original terminal-preservation assertions failed with expected Deleted, actual Deleting.

dotnet test .\test\Microsoft.Crank.UnitTests\Microsoft.Crank.UnitTests.csproj --no-restore --filter "FullyQualifiedName~JobDeletionTests|FullyQualifiedName~JobsControllerTests"

Final result on Windows/.NET 10: 39 passed, including 16 new cases and 23 existing controller tests. The race tests also reject a guard moved outside the controller lock and an unlocked worker publication; the correct implementation was restored and revalidated afterward.

This verifies the current-upstream defect and local fix, not the source revision of any previously deployed binary. No benchmark, deployment, Linux, or live-agent validation is claimed. Other state-writer races and controller behavior are outside this change.

Synchronize DELETE with terminal-state publication using the same per-job monitor. Keep logging outside the worker critical section and cover both transition orderings and existing HTTP behavior.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 083b3d15-ae89-4560-9534-38e65695d3be

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.

🟢 Approval recommended

The shared monitor correctly serializes the two transitions, existing responses are preserved, and no unresolved issues were identified.

No open issues 🎉

What changed in this PR

Prevents late or repeated DELETE requests from moving completed jobs back from Deleted to Deleting, while preserving existing HTTP responses.

Changes:

  • Guards DELETE state changes with the same per-job monitor used for worker completion.
  • Extracts terminal-state publication into an internal helper, keeping cleanup and logging outside the lock.
  • Adds regression tests for repeated requests, missing jobs, non-deleted states, and both concurrent transition orderings.
File Description
test/​Microsoft.Crank.UnitTests/​JobDeletionTests.cs Tests deletion behavior and synchronized terminal-state preservation.
src/​Microsoft.Crank.Agent/​Startup.cs Publishes Deleted under the job monitor and logs afterward.
src/​Microsoft.Crank.Agent/​Controllers/​JobsController.cs Preserves Deleted under the shared monitor without changing responses.

Review effort: Balanced

@LoopedBard3
LoopedBard3 marked this pull request as ready for review October 21, 2026 22:40
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.

2 participants