feat(FN-5363): remove queue-head fallback in acquireMergeQueueLease targetTaskId path
When targetTaskId is passed, the lease attempt must target that task only. The previous code silently fell back to queue-head selection if the targeted task was not available — producing a lease for a different task, then returning it with the wrong taskId. acquireReuseHandoff would then see lease.taskId !== input.task.id and emit a misleading 'no-lease' diagnostic that hid the real cause (queue head was occupied by an unrelated task). The fix: when targetTaskId is set and the lease for that task returns null, return null immediately instead of falling through to the queue-head SELECT. Callers (acquireReuseHandoff) already validate the returned taskId and emit structured 'no-lease' diagnostics including acquiredTaskId so the polluter is identifiable in audit logs. Queue-head fallback is preserved for callers that omit targetTaskId (backward-compatible).
This commit is contained in:
@@ -5996,24 +5996,64 @@ export class TaskStore extends EventEmitter<TaskStoreEvents> {
|
|||||||
return this.db.transactionImmediate(() => {
|
return this.db.transactionImmediate(() => {
|
||||||
const now = opts.now ?? new Date().toISOString();
|
const now = opts.now ?? new Date().toISOString();
|
||||||
const leaseExpiresAt = new Date(Date.parse(now) + opts.leaseDurationMs).toISOString();
|
const leaseExpiresAt = new Date(Date.parse(now) + opts.leaseDurationMs).toISOString();
|
||||||
const leased = this.db.prepare(`
|
|
||||||
UPDATE mergeQueue
|
// Target the specific task if provided; return null immediately when unavailable
|
||||||
SET leasedBy = ?, leasedAt = ?, leaseExpiresAt = ?
|
// rather than falling back to the queue head, so callers that pass targetTaskId
|
||||||
WHERE taskId = (
|
// can distinguish "target not available" from "no tasks available".
|
||||||
SELECT taskId FROM mergeQueue
|
let leased: MergeQueueRow | undefined;
|
||||||
WHERE leasedBy IS NULL OR leaseExpiresAt <= ?
|
if (opts.targetTaskId) {
|
||||||
ORDER BY CASE priority
|
leased = this.db.prepare(`
|
||||||
WHEN 'urgent' THEN 0
|
UPDATE mergeQueue
|
||||||
WHEN 'high' THEN 1
|
SET leasedBy = ?, leasedAt = ?, leaseExpiresAt = ?
|
||||||
WHEN 'normal' THEN 2
|
WHERE taskId = ?
|
||||||
WHEN 'low' THEN 3
|
AND (leasedBy IS NULL OR leaseExpiresAt <= ?)
|
||||||
ELSE 4
|
RETURNING *
|
||||||
END ASC,
|
`).get(workerId, now, leaseExpiresAt, opts.targetTaskId, now) as MergeQueueRow | undefined;
|
||||||
enqueuedAt ASC
|
// Do NOT fall back to queue-head when a target was explicitly requested.
|
||||||
LIMIT 1
|
// Callers (e.g. acquireReuseHandoff) use the returned taskId to validate
|
||||||
)
|
// the lease and emit structured diagnostics for "target unavailable".
|
||||||
RETURNING *
|
} else {
|
||||||
`).get(workerId, now, leaseExpiresAt, now) as MergeQueueRow | undefined;
|
// Backward-compatible queue-head selection for callers that don't target a task.
|
||||||
|
leased = this.db.prepare(`
|
||||||
|
UPDATE mergeQueue
|
||||||
|
SET leasedBy = ?, leasedAt = ?, leaseExpiresAt = ?
|
||||||
|
WHERE taskId = (
|
||||||
|
SELECT taskId FROM mergeQueue
|
||||||
|
WHERE leasedBy IS NULL OR leaseExpiresAt <= ?
|
||||||
|
ORDER BY CASE priority
|
||||||
|
WHEN 'urgent' THEN 0
|
||||||
|
WHEN 'high' THEN 1
|
||||||
|
WHEN 'normal' THEN 2
|
||||||
|
WHEN 'low' THEN 3
|
||||||
|
ELSE 4
|
||||||
|
END ASC,
|
||||||
|
enqueuedAt ASC
|
||||||
|
LIMIT 1
|
||||||
|
)
|
||||||
|
RETURNING *
|
||||||
|
`).get(workerId, now, leaseExpiresAt, now) as MergeQueueRow | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!leased) {
|
||||||
|
leased = this.db.prepare(`
|
||||||
|
UPDATE mergeQueue
|
||||||
|
SET leasedBy = ?, leasedAt = ?, leaseExpiresAt = ?
|
||||||
|
WHERE taskId = (
|
||||||
|
SELECT taskId FROM mergeQueue
|
||||||
|
WHERE leasedBy IS NULL OR leaseExpiresAt <= ?
|
||||||
|
ORDER BY CASE priority
|
||||||
|
WHEN 'urgent' THEN 0
|
||||||
|
WHEN 'high' THEN 1
|
||||||
|
WHEN 'normal' THEN 2
|
||||||
|
WHEN 'low' THEN 3
|
||||||
|
ELSE 4
|
||||||
|
END ASC,
|
||||||
|
enqueuedAt ASC
|
||||||
|
LIMIT 1
|
||||||
|
)
|
||||||
|
RETURNING *
|
||||||
|
`).get(workerId, now, leaseExpiresAt, now) as MergeQueueRow | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
if (!leased) {
|
if (!leased) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
Reference in New Issue
Block a user