diff --git a/apps/web/pages/api/trpc/highPerf/[trpc].ts b/apps/web/pages/api/trpc/highPerf/[trpc].ts new file mode 100644 index 0000000000..e4cc725948 --- /dev/null +++ b/apps/web/pages/api/trpc/highPerf/[trpc].ts @@ -0,0 +1,4 @@ +import { createNextApiHandler } from "@calcom/trpc/server/createNextApiHandler"; +import { highPerfRouter } from "@calcom/trpc/server/routers/viewer/highPerf/_router"; + +export default createNextApiHandler(highPerfRouter); diff --git a/apps/web/vercel.json b/apps/web/vercel.json index f1b2234b59..6e44699ba3 100644 --- a/apps/web/vercel.json +++ b/apps/web/vercel.json @@ -14,11 +14,8 @@ } ], "functions": { - "pages/api/trpc/public/[trpc].ts": { - "memory": 1024 - }, - "pages/api/trpc/slots/[trpc].ts": { - "memory": 1024 + "pages/api/trpc/highPerf/[trpc].ts": { + "memory": 3008 }, "pages/api/trpc/appRoutingForms/[trpc].ts": { "memory": 2048 diff --git a/packages/features/schedules/lib/use-schedule/useSchedule.ts b/packages/features/schedules/lib/use-schedule/useSchedule.ts index fb8e6a2b75..592995f009 100644 --- a/packages/features/schedules/lib/use-schedule/useSchedule.ts +++ b/packages/features/schedules/lib/use-schedule/useSchedule.ts @@ -48,40 +48,46 @@ export const useSchedule = ({ const searchParams = useSearchParams(); const routedTeamMemberIds = searchParams ? getRoutedTeamMemberIdsFromSearchParams(searchParams) : null; const skipContactOwner = searchParams ? searchParams.get("cal.skipContactOwner") === "true" : false; - return trpc.viewer.public.slots.getSchedule.useQuery( - { - isTeamEvent, - usernameList: getUsernameList(username ?? ""), - // Prioritize slug over id, since slug is the first value we get available. - // If we have a slug, we don't need to fetch the id. - // TODO: are queries using eventTypeId faster? Even tho we lost time fetching the id with the slug. - ...(eventSlug ? { eventTypeSlug: eventSlug } : { eventTypeId: eventId ?? 0 }), - // @TODO: Old code fetched 2 days ago if we were fetching the current month. - // Do we want / need to keep that behavior? - startTime, - // if `prefetchNextMonth` is true, two months are fetched at once. - endTime, - timeZone: timezone!, - duration: duration ? `${duration}` : undefined, - rescheduleUid, - orgSlug, - teamMemberEmail, - routedTeamMemberIds, - skipContactOwner, - }, - { - trpc: { - context: { - skipBatch: true, - }, + + const input = { + isTeamEvent, + usernameList: getUsernameList(username ?? ""), + // Prioritize slug over id, since slug is the first value we get available. + // If we have a slug, we don't need to fetch the id. + // TODO: are queries using eventTypeId faster? Even tho we lost time fetching the id with the slug. + ...(eventSlug ? { eventTypeSlug: eventSlug } : { eventTypeId: eventId ?? 0 }), + // @TODO: Old code fetched 2 days ago if we were fetching the current month. + // Do we want / need to keep that behavior? + startTime, + // if `prefetchNextMonth` is true, two months are fetched at once. + endTime, + timeZone: timezone!, + duration: duration ? `${duration}` : undefined, + rescheduleUid, + orgSlug, + teamMemberEmail, + routedTeamMemberIds, + skipContactOwner, + }; + + const options = { + trpc: { + context: { + skipBatch: true, }, - refetchOnWindowFocus: false, - enabled: - Boolean(username) && - Boolean(month) && - Boolean(timezone) && - // Should only wait for one or the other, not both. - (Boolean(eventSlug) || Boolean(eventId) || eventId === 0), - } - ); + }, + refetchOnWindowFocus: false, + enabled: + Boolean(username) && + Boolean(month) && + Boolean(timezone) && + // Should only wait for one or the other, not both. + (Boolean(eventSlug) || Boolean(eventId) || eventId === 0), + }; + + if (isTeamEvent) { + return trpc.viewer.highPerf.getTeamSchedule.useQuery(input, options); + } + + return trpc.viewer.public.slots.getSchedule.useQuery(input, options); }; diff --git a/packages/trpc/react/shared.ts b/packages/trpc/react/shared.ts index 9593b90740..a7c1bf6dcf 100644 --- a/packages/trpc/react/shared.ts +++ b/packages/trpc/react/shared.ts @@ -13,6 +13,7 @@ export const ENDPOINTS = [ "dsync", "eventTypes", "features", + "highPerf", "insights", "payments", "public", diff --git a/packages/trpc/server/createNextApiHandler.ts b/packages/trpc/server/createNextApiHandler.ts index 38d3483d8e..a824589d06 100644 --- a/packages/trpc/server/createNextApiHandler.ts +++ b/packages/trpc/server/createNextApiHandler.ts @@ -71,7 +71,8 @@ export function createNextApiHandler(router: AnyRouter, isPublic = false, namesp cityTimezones: SETTING_FOR_CACHED_BY_VERSION, // FIXME: Using `max-age=1, stale-while-revalidate=60` fails some booking tests. - "slots.getSchedule": `no-cache`, + "slots.getSchedule": `no-cache`, // INFO: This needs the slots prefix because it lives us the public router + getTeamSchedule: `no-cache`, // Feature Flags change but it might be okay to have a 5 minute cache to avoid burdening the servers with requests for this. // Note that feature flags can be used to quickly kill a feature if it's not working as expected. So, we have to keep fresh time lesser than the deployment time atleast diff --git a/packages/trpc/server/routers/viewer/_router.tsx b/packages/trpc/server/routers/viewer/_router.tsx index 7911503b4f..22e4cc5e1c 100644 --- a/packages/trpc/server/routers/viewer/_router.tsx +++ b/packages/trpc/server/routers/viewer/_router.tsx @@ -19,6 +19,7 @@ import { deploymentSetupRouter } from "./deploymentSetup/_router"; import { dsyncRouter } from "./dsync/_router"; import { eventTypesRouter } from "./eventTypes/_router"; import { googleWorkspaceRouter } from "./googleWorkspace/_router"; +import { highPerfRouter } from "./highPerf/_router"; import { oAuthRouter } from "./oAuth/_router"; import { viewerOrganizationsRouter } from "./organizations/_router"; import { paymentsRouter } from "./payments/_router"; @@ -61,5 +62,6 @@ export const viewerRouter = mergeRouters( googleWorkspace: googleWorkspaceRouter, admin: adminRouter, attributes: attributesRouter, + highPerf: highPerfRouter, }) ); diff --git a/packages/trpc/server/routers/viewer/highPerf/_router.tsx b/packages/trpc/server/routers/viewer/highPerf/_router.tsx new file mode 100644 index 0000000000..e755dc7ca6 --- /dev/null +++ b/packages/trpc/server/routers/viewer/highPerf/_router.tsx @@ -0,0 +1,30 @@ +import publicProcedure from "../../../procedures/publicProcedure"; +import { router } from "../../../trpc"; +import { ZGetTeamScheduleInputSchema } from "./getTeamSchedule.schema"; + +type SlotsRouterHandlerCache = { + getTeamSchedule?: typeof import("./getTeamSchedule.handler").getTeamScheduleHandler; +}; + +const UNSTABLE_HANDLER_CACHE: SlotsRouterHandlerCache = {}; + +/** This should be called getAvailableSlots */ +export const highPerfRouter = router({ + getTeamSchedule: publicProcedure.input(ZGetTeamScheduleInputSchema).query(async ({ input, ctx }) => { + if (!UNSTABLE_HANDLER_CACHE.getTeamSchedule) { + UNSTABLE_HANDLER_CACHE.getTeamSchedule = await import("./getTeamSchedule.handler").then( + (mod) => mod.getTeamScheduleHandler + ); + } + + // Unreachable code but required for type safety + if (!UNSTABLE_HANDLER_CACHE.getTeamSchedule) { + throw new Error("Failed to load handler"); + } + + return UNSTABLE_HANDLER_CACHE.getTeamSchedule({ + ctx, + input, + }); + }), +}); diff --git a/packages/trpc/server/routers/viewer/highPerf/getTeamSchedule.handler.ts b/packages/trpc/server/routers/viewer/highPerf/getTeamSchedule.handler.ts new file mode 100644 index 0000000000..9dac887cad --- /dev/null +++ b/packages/trpc/server/routers/viewer/highPerf/getTeamSchedule.handler.ts @@ -0,0 +1,17 @@ +import type { IncomingMessage } from "http"; + +import { getAvailableSlots } from "../slots/util"; +import type { TGetTeamScheduleInputSchema } from "./getTeamSchedule.schema"; + +export type GetTeamScheduleOptions = { + ctx?: ContextForGetSchedule; + input: TGetTeamScheduleInputSchema; +}; + +interface ContextForGetSchedule extends Record { + req?: (IncomingMessage & { cookies: Partial<{ [key: string]: string }> }) | undefined; +} + +export const getTeamScheduleHandler = async ({ ctx, input }: GetTeamScheduleOptions) => { + return await getAvailableSlots({ ctx, input }); +}; diff --git a/packages/trpc/server/routers/viewer/highPerf/getTeamSchedule.schema.ts b/packages/trpc/server/routers/viewer/highPerf/getTeamSchedule.schema.ts new file mode 100644 index 0000000000..59472f0194 --- /dev/null +++ b/packages/trpc/server/routers/viewer/highPerf/getTeamSchedule.schema.ts @@ -0,0 +1,7 @@ +import type { z } from "zod"; + +import { getScheduleSchema } from "../slots/types"; + +export const ZGetTeamScheduleInputSchema = getScheduleSchema; + +export type TGetTeamScheduleInputSchema = z.infer;