Skip to content

Commit b4138e6

Browse files
authored
fix: if there is a name conflict ignore the query error as this will be detected later in the code (#4043)
Signed-off-by: Uroš Marolt <uros@marolt.me>
1 parent d479638 commit b4138e6

1 file changed

Lines changed: 20 additions & 27 deletions

File tree

services/apps/pcc_sync_worker/src/consumer/pccProjectConsumer.ts

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -538,44 +538,37 @@ async function upsertInsightsProject(
538538
)
539539

540540
// INSERT for the subproject segment only (the matched leaf).
541-
// Partial unique index on segmentId WHERE deletedAt IS NULL means ON CONFLICT won't fire
542-
// for soft-deleted rows — use UPDATE-then-INSERT pattern (UPDATE already done above).
541+
// Before inserting, check if a same-family sibling (group/project level sharing the same
542+
// sourceId) already holds this name. Shallow hierarchies (eff=1/2) have group+project+subproject
543+
// all sharing the same name and sourceId — the group/project rows are written first and would
544+
// cause a name conflict on the subproject INSERT. Skip the INSERT in that case; the family is
545+
// already represented.
546+
const sameFamilyNameHolder = await db.oneOrNone(
547+
`SELECT 1
548+
FROM "insightsProjects" ip
549+
JOIN segments s ON s.id = ip."segmentId"
550+
WHERE ip.name = $(name)
551+
AND ip."deletedAt" IS NULL
552+
AND s."sourceId" = $(sourceId)
553+
AND s."tenantId" = $(tenantId)
554+
LIMIT 1`,
555+
{ name: project.name, sourceId, tenantId: DEFAULT_TENANT_ID },
556+
)
557+
if (sameFamilyNameHolder) return false
558+
543559
const exists = await db.oneOrNone<{ id: string }>(
544560
`SELECT id FROM "insightsProjects" WHERE "segmentId" = $(segmentId) AND "deletedAt" IS NULL`,
545561
{ segmentId },
546562
)
547563
if (exists) return false
548564

549565
// logoUrl intentionally omitted from the INSERT column list — see note above.
550-
const inserted = await db.result(
566+
await db.none(
551567
`INSERT INTO "insightsProjects" (name, slug, description, "segmentId", "isLF")
552-
VALUES ($(name), generate_slug('insightsProjects', $(name)), $(description), $(segmentId), TRUE)
553-
ON CONFLICT (name) WHERE "deletedAt" IS NULL DO NOTHING`,
568+
VALUES ($(name), generate_slug('insightsProjects', $(name)), $(description), $(segmentId), TRUE)`,
554569
{ name: project.name, description: project.description, segmentId },
555570
)
556571

557-
if (inserted.rowCount === 0) {
558-
// INSERT was a no-op on the partial unique index (name) WHERE "deletedAt" IS NULL.
559-
// The pre-check above already ruled out cross-sourceId conflicts, so the row holding
560-
// the name must be a same-sourceId sibling — shallow hierarchies (eff=1/2) where
561-
// group/project/subproject share both name and sourceId. Verify before concluding
562-
// it's not a conflict (guards against a hypothetical race with another writer).
563-
const holder = await db.oneOrNone<{ sameFamily: boolean }>(
564-
`SELECT s."sourceId" = $(sourceId) AS "sameFamily"
565-
FROM "insightsProjects" ip
566-
JOIN segments s ON s.id = ip."segmentId"
567-
WHERE ip.name = $(name)
568-
AND ip."deletedAt" IS NULL
569-
AND s."tenantId" = $(tenantId)
570-
LIMIT 1`,
571-
{ name: project.name, sourceId, tenantId: DEFAULT_TENANT_ID },
572-
)
573-
// Same-family holder (or holder vanished between INSERT and re-check) → not a real
574-
// conflict; the project family is already represented via the sibling row.
575-
if (!holder || holder.sameFamily) return false
576-
return true
577-
}
578-
579572
return false
580573
}
581574

0 commit comments

Comments
 (0)