mirror of
https://github.com/alkimake/paperclip.git
synced 2026-06-14 01:50:39 +09:00
fix: add executionAgentNameKey to execution lock clears (Greptile)
Issue 1: add executionAgentNameKey = null alongside executionRunId in Fix B (status change, reassignment) and Fix C (staleness clear UPDATE), matching the existing pattern used everywhere else in the codebase. Issue 2: wrap Fix C staleness pre-check in a db.transaction with SELECT ... FOR UPDATE to make the read + conditional clear atomic, consistent with the enqueueWakeup() pattern.
This commit is contained in:
parent
65e0d3d672
commit
72408642b1
1 changed files with 18 additions and 10 deletions
|
|
@ -1293,6 +1293,7 @@ export function issueService(db: Db) {
|
|||
patch.checkoutRunId = null;
|
||||
// Fix B: also clear the execution lock when leaving in_progress
|
||||
patch.executionRunId = null;
|
||||
patch.executionAgentNameKey = null;
|
||||
patch.executionLockedAt = null;
|
||||
}
|
||||
if (
|
||||
|
|
@ -1302,6 +1303,7 @@ export function issueService(db: Db) {
|
|||
patch.checkoutRunId = null;
|
||||
// Fix B: clear execution lock on reassignment, matching checkoutRunId clear
|
||||
patch.executionRunId = null;
|
||||
patch.executionAgentNameKey = null;
|
||||
patch.executionLockedAt = null;
|
||||
}
|
||||
|
||||
|
|
@ -1387,21 +1389,27 @@ export function issueService(db: Db) {
|
|||
// Fix C: staleness detection — if executionRunId references a run that is no
|
||||
// longer queued or running, clear it before applying the execution lock condition
|
||||
// so a dead lock can't produce a spurious 409.
|
||||
const preCheckRow = await db
|
||||
.select({ executionRunId: issues.executionRunId })
|
||||
.from(issues)
|
||||
.where(eq(issues.id, id))
|
||||
.then((rows) => rows[0] ?? null);
|
||||
if (preCheckRow?.executionRunId) {
|
||||
const lockRun = await db
|
||||
// Wrapped in a transaction with SELECT FOR UPDATE to make the read + clear atomic,
|
||||
// matching the existing pattern in enqueueWakeup().
|
||||
await db.transaction(async (tx) => {
|
||||
await tx.execute(
|
||||
sql`select id from issues where id = ${id} for update`,
|
||||
);
|
||||
const preCheckRow = await tx
|
||||
.select({ executionRunId: issues.executionRunId })
|
||||
.from(issues)
|
||||
.where(eq(issues.id, id))
|
||||
.then((rows) => rows[0] ?? null);
|
||||
if (!preCheckRow?.executionRunId) return;
|
||||
const lockRun = await tx
|
||||
.select({ id: heartbeatRuns.id, status: heartbeatRuns.status })
|
||||
.from(heartbeatRuns)
|
||||
.where(eq(heartbeatRuns.id, preCheckRow.executionRunId))
|
||||
.then((rows) => rows[0] ?? null);
|
||||
if (!lockRun || (lockRun.status !== "queued" && lockRun.status !== "running")) {
|
||||
await db
|
||||
await tx
|
||||
.update(issues)
|
||||
.set({ executionRunId: null, executionLockedAt: null, updatedAt: now })
|
||||
.set({ executionRunId: null, executionAgentNameKey: null, executionLockedAt: null, updatedAt: now })
|
||||
.where(
|
||||
and(
|
||||
eq(issues.id, id),
|
||||
|
|
@ -1409,7 +1417,7 @@ export function issueService(db: Db) {
|
|||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const sameRunAssigneeCondition = checkoutRunId
|
||||
? and(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue