From b0999abc68acf9d7c82cf4cd88ce3a025242f0bc Mon Sep 17 00:00:00 2001 From: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com> Date: Thu, 26 Jun 2025 13:43:31 -0400 Subject: [PATCH] fix: Generate new idempotency key when round robin reassigning (#22065) * Create idempotencyKeyService * Use `idempotencyKeyService` in middleware * Use `idempotencyKeyService` in RR reassignments --- .../roundRobinManualReassignment.ts | 7 +++++++ .../ee/round-robin/roundRobinReassignment.ts | 8 ++++++++ .../idempotencyKey/idempotencyKeyService.ts | 20 +++++++++++++++++++ .../extensions/booking-idempotency-key.ts | 14 ++++++------- 4 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 packages/lib/idempotencyKey/idempotencyKeyService.ts diff --git a/packages/features/ee/round-robin/roundRobinManualReassignment.ts b/packages/features/ee/round-robin/roundRobinManualReassignment.ts index eeebabe091..6cc7ac27c2 100644 --- a/packages/features/ee/round-robin/roundRobinManualReassignment.ts +++ b/packages/features/ee/round-robin/roundRobinManualReassignment.ts @@ -24,6 +24,7 @@ import { SENDER_NAME } from "@calcom/lib/constants"; import { enrichUserWithDelegationCredentialsIncludeServiceAccountKey } from "@calcom/lib/delegationCredential/server"; import { getEventName } from "@calcom/lib/event"; import { getBookerBaseUrl } from "@calcom/lib/getBookerUrl/server"; +import { IdempotencyKeyService } from "@calcom/lib/idempotencyKey/idempotencyKeyService"; import { isPrismaObjOrUndefined } from "@calcom/lib/isPrismaObj"; import logger from "@calcom/lib/logger"; import { getTranslation } from "@calcom/lib/server/i18n"; @@ -181,6 +182,12 @@ export const roundRobinManualReassignment = async ({ userPrimaryEmail: newUser.email, reassignReason, reassignById: reassignedById, + idempotencyKey: IdempotencyKeyService.generate({ + startTime: booking.startTime, + endTime: booking.endTime, + userId: newUser.id, + reassignedById, + }), }, select: bookingSelect, }); diff --git a/packages/features/ee/round-robin/roundRobinReassignment.ts b/packages/features/ee/round-robin/roundRobinReassignment.ts index 3bdcc3adad..39c087b3d5 100644 --- a/packages/features/ee/round-robin/roundRobinReassignment.ts +++ b/packages/features/ee/round-robin/roundRobinReassignment.ts @@ -21,6 +21,8 @@ import { enrichUserWithDelegationCredentialsIncludeServiceAccountKey, } from "@calcom/lib/delegationCredential/server"; import { getEventName } from "@calcom/lib/event"; +import { getBookerBaseUrl } from "@calcom/lib/getBookerUrl/server"; +import { IdempotencyKeyService } from "@calcom/lib/idempotencyKey/idempotencyKeyService"; import { isPrismaObjOrUndefined } from "@calcom/lib/isPrismaObj"; import logger from "@calcom/lib/logger"; import { getLuckyUser } from "@calcom/lib/server/getLuckyUser"; @@ -238,6 +240,12 @@ export const roundRobinReassignment = async ({ userId: reassignedRRHost.id, userPrimaryEmail: reassignedRRHost.email, title: newBookingTitle, + idempotencyKey: IdempotencyKeyService.generate({ + startTime: booking.startTime, + endTime: booking.endTime, + userId: reassignedRRHost.id, + reassignedById, + }), }, select: bookingSelect, }); diff --git a/packages/lib/idempotencyKey/idempotencyKeyService.ts b/packages/lib/idempotencyKey/idempotencyKeyService.ts new file mode 100644 index 0000000000..63ac06aa21 --- /dev/null +++ b/packages/lib/idempotencyKey/idempotencyKeyService.ts @@ -0,0 +1,20 @@ +import { v5 as uuidv5 } from "uuid"; + +export class IdempotencyKeyService { + static generate({ + startTime, + endTime, + userId, + reassignedById, + }: { + startTime: Date | string; + endTime: Date | string; + userId?: number; + reassignedById?: number | null; + }) { + return uuidv5( + `${startTime.valueOf()}.${endTime.valueOf()}.${userId}${reassignedById ? `.${reassignedById}` : ""}`, + uuidv5.URL + ); + } +} diff --git a/packages/prisma/extensions/booking-idempotency-key.ts b/packages/prisma/extensions/booking-idempotency-key.ts index 1179bdafad..ebc56419c2 100644 --- a/packages/prisma/extensions/booking-idempotency-key.ts +++ b/packages/prisma/extensions/booking-idempotency-key.ts @@ -1,6 +1,6 @@ import { Prisma } from "@prisma/client"; -import { v5 as uuidv5 } from "uuid"; +import { IdempotencyKeyService } from "@calcom/lib/idempotencyKey/idempotencyKeyService"; import { BookingStatus } from "@calcom/prisma/enums"; export function bookingIdempotencyKeyExtension() { @@ -9,12 +9,12 @@ export function bookingIdempotencyKeyExtension() { booking: { async create({ args, query }) { if (args.data.status === BookingStatus.ACCEPTED) { - const idempotencyKey = uuidv5( - `${args.data.startTime.valueOf()}.${args.data.endTime.valueOf()}.${ - args.data?.user?.connect?.id - }${args.data?.reassignById ? `.${args.data.reassignById}` : ""}`, - uuidv5.URL - ); + const idempotencyKey = IdempotencyKeyService.generate({ + startTime: args.data.startTime, + endTime: args.data.endTime, + userId: args.data.user?.connect?.id, + reassignedById: args.data.reassignById, + }); args.data.idempotencyKey = idempotencyKey; } return query(args);