fix(engine): add cross-process merge guard to prevent concurrent merges

Multiple engine processes (dashboard + serve) share the same SQLite database
but each has its own in-memory merge queue. Without a cross-process check,
two processes can start merging different tasks simultaneously.

Added store.getActiveMergingTask() as a DB-level check before any merge
starts. The drainMergeQueue defers with pollIntervalMs delay, and both
aiMergeTask and processPullRequestMergeTask have safety-net checks.
Also moved stale merge status cleanup to run regardless of autoMerge setting.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-04-13 20:21:58 -07:00
parent 827c0370c3
commit f9f7aff3ec
7 changed files with 70 additions and 3 deletions

View File

@@ -213,6 +213,12 @@ export async function processPullRequestMergeTask(
return "waiting";
}
// Cross-process safety net: abort if another task is already mid-merge.
const activeMerge = store.getActiveMergingTask(task.id);
if (activeMerge) {
await store.updateTask(task.id, { status: "awaiting-pr-checks" });
return "waiting";
}
await store.updateTask(task.id, { status: "merging-pr" });
const mergedPr = await github.mergePr({ number: prInfo.number, method: "squash" });
await store.updatePrInfo(task.id, { ...mergedPr, lastCheckedAt: new Date().toISOString() });