perf: Move OOO-related tRPC procedures to new routers (#20136)

* perf: Move OOO-related tRPC procedures to new routers

* Moved test file

* push fix for import path in tests

* fix trpc response url that we wait for

---------

Co-authored-by: sean-brydon <sean@cal.com>
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
This commit is contained in:
Keith Williams
2025-03-21 09:03:10 -07:00
committed by GitHub
co-authored by sean-brydon Anik Dhabal Babu sean-brydon
parent 15cb687307
commit 78ddf71823
25 changed files with 62 additions and 94 deletions
@@ -41,7 +41,7 @@ export const AvailabilitySettingsWebWrapper = ({
const isPending = isFetchingPending && !scheduleProp;
const schedule = scheduleProp ?? scheduleData;
const { data: travelSchedulesData } = trpc.viewer.getTravelSchedules.useQuery(undefined, {
const { data: travelSchedulesData } = trpc.viewer.travelSchedules.get.useQuery(undefined, {
enabled: !travelSchedulesProp,
});
const travelSchedules = travelSchedulesProp ?? travelSchedulesData;
@@ -63,7 +63,7 @@ const SkeletonLoader = () => {
interface GeneralViewProps {
localeProp: string;
user: RouterOutputs["viewer"]["me"]["get"];
travelSchedules: RouterOutputs["viewer"]["getTravelSchedules"];
travelSchedules: RouterOutputs["viewer"]["travelSchedules"]["get"];
revalidatePage: GeneralQueryViewProps["revalidatePage"];
}
@@ -77,7 +77,7 @@ const GeneralQueryView = ({ revalidatePage }: GeneralQueryViewProps) => {
const { data: user, isPending } = trpc.viewer.me.get.useQuery();
const { data: travelSchedules, isPending: isPendingTravelSchedules } =
trpc.viewer.getTravelSchedules.useQuery();
trpc.viewer.travelSchedules.get.useQuery();
if (isPending || isPendingTravelSchedules) return <SkeletonLoader />;
if (!user) {
+4
View File
@@ -0,0 +1,4 @@
import { createNextApiHandler } from "@calcom/trpc/server/createNextApiHandler";
import { oooRouter } from "@calcom/trpc/server/routers/viewer/ooo/_router";
export default createNextApiHandler(oooRouter);
@@ -0,0 +1,4 @@
import { createNextApiHandler } from "@calcom/trpc/server/createNextApiHandler";
import { travelSchedulesRouter } from "@calcom/trpc/server/routers/viewer/travelSchedules/_router";
export default createNextApiHandler(travelSchedulesRouter);
+1 -1
View File
@@ -808,7 +808,7 @@ test.describe("Out of office", () => {
});
async function saveAndWaitForResponse(page: Page, expectedStatusCode = 200) {
await submitAndWaitForResponse(page, "/api/trpc/viewer/outOfOfficeCreateOrUpdate?batch=1", {
await submitAndWaitForResponse(page, "/api/trpc/ooo/outOfOfficeCreateOrUpdate?batch=1", {
action: () => page.getByTestId("create-or-edit-entry-ooo-redirect").click(),
expectedStatusCode,
});
@@ -33,7 +33,7 @@ const DateOverrideList = ({
excludedDates?: string[];
userTimeFormat: number | null;
hour12: boolean;
travelSchedules?: RouterOutputs["viewer"]["getTravelSchedules"];
travelSchedules?: RouterOutputs["viewer"]["travelSchedules"]["get"];
weekStart?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
handleAvailabilityUpdate?: VoidFunction;
}) => {
@@ -122,7 +122,7 @@ export const CreateOrEditOutOfOfficeEntryModal = ({
}, document.querySelector('[role="dialog"]'));
const { data: outOfOfficeReasonList, isPending: isReasonListPending } =
trpc.viewer.outOfOfficeReasonList.useQuery();
trpc.viewer.ooo.outOfOfficeReasonList.useQuery();
const reasonList = (outOfOfficeReasonList || []).map((reason) => ({
label: `${reason.emoji} ${reason.userId === null ? t(reason.reason) : reason.reason}`,
value: reason.id,
@@ -158,7 +158,7 @@ export const CreateOrEditOutOfOfficeEntryModal = ({
const watchedTeamUserId = watch("toTeamUserId");
const watchForUserId = watch("forUserId");
const createOrEditOutOfOfficeEntry = trpc.viewer.outOfOfficeCreateOrUpdate.useMutation({
const createOrEditOutOfOfficeEntry = trpc.viewer.ooo.outOfOfficeCreateOrUpdate.useMutation({
onSuccess: () => {
showToast(
currentlyEditingOutOfOfficeEntry
@@ -166,7 +166,7 @@ export const CreateOrEditOutOfOfficeEntryModal = ({
: t("success_entry_created"),
"success"
);
utils.viewer.outOfOfficeEntriesList.invalidate();
utils.viewer.ooo.outOfOfficeEntriesList.invalidate();
closeModal();
},
onError: (error) => {
@@ -86,7 +86,7 @@ function OutOfOfficeEntriesListContent() {
const endDateRange = useFilterValue("dateRange", ZDateRangeFilterValue)?.data;
const { data, isPending, fetchNextPage, isFetching, refetch, hasNextPage } =
trpc.viewer.outOfOfficeEntriesList.useInfiniteQuery(
trpc.viewer.ooo.outOfOfficeEntriesList.useInfiniteQuery(
{
limit: 10,
fetchTeamMembersEntries: selectedTab === OutOfOfficeTab.TEAM,
@@ -319,7 +319,7 @@ function OutOfOfficeEntriesListContent() {
getFilteredRowModel: getFilteredRowModel(),
});
const deleteOutOfOfficeEntryMutation = trpc.viewer.outOfOfficeEntryDelete.useMutation({
const deleteOutOfOfficeEntryMutation = trpc.viewer.ooo.outOfOfficeEntryDelete.useMutation({
onSuccess: () => {
showToast(t("success_deleted_entry_out_of_office"), "success");
setDeletedEntry((previousValue) => previousValue + 1);
@@ -86,7 +86,7 @@ type AvailabilitySettingsProps = {
timeZone: string;
schedule: Availability[];
};
travelSchedules?: RouterOutputs["viewer"]["getTravelSchedules"];
travelSchedules?: RouterOutputs["viewer"]["travelSchedules"]["get"];
handleDelete: () => void;
allowDelete?: boolean;
allowSetToDefault?: boolean;
@@ -177,7 +177,7 @@ const DateOverride = ({
}: {
workingHours: WorkingHours[];
userTimeFormat: number | null;
travelSchedules?: RouterOutputs["viewer"]["getTravelSchedules"];
travelSchedules?: RouterOutputs["viewer"]["travelSchedules"]["get"];
weekStart: 0 | 1 | 2 | 3 | 4 | 5 | 6;
overridesModalClassNames?: string;
handleSubmit: (data: AvailabilityFormValues) => Promise<void>;
+2 -1
View File
@@ -17,6 +17,7 @@ export const ENDPOINTS = [
"i18n",
"insights",
"me",
"ooo",
"payments",
"public",
"timezones",
@@ -24,6 +25,7 @@ export const ENDPOINTS = [
"slots",
"teams",
"organizations",
"travelSchedules",
"users",
"viewer",
"webhook",
@@ -33,5 +35,4 @@ export const ENDPOINTS = [
"attributes",
"delegationCredential",
"routingForms",
"delegationCredential",
] as const;
@@ -10,9 +10,6 @@ import { ZGetCalVideoRecordingsInputSchema } from "./getCalVideoRecordings.schem
import { ZGetDownloadLinkOfCalVideoRecordingsInputSchema } from "./getDownloadLinkOfCalVideoRecordings.schema";
import { ZLocationOptionsInputSchema } from "./locationOptions.schema";
import { ZNoShowInputSchema } from "./markNoShow.schema";
import { ZOutOfOfficeInputSchema } from "./outOfOfficeCreateOrUpdate.schema";
import { ZOutOfOfficeEntriesListSchema } from "./outOfOfficeEntriesList.schema";
import { ZOutOfOfficeDelete } from "./outOfOfficeEntryDelete.schema";
import { teamsAndUserProfilesQuery } from "./procedures/teamsAndUserProfilesQuery";
import { ZRemoveNotificationsSubscriptionInputSchema } from "./removeNotificationsSubscription.schema";
import { ZRoutingFormOrderInputSchema } from "./routingFormOrder.schema";
@@ -40,12 +37,7 @@ type AppsRouterHandlerCache = {
getDownloadLinkOfCalVideoRecordings?: typeof import("./getDownloadLinkOfCalVideoRecordings.handler").getDownloadLinkOfCalVideoRecordingsHandler;
teamsAndUserProfilesQuery?: typeof import("./teamsAndUserProfilesQuery.handler").teamsAndUserProfilesQuery;
connectAndJoin?: typeof import("./connectAndJoin.handler").Handler;
outOfOfficeCreateOrUpdate?: typeof import("./outOfOfficeCreateOrUpdate.handler").outOfOfficeCreateOrUpdate;
outOfOfficeEntriesList?: typeof import("./outOfOfficeEntriesList.handler").outOfOfficeEntriesList;
outOfOfficeEntryDelete?: typeof import("./outOfOfficeEntryDelete.handler").outOfOfficeEntryDelete;
addSecondaryEmail?: typeof import("./addSecondaryEmail.handler").addSecondaryEmailHandler;
getTravelSchedules?: typeof import("./getTravelSchedules.handler").getTravelSchedulesHandler;
outOfOfficeReasonList?: typeof import("./outOfOfficeReasons.handler").outOfOfficeReasonList;
addNotificationsSubscription?: typeof import("./addNotificationsSubscription.handler").addNotificationsSubscriptionHandler;
removeNotificationsSubscription?: typeof import("./removeNotificationsSubscription.handler").removeNotificationsSubscriptionHandler;
markNoShow?: typeof import("./markNoShow.handler").markNoShow;
@@ -257,50 +249,6 @@ export const loggedInViewerRouter = router({
return UNSTABLE_HANDLER_CACHE.connectAndJoin({ ctx, input });
}),
outOfOfficeCreateOrUpdate: authedProcedure
.input(ZOutOfOfficeInputSchema)
.mutation(async ({ ctx, input }) => {
if (!UNSTABLE_HANDLER_CACHE.outOfOfficeCreateOrUpdate) {
UNSTABLE_HANDLER_CACHE.outOfOfficeCreateOrUpdate = (
await import("./outOfOfficeCreateOrUpdate.handler")
).outOfOfficeCreateOrUpdate;
}
// Unreachable code but required for type safety
if (!UNSTABLE_HANDLER_CACHE.outOfOfficeCreateOrUpdate) {
throw new Error("Failed to load handler");
}
return UNSTABLE_HANDLER_CACHE.outOfOfficeCreateOrUpdate({ ctx, input });
}),
outOfOfficeEntriesList: authedProcedure.input(ZOutOfOfficeEntriesListSchema).query(async (opts) => {
if (!UNSTABLE_HANDLER_CACHE.outOfOfficeEntriesList) {
UNSTABLE_HANDLER_CACHE.outOfOfficeEntriesList = (
await import("./outOfOfficeEntriesList.handler")
).outOfOfficeEntriesList;
}
// Unreachable code but required for type safety
if (!UNSTABLE_HANDLER_CACHE.outOfOfficeEntriesList) {
throw new Error("Failed to load handler");
}
return UNSTABLE_HANDLER_CACHE.outOfOfficeEntriesList(opts);
}),
outOfOfficeEntryDelete: authedProcedure.input(ZOutOfOfficeDelete).mutation(async ({ ctx, input }) => {
if (!UNSTABLE_HANDLER_CACHE.outOfOfficeEntryDelete) {
UNSTABLE_HANDLER_CACHE.outOfOfficeEntryDelete = (
await import("./outOfOfficeEntryDelete.handler")
).outOfOfficeEntryDelete;
}
// Unreachable code but required for type safety
if (!UNSTABLE_HANDLER_CACHE.outOfOfficeEntryDelete) {
throw new Error("Failed to load handler");
}
return UNSTABLE_HANDLER_CACHE.outOfOfficeEntryDelete({ ctx, input });
}),
addSecondaryEmail: authedProcedure.input(ZAddSecondaryEmailInputSchema).mutation(async ({ ctx, input }) => {
if (!UNSTABLE_HANDLER_CACHE.addSecondaryEmail) {
UNSTABLE_HANDLER_CACHE.addSecondaryEmail = (
@@ -315,34 +263,6 @@ export const loggedInViewerRouter = router({
return UNSTABLE_HANDLER_CACHE.addSecondaryEmail({ ctx, input });
}),
getTravelSchedules: authedProcedure.query(async ({ ctx }) => {
if (!UNSTABLE_HANDLER_CACHE.getTravelSchedules) {
UNSTABLE_HANDLER_CACHE.getTravelSchedules = (
await import("./getTravelSchedules.handler")
).getTravelSchedulesHandler;
}
// Unreachable code but required for type safety
if (!UNSTABLE_HANDLER_CACHE.getTravelSchedules) {
throw new Error("Failed to load handler");
}
return UNSTABLE_HANDLER_CACHE.getTravelSchedules({ ctx });
}),
outOfOfficeReasonList: authedProcedure.query(async () => {
if (!UNSTABLE_HANDLER_CACHE.outOfOfficeReasonList) {
UNSTABLE_HANDLER_CACHE.outOfOfficeReasonList = (
await import("./outOfOfficeReasons.handler")
).outOfOfficeReasonList;
}
// Unreachable code but required for type safety
if (!UNSTABLE_HANDLER_CACHE.outOfOfficeReasonList) {
throw new Error("Failed to load handler");
}
return UNSTABLE_HANDLER_CACHE.outOfOfficeReasonList();
}),
addNotificationsSubscription: authedProcedure
.input(ZAddNotificationsSubscriptionInputSchema)
.mutation(async ({ ctx, input }) => {
@@ -3,7 +3,7 @@ import { vi } from "vitest";
import { prisma } from "@calcom/prisma";
import { outOfOfficeCreateOrUpdate } from "../outOfOfficeCreateOrUpdate.handler";
import { outOfOfficeCreateOrUpdate } from "../ooo/outOfOfficeCreateOrUpdate.handler";
const prismaMock = {
outOfOfficeEntry: {
@@ -24,12 +24,14 @@ import { highPerfRouter } from "./highPerf/_router";
import { i18nRouter } from "./i18n/_router";
import { meRouter } from "./me/_router";
import { oAuthRouter } from "./oAuth/_router";
import { oooRouter } from "./ooo/_router";
import { viewerOrganizationsRouter } from "./organizations/_router";
import { paymentsRouter } from "./payments/_router";
import { routingFormsRouter } from "./routing-forms/_router";
import { slotsRouter } from "./slots/_router";
import { ssoRouter } from "./sso/_router";
import { viewerTeamsRouter } from "./teams/_router";
import { travelSchedulesRouter } from "./travelSchedules/_router";
import { webhookRouter } from "./webhook/_router";
import { workflowsRouter } from "./workflows/_router";
@@ -70,5 +72,7 @@ export const viewerRouter = mergeRouters(
attributes: attributesRouter,
highPerf: highPerfRouter,
routingForms: routingFormsRouter,
ooo: oooRouter,
travelSchedules: travelSchedulesRouter,
})
);
@@ -0,0 +1,26 @@
import authedProcedure from "../../../procedures/authedProcedure";
import { router } from "../../../trpc";
import { ZOutOfOfficeInputSchema } from "./outOfOfficeCreateOrUpdate.schema";
import { ZOutOfOfficeEntriesListSchema } from "./outOfOfficeEntriesList.schema";
import { ZOutOfOfficeDelete } from "./outOfOfficeEntryDelete.schema";
export const oooRouter = router({
outOfOfficeCreateOrUpdate: authedProcedure
.input(ZOutOfOfficeInputSchema)
.mutation(async ({ ctx, input }) => {
const handler = (await import("./outOfOfficeCreateOrUpdate.handler")).outOfOfficeCreateOrUpdate;
return handler({ ctx, input });
}),
outOfOfficeEntryDelete: authedProcedure.input(ZOutOfOfficeDelete).mutation(async ({ ctx, input }) => {
const handler = (await import("./outOfOfficeEntryDelete.handler")).outOfOfficeEntryDelete;
return handler({ ctx, input });
}),
outOfOfficeEntriesList: authedProcedure.input(ZOutOfOfficeEntriesListSchema).query(async (opts) => {
const handler = (await import("./outOfOfficeEntriesList.handler")).outOfOfficeEntriesList;
return handler(opts);
}),
outOfOfficeReasonList: authedProcedure.query(async () => {
const handler = (await import("./outOfOfficeReasons.handler")).outOfOfficeReasonList;
return handler();
}),
});
@@ -0,0 +1,9 @@
import authedProcedure from "../../../procedures/authedProcedure";
import { router } from "../../../trpc";
export const travelSchedulesRouter = router({
get: authedProcedure.query(async ({ ctx }) => {
const handler = (await import("./getTravelSchedules.handler")).getTravelSchedulesHandler;
return handler({ ctx });
}),
});