Skip to content

Commit

Permalink
perf: Improve loading existing bookings via API (#16410)
Browse files Browse the repository at this point in the history
  • Loading branch information
keithwillcode authored and zomars committed Sep 4, 2024
1 parent 143ff40 commit 51d210e
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 65 deletions.
124 changes: 70 additions & 54 deletions packages/core/getBusyTimes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Booking, EventType } from "@prisma/client";
import { Prisma } from "@prisma/client";

import { getBusyCalendarTimes } from "@calcom/core/CalendarManager";
import dayjs from "@calcom/dayjs";
Expand All @@ -8,7 +9,7 @@ import logger from "@calcom/lib/logger";
import { getPiiFreeBooking } from "@calcom/lib/piiFreeData";
import { performance } from "@calcom/lib/server/perfObserver";
import prisma from "@calcom/prisma";
import type { Prisma, SelectedCalendar } from "@calcom/prisma/client";
import type { SelectedCalendar } from "@calcom/prisma/client";
import { BookingStatus } from "@calcom/prisma/enums";
import { stringToDayjs } from "@calcom/prisma/zod-utils";
import type { EventBusyDetails, IntervalLimit } from "@calcom/types/Calendar";
Expand Down Expand Up @@ -106,63 +107,78 @@ export async function getBusyTimes(params: {
// Will keep support for retrieving a user's bookings if the caller does not already supply them.
// This function is called from multiple places but we aren't refactoring all of them at this moment
// to avoid potential side effects.
const bookings = params.currentBookings
? params.currentBookings
: await prisma.booking.findMany({
where: {
OR: [
// User is primary host (individual events, or primary organizer)
{
...sharedQuery,
userId,
},
// The current user has a different booking at this time he/she attends
{
...sharedQuery,
attendees: {
some: {
email: userEmail,
},
},
},
{
startTime: { lte: endTimeDate },
endTime: { gte: startTimeDate },
eventType: {
id: eventTypeId,
requiresConfirmation: true,
requiresConfirmationWillBlockSlot: true,
},
status: {
in: [BookingStatus.PENDING],
},
},
],
},
let bookings = params.currentBookings;

if (!bookings) {
const bookingsSelect = Prisma.validator<Prisma.BookingSelect>()({
id: true,
uid: true,
userId: true,
startTime: true,
endTime: true,
title: true,
eventType: {
select: {
id: true,
uid: true,
userId: true,
startTime: true,
endTime: true,
title: true,
eventType: {
select: {
id: true,
afterEventBuffer: true,
beforeEventBuffer: true,
seatsPerTimeSlot: true,
},
afterEventBuffer: true,
beforeEventBuffer: true,
seatsPerTimeSlot: true,
},
},
...(seatedEvent && {
_count: {
select: {
seatsReferences: true,
},
...(seatedEvent && {
_count: {
select: {
seatsReferences: true,
},
},
}),
},
});
}),
});

const currentBookingsAllUsersQueryOne = prisma.booking.findMany({
where: {
// User is primary host (individual events, or primary organizer)
...sharedQuery,
userId,
},
select: bookingsSelect,
});

const currentBookingsAllUsersQueryTwo = prisma.booking.findMany({
where: {
...sharedQuery,
attendees: {
some: {
email: userEmail,
},
},
},
select: bookingsSelect,
});

const currentBookingsAllUsersQueryThree = prisma.booking.findMany({
where: {
startTime: { lte: endTimeDate },
endTime: { gte: startTimeDate },
eventType: {
id: eventTypeId,
requiresConfirmation: true,
requiresConfirmationWillBlockSlot: true,
},
status: {
in: [BookingStatus.PENDING],
},
},
select: bookingsSelect,
});

const [resultOne, resultTwo, resultThree] = await Promise.all([
currentBookingsAllUsersQueryOne,
currentBookingsAllUsersQueryTwo,
currentBookingsAllUsersQueryThree,
]);

bookings = [...resultOne, ...resultTwo, ...resultThree];
}

const bookingSeatCountMap: { [x: string]: number } = {};
const busyTimes = bookings.reduce(
Expand Down
16 changes: 5 additions & 11 deletions packages/trpc/server/routers/viewer/slots/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ export async function getAvailableSlots({ input, ctx }: GetScheduleOptions): Pro
};

const allUserIds = usersWithCredentials.map((user) => user.id);
const bookingsSelect = {
const bookingsSelect = Prisma.validator<Prisma.BookingSelect>()({
id: true,
uid: true,
userId: true,
Expand All @@ -468,7 +468,7 @@ export async function getAvailableSlots({ input, ctx }: GetScheduleOptions): Pro
},
},
}),
};
});

const currentBookingsAllUsersQueryOne = prisma.booking.findMany({
where: {
Expand All @@ -477,9 +477,7 @@ export async function getAvailableSlots({ input, ctx }: GetScheduleOptions): Pro
in: allUserIds,
},
},
select: {
...bookingsSelect,
},
select: bookingsSelect,
});

const currentBookingsAllUsersQueryTwo = prisma.booking.findMany({
Expand All @@ -493,9 +491,7 @@ export async function getAvailableSlots({ input, ctx }: GetScheduleOptions): Pro
},
},
},
select: {
...bookingsSelect,
},
select: bookingsSelect,
});

const currentBookingsAllUsersQueryThree = prisma.booking.findMany({
Expand All @@ -511,9 +507,7 @@ export async function getAvailableSlots({ input, ctx }: GetScheduleOptions): Pro
in: [BookingStatus.PENDING],
},
},
select: {
...bookingsSelect,
},
select: bookingsSelect,
});

const [resultOne, resultTwo, resultThree] = await Promise.all([
Expand Down

0 comments on commit 51d210e

Please sign in to comment.