Ensure that availability is fetched in parallel (#14809)
This commit is contained in:
@@ -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 = {
|
||||
|
||||
Reference in New Issue
Block a user