fix(FN-5363): target mergeQueue lease to specific task ID instead of queue head
The merge handoff path in acquireReuseHandoff called acquireMergeQueueLease without a targetTaskId, which grabbed the priority/FIFO-sorted queue head instead of the specific in-review task. When the queue head was a different task (e.g. a polluted non-review entry), the returned lease had a mismatched taskId and triggered 'no-lease' for every in-review task. Fix: - Pass targetTaskId: input.task.id to acquireMergeQueueLease so the merge lane targets its specific task instead of grabbing the queue head. MergeQueueAcquireOptions.targetTaskId is already wired in store.ts. - Replace the broken typeof check (typeof object !== 'object' is always false for plain JSON objects returned by RETURNING *) with a proper 'taskId' in lease guard. - Add acquiredTaskId to the no-lease error payload for better observability. Reliability backstop: merge-reuse-task-worktree.test.ts guards this path. Fixes: FN-5363
This commit is contained in:
@@ -395,9 +395,10 @@ export async function acquireReuseHandoff(input: ReuseHandoffInput): Promise<Han
|
||||
// Non-atomic fallback: executor lease checks above race with mergeQueue lease acquisition.
|
||||
// TaskStore does not yet expose an atomic executor-lease absence check inside mergeQueue leasing.
|
||||
lease = (input.store as TaskStore & {
|
||||
acquireMergeQueueLease(workerId: string, opts: { leaseDurationMs: number; now?: string }): unknown;
|
||||
acquireMergeQueueLease(workerId: string, opts: { leaseDurationMs: number; now?: string; targetTaskId?: string }): unknown;
|
||||
}).acquireMergeQueueLease(MERGE_HANDOFF_WORKER_ID, {
|
||||
leaseDurationMs: 15 * 60 * 1000,
|
||||
targetTaskId: input.task.id,
|
||||
});
|
||||
} catch (error) {
|
||||
if (error instanceof PoolDoubleLeaseError) {
|
||||
@@ -412,10 +413,11 @@ export async function acquireReuseHandoff(input: ReuseHandoffInput): Promise<Han
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
if (!lease || typeof lease !== "object" || (lease as { taskId?: string }).taskId !== input.task.id) {
|
||||
if (!lease || !("taskId" in lease) || lease.taskId !== input.task.id) {
|
||||
throw new MergeHandoffRefusedError("lease-handoff-failed", "no-lease", {
|
||||
taskId: input.task.id,
|
||||
worktreePath,
|
||||
acquiredTaskId: lease && "taskId" in lease ? lease.taskId : null,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user