Ensure that availability is fetched in parallel (#14809)

This commit is contained in:
Hariom Balhara
2024-05-03 13:56:10 +01:00
committed by GitHub
parent 97b2816897
commit 88f4dd2446
3 changed files with 93 additions and 51 deletions
+40
View File
@@ -794,3 +794,43 @@ const _getOutOfOfficeDays = async ({
return acc;
}, {});
};
type GetUserAvailabilityQuery = Parameters<typeof getUserAvailability>[0];
type GetUserAvailabilityInitialData = NonNullable<Parameters<typeof getUserAvailability>[1]>;
const _getUsersAvailability = async ({
users,
query,
initialData,
}: {
users: (NonNullable<GetUserAvailabilityInitialData["user"]> & {
currentBookings?: GetUserAvailabilityInitialData["currentBookings"];
})[];
query: Omit<GetUserAvailabilityQuery, "userId" | "username">;
initialData?: Omit<GetUserAvailabilityInitialData, "user">;
}) => {
return await Promise.all(
users.map((user) =>
_getUserAvailability(
{
...query,
userId: user.id,
username: user.username || "",
},
initialData
? {
...initialData,
user,
currentBookings: user.currentBookings,
}
: undefined
)
)
);
};
export const getUsersAvailability = async (
...args: Parameters<typeof _getUsersAvailability>
): Promise<ReturnType<typeof _getUsersAvailability>> => {
return monitorCallbackAsync(_getUsersAvailability, ...args);
};
@@ -24,7 +24,7 @@ import { getAppFromSlug } from "@calcom/app-store/utils";
import EventManager from "@calcom/core/EventManager";
import { getEventName } from "@calcom/core/event";
import { getBusyTimesForLimitChecks } from "@calcom/core/getBusyTimes";
import { getUserAvailability } from "@calcom/core/getUserAvailability";
import { getUsersAvailability } from "@calcom/core/getUserAvailability";
import dayjs from "@calcom/dayjs";
import { scheduleMandatoryReminder } from "@calcom/ee/workflows/lib/reminders/scheduleMandatoryReminder";
import {
@@ -362,24 +362,25 @@ export async function ensureAvailableUsers(
});
}
for (const user of eventType.users) {
const { oooExcludedDateRanges: dateRanges, busy: bufferedBusyTimes } = await getUserAvailability(
{
(
await getUsersAvailability({
users: eventType.users,
query: {
...input,
userId: user.id,
eventTypeId: eventType.id,
duration: originalBookingDuration,
returnDateOverrides: false,
dateFrom: startDateTimeUtc.format(),
dateTo: endDateTimeUtc.format(),
},
{
user,
initialData: {
eventType,
rescheduleUid: input.originalRescheduledBooking?.uid ?? null,
busyTimesFromLimitsBookings: busyTimesFromLimitsBookingsAllUsers,
}
);
},
})
).forEach(({ oooExcludedDateRanges: dateRanges, busy: bufferedBusyTimes }, index) => {
const user = eventType.users[index];
log.debug(
"calendarBusyTimes==>>>",
@@ -395,7 +396,7 @@ export async function ensureAvailableUsers(
input,
})
);
continue;
return;
}
let foundConflict = false;
@@ -422,7 +423,7 @@ export async function ensureAvailableUsers(
input,
})
);
continue;
return;
}
try {
@@ -434,7 +435,8 @@ export async function ensureAvailableUsers(
if (!foundConflict) {
availableUsers.push(user);
}
}
});
if (!availableUsers.length) {
loggerWithEventDetails.error(
`No available users found.`,
@@ -5,7 +5,7 @@ import { v4 as uuid } from "uuid";
import { getAggregatedAvailability } from "@calcom/core/getAggregatedAvailability";
import { getBusyTimesForLimitChecks } from "@calcom/core/getBusyTimes";
import type { CurrentSeats, IFromUser, IToUser } from "@calcom/core/getUserAvailability";
import { getUserAvailability } from "@calcom/core/getUserAvailability";
import { getUsersAvailability } from "@calcom/core/getUserAvailability";
import type { Dayjs } from "@calcom/dayjs";
import dayjs from "@calcom/dayjs";
import { getSlugOrRequestedSlug, orgDomainConfig } from "@calcom/ee/organizations/lib/orgDomains";
@@ -456,44 +456,44 @@ export async function getAvailableSlots({ input, ctx }: GetScheduleOptions): Pro
});
}
const users = usersWithCredentials.map((currentUser) => {
return {
...currentUser,
currentBookings: currentBookingsAllUsers
.filter((b) => b.userId === currentUser.id || b.attendees?.some((a) => a.email === currentUser.email))
.map((bookings) => {
const { attendees: _attendees, ...bookingWithoutAttendees } = bookings;
return bookingWithoutAttendees;
}),
};
});
/* We get all users working hours and busy slots */
const allUsersAvailability = await Promise.all(
usersWithCredentials.map(async (currentUser) => {
const {
busy,
dateRanges,
oooExcludedDateRanges,
currentSeats: _currentSeats,
timeZone,
datesOutOfOffice,
} = await getUserAvailability(
{
userId: currentUser.id,
username: currentUser.username || "",
dateFrom: startTime.format(),
dateTo: endTime.format(),
eventTypeId: eventType.id,
afterEventBuffer: eventType.afterEventBuffer,
beforeEventBuffer: eventType.beforeEventBuffer,
duration: input.duration || 0,
returnDateOverrides: false,
},
{
user: currentUser,
eventType,
currentSeats,
rescheduleUid: input.rescheduleUid,
currentBookings: currentBookingsAllUsers
.filter(
(b) => b.userId === currentUser.id || b.attendees?.some((a) => a.email === currentUser.email)
)
.map((bookings) => {
const { attendees: _attendees, ...bookingWithoutAttendees } = bookings;
return bookingWithoutAttendees;
}),
busyTimesFromLimitsBookings: busyTimesFromLimitsBookingsAllUsers,
}
);
const allUsersAvailability = (
await getUsersAvailability({
users,
query: {
dateFrom: startTime.format(),
dateTo: endTime.format(),
eventTypeId: eventType.id,
afterEventBuffer: eventType.afterEventBuffer,
beforeEventBuffer: eventType.beforeEventBuffer,
duration: input.duration || 0,
returnDateOverrides: false,
},
initialData: {
eventType,
currentSeats,
rescheduleUid: input.rescheduleUid,
busyTimesFromLimitsBookings: busyTimesFromLimitsBookingsAllUsers,
},
})
).map(
(
{ busy, dateRanges, oooExcludedDateRanges, currentSeats: _currentSeats, timeZone, datesOutOfOffice },
index
) => {
const currentUser = users[index];
if (!currentSeats && _currentSeats) currentSeats = _currentSeats;
return {
timeZone,
@@ -503,7 +503,7 @@ export async function getAvailableSlots({ input, ctx }: GetScheduleOptions): Pro
user: currentUser,
datesOutOfOffice,
};
})
}
);
const availabilityCheckProps = {