fix(ploeg): keep the legacy claim off Work Items a live Shift owns #153

Merged
ryangr0 merged 1 commit from ryangr0/ploeg-legacy-claim-respects-shifts into development 2026-10-03 00:26:44 +00:00 AGit
Owner

A role-less claim tried the Shift path first and fell back to
Store.ClaimWithin after ErrNoWork or ErrBudgetExhausted. ClaimWithin
selected any queued item, including one owned by a live Shift. Two
role-less workers could race: one locked the Shift's pending empty-role
Run, the other skipped it under SKIP LOCKED, got ErrNoWork and leased the
same still-queued Work Item through the legacy path. That created a Run
outside the Shift and its pool, and managed mode signed a token for it.
An exhausted Shift pool likewise fell through to an unpooled legacy
claim.

ClaimWithin now excludes items with a live Shift, and a role-less claim
that the Shift path refuses for budget answers 204 without trying the
legacy path. Items without a Shift are claimed as before; the claimable
index test now covers the new predicate.

The roleless KEDA scaler query in ops/helm/ploeg/templates/scaledjob.yaml is deliberately unchanged: it now counts a superset (empty-role Shift Runs keep their item queued), which only overshoots. Its 'must stay in sync with store.Claim' comment is now slightly loose.

Verified with mise run verify on the pinned toolchain (all gates passed).

Ticket: https://vikunja.webgrip.dev/tasks/1735

🤖 Generated with Claude Code

A role-less claim tried the Shift path first and fell back to Store.ClaimWithin after ErrNoWork or ErrBudgetExhausted. ClaimWithin selected any queued item, including one owned by a live Shift. Two role-less workers could race: one locked the Shift's pending empty-role Run, the other skipped it under SKIP LOCKED, got ErrNoWork and leased the same still-queued Work Item through the legacy path. That created a Run outside the Shift and its pool, and managed mode signed a token for it. An exhausted Shift pool likewise fell through to an unpooled legacy claim. ClaimWithin now excludes items with a live Shift, and a role-less claim that the Shift path refuses for budget answers 204 without trying the legacy path. Items without a Shift are claimed as before; the claimable index test now covers the new predicate. The roleless KEDA scaler query in ops/helm/ploeg/templates/scaledjob.yaml is deliberately unchanged: it now counts a superset (empty-role Shift Runs keep their item queued), which only overshoots. Its 'must stay in sync with store.Claim' comment is now slightly loose. Verified with `mise run verify` on the pinned toolchain (all gates passed). Ticket: https://vikunja.webgrip.dev/tasks/1735 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(ploeg): keep the legacy claim off Work Items a live Shift owns
Some checks failed
[Workflow] On Pull Request / checks (pull_request) Has been cancelled
[Workflow] On Pull Request / warnings (pull_request) Has been cancelled
[Workflow] On Pull Request / release-policy (pull_request) Has been cancelled
c31b804c2b
A role-less claim tried the Shift path first and fell back to
Store.ClaimWithin after ErrNoWork or ErrBudgetExhausted. ClaimWithin
selected any queued item, including one owned by a live Shift. Two
role-less workers could race: one locked the Shift's pending empty-role
Run, the other skipped it under SKIP LOCKED, got ErrNoWork and leased the
same still-queued Work Item through the legacy path. That created a Run
outside the Shift and its pool, and managed mode signed a token for it.
An exhausted Shift pool likewise fell through to an unpooled legacy
claim.

ClaimWithin now excludes items with a live Shift, and a role-less claim
that the Shift path refuses for budget answers 204 without trying the
legacy path. Items without a Shift are claimed as before; the claimable
index test now covers the new predicate.

VIK-1735

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
ryangr0 merged commit e5180daf4c into development 2026-10-03 00:26:44 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
webgrip/unfold!153
No description provided.