From 45bccb700d9250efead64cf68dc10399ff35ed74 Mon Sep 17 00:00:00 2001 From: Nicky Leach Date: Sat, 20 Jun 2026 02:13:58 +0000 Subject: [PATCH] Serialize gate confirmation mirror writes --- server/src/__tests__/issues-service.test.ts | 8 +++++++- server/src/services/issues.ts | 12 +++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/server/src/__tests__/issues-service.test.ts b/server/src/__tests__/issues-service.test.ts index 1d6c13a6593..684576f61ef 100644 --- a/server/src/__tests__/issues-service.test.ts +++ b/server/src/__tests__/issues-service.test.ts @@ -2957,7 +2957,13 @@ describeEmbeddedPostgres("issueService.create workspace inheritance", () => { body: `A user pasted the mirror marker: `, }); - const mirrored = await svc.mirrorGateConfirmationToParent(child.id); + const mirrorResults = await Promise.all([ + svc.mirrorGateConfirmationToParent(child.id), + svc.mirrorGateConfirmationToParent(child.id), + ]); + expect(mirrorResults.filter(Boolean)).toHaveLength(1); + expect(mirrorResults.filter((result) => result === null)).toHaveLength(1); + const mirrored = mirrorResults.find(Boolean); expect(mirrored).toMatchObject({ issueId: parentIssueId, authorType: "system", diff --git a/server/src/services/issues.ts b/server/src/services/issues.ts index d4e6d260de7..b53aefca7c0 100644 --- a/server/src/services/issues.ts +++ b/server/src/services/issues.ts @@ -4645,8 +4645,8 @@ export function issueService(db: Db) { }; }, - mirrorGateConfirmationToParent: async (childIssueId: string) => { - const child = await db + mirrorGateConfirmationToParent: async (childIssueId: string) => db.transaction(async (tx) => { + const child = await tx .select({ id: issues.id, companyId: issues.companyId, @@ -4658,6 +4658,7 @@ export function issueService(db: Db) { }) .from(issues) .where(eq(issues.id, childIssueId)) + .for("update") .then((rows) => rows[0] ?? null); if (!child || child.status !== "done" || !child.parentId) return null; @@ -4665,7 +4666,7 @@ export function issueService(db: Db) { if (!mirror || mirror.parentIssueId !== child.parentId) return null; const marker = buildGateConfirmationMirrorMarker(child.id); - const existingMirror = await db + const existingMirror = await tx .select({ id: issueComments.id }) .from(issueComments) .where(and( @@ -4678,7 +4679,7 @@ export function issueService(db: Db) { .then((rows) => rows[0] ?? null); if (existingMirror) return null; - const latestChildComment = await db + const latestChildComment = await tx .select({ body: issueComments.body }) .from(issueComments) .where(and( @@ -4700,8 +4701,9 @@ export function issueService(db: Db) { }), {}, { authorType: "system" }, + tx, ); - }, + }), createChild: async ( parentIssueId: string,