From 2967cdbf7588ba96313092065cd428a5836c27da Mon Sep 17 00:00:00 2001 From: Eric Allam Date: Wed, 15 Jul 2026 18:56:04 +0100 Subject: [PATCH] fix(run-store): fix batch idempotency lookup on the dedicated run-ops store findRunsByIdempotencyKeys built its UNION ALL of per-key point-lookups with @trigger.dev/database's Prisma.sql/Prisma.join and then ran it on whichever store client it was handed. On the dedicated run-ops store that client is a separate generated Prisma client, and a Sql from a different generated client is not recognized: the bare $queryRaw(Prisma.join(...)) form dropped the query text ("Argument query is missing"), so batchTrigger requests carrying any per-item idempotencyKey failed. Rebuild the lookup as a plain parameterized string via $queryRawUnsafe (static SQL + integer placeholders, all values bound), so it no longer depends on which generated client executes it. Same per-key point-lookup shape; no change on the single-client path. --- .../fix-batch-idempotency-per-item-keys.md | 6 ++++++ .../run-store/src/PostgresRunStore.ts | 14 ++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 .server-changes/fix-batch-idempotency-per-item-keys.md diff --git a/.server-changes/fix-batch-idempotency-per-item-keys.md b/.server-changes/fix-batch-idempotency-per-item-keys.md new file mode 100644 index 0000000000..9e84d474c3 --- /dev/null +++ b/.server-changes/fix-batch-idempotency-per-item-keys.md @@ -0,0 +1,6 @@ +--- +area: webapp +type: fix +--- + +Fix batchTrigger requests that set a per-item idempotency key failing with an error instead of creating and deduplicating the runs diff --git a/internal-packages/run-store/src/PostgresRunStore.ts b/internal-packages/run-store/src/PostgresRunStore.ts index b709857932..c206f4605f 100644 --- a/internal-packages/run-store/src/PostgresRunStore.ts +++ b/internal-packages/run-store/src/PostgresRunStore.ts @@ -72,6 +72,7 @@ export interface RunOpsCapableClient { // Standalone entity keyed by (environmentId, name); present on both schemas. waitpointTag: RunOpsDelegate<"upsert" | "findMany">; $queryRaw: PrismaClient["$queryRaw"]; + $queryRawUnsafe: PrismaClient["$queryRawUnsafe"]; $executeRaw: PrismaClient["$executeRaw"]; } @@ -1691,11 +1692,16 @@ export class PostgresRunStore implements RunStore { return []; } const prisma = (client ?? this.readOnlyPrisma) as RunOpsCapableClient; - const branches = args.idempotencyKeys.map( - (key) => - Prisma.sql`SELECT "friendlyId", "idempotencyKey", "idempotencyKeyExpiresAt" FROM "TaskRun" WHERE "runtimeEnvironmentId" = ${args.runtimeEnvironmentId} AND "taskIdentifier" = ${args.taskIdentifier} AND "idempotencyKey" = ${key}` + const params: string[] = []; + const branches = args.idempotencyKeys.map((key) => { + const base = params.length; + params.push(args.runtimeEnvironmentId, args.taskIdentifier, key); + return `SELECT "friendlyId", "idempotencyKey", "idempotencyKeyExpiresAt" FROM "TaskRun" WHERE "runtimeEnvironmentId" = $${base + 1} AND "taskIdentifier" = $${base + 2} AND "idempotencyKey" = $${base + 3}`; + }); + return prisma.$queryRawUnsafe( + branches.join(" UNION ALL "), + ...params ); - return prisma.$queryRaw(Prisma.join(branches, " UNION ALL ")); } // --- run-ops persistence ---