perf: Move /me stats to separate tRPC handler (#17206)
* perf: Move /me stats to separate tRPC handler * Update packages/trpc/server/routers/loggedInViewer/meStats.handler.ts Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> * Rename and skipping batch for myStats * Refactor of counting team events * Fixed type issues --------- Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
This commit is contained in:
co-authored by
Udit Takkar
parent
c197c33fd0
commit
7dbcb62724
@@ -28,11 +28,18 @@ const usePostHogHook: () => PostHogHook = isPostHogEnabled
|
||||
const usePostHog = () => {
|
||||
const posthog = usePostHogHook();
|
||||
const { data } = trpc.viewer.me.useQuery();
|
||||
const { data: statsData } = trpc.viewer.myStats.useQuery(undefined, {
|
||||
trpc: {
|
||||
context: {
|
||||
skipBatch: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
const { hasPaidPlan } = useHasPaidPlan();
|
||||
const { hasTeamPlan } = useHasTeamPlan();
|
||||
|
||||
const identify = async () => {
|
||||
if (!data) return;
|
||||
if (!data || !statsData) return;
|
||||
|
||||
posthog.identify(String(data.id), {
|
||||
distinctId: String(data.id),
|
||||
@@ -49,13 +56,13 @@ const usePostHog = () => {
|
||||
has_team_plan: hasTeamPlan,
|
||||
metadata: data?.metadata,
|
||||
completed_onboarding: data?.completedOnboarding,
|
||||
sum_of_bookings: data?.sumOfBookings,
|
||||
sum_of_calendars: data?.sumOfCalendars,
|
||||
sum_of_teams: data?.sumOfTeams,
|
||||
sum_of_bookings: statsData?.sumOfBookings,
|
||||
sum_of_calendars: statsData?.sumOfCalendars,
|
||||
sum_of_teams: statsData?.sumOfTeams,
|
||||
has_orgs_plan: !!data?.organizationId,
|
||||
organization: data?.organization?.slug,
|
||||
sum_of_event_types: data?.sumOfEventTypes,
|
||||
sum_of_team_event_types: data?.sumOfTeamEventTypes,
|
||||
sum_of_event_types: statsData?.sumOfEventTypes,
|
||||
sum_of_team_event_types: statsData?.sumOfTeamEventTypes,
|
||||
is_premium: data?.isPremium,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -26,11 +26,18 @@ const useIntercomHook = isInterComEnabled
|
||||
export const useIntercom = () => {
|
||||
const hookData = useIntercomHook();
|
||||
const { data } = trpc.viewer.me.useQuery();
|
||||
const { data: statsData } = trpc.viewer.myStats.useQuery(undefined, {
|
||||
trpc: {
|
||||
context: {
|
||||
skipBatch: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
const { hasPaidPlan } = useHasPaidPlan();
|
||||
const { hasTeamPlan } = useHasTeamPlan();
|
||||
|
||||
const boot = async () => {
|
||||
if (!data) return;
|
||||
if (!data || !statsData) return;
|
||||
let userHash;
|
||||
|
||||
const req = await fetch(`/api/intercom-hash`);
|
||||
@@ -61,13 +68,13 @@ export const useIntercom = () => {
|
||||
metadata: data?.metadata,
|
||||
completed_onboarding: data.completedOnboarding,
|
||||
is_logged_in: !!data,
|
||||
sum_of_bookings: data?.sumOfBookings,
|
||||
sum_of_calendars: data?.sumOfCalendars,
|
||||
sum_of_teams: data?.sumOfTeams,
|
||||
sum_of_bookings: statsData?.sumOfBookings,
|
||||
sum_of_calendars: statsData?.sumOfCalendars,
|
||||
sum_of_teams: statsData?.sumOfTeams,
|
||||
has_orgs_plan: !!data?.organizationId,
|
||||
organization: data?.organization?.slug,
|
||||
sum_of_event_types: data?.sumOfEventTypes,
|
||||
sum_of_team_event_types: data?.sumOfTeamEventTypes,
|
||||
sum_of_event_types: statsData?.sumOfEventTypes,
|
||||
sum_of_team_event_types: statsData?.sumOfTeamEventTypes,
|
||||
is_premium: data?.isPremium,
|
||||
},
|
||||
});
|
||||
@@ -104,13 +111,13 @@ export const useIntercom = () => {
|
||||
metadata: data?.metadata,
|
||||
completed_onboarding: data?.completedOnboarding,
|
||||
is_logged_in: !!data,
|
||||
sum_of_bookings: data?.sumOfBookings,
|
||||
sum_of_calendars: data?.sumOfCalendars,
|
||||
sum_of_teams: data?.sumOfTeams,
|
||||
sum_of_bookings: statsData?.sumOfBookings,
|
||||
sum_of_calendars: statsData?.sumOfCalendars,
|
||||
sum_of_teams: statsData?.sumOfTeams,
|
||||
has_orgs_plan: !!data?.organizationId,
|
||||
organization: data?.organization?.slug,
|
||||
sum_of_event_types: data?.sumOfEventTypes,
|
||||
sum_of_team_event_types: data?.sumOfTeamEventTypes,
|
||||
sum_of_event_types: statsData?.sumOfEventTypes,
|
||||
sum_of_team_event_types: statsData?.sumOfTeamEventTypes,
|
||||
is_premium: data?.isPremium,
|
||||
},
|
||||
});
|
||||
@@ -122,13 +129,22 @@ export const useIntercom = () => {
|
||||
export const useBootIntercom = () => {
|
||||
const { boot } = useIntercom();
|
||||
const { data: user } = trpc.viewer.me.useQuery();
|
||||
const { data: statsData } = trpc.viewer.myStats.useQuery(undefined, {
|
||||
trpc: {
|
||||
context: {
|
||||
skipBatch: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
useEffect(() => {
|
||||
// not using useMediaQuery as it toggles between true and false
|
||||
const showIntercom = localStorage.getItem("showIntercom");
|
||||
if (!isInterComEnabled || showIntercom === "false" || window.innerWidth <= 768 || !user) return;
|
||||
if (!isInterComEnabled || showIntercom === "false" || window.innerWidth <= 768 || !user || !statsData)
|
||||
return;
|
||||
|
||||
boot();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [user]);
|
||||
}, [user, statsData]);
|
||||
};
|
||||
|
||||
export default useIntercom;
|
||||
|
||||
@@ -16,6 +16,7 @@ import { ZLocationOptionsInputSchema } from "./locationOptions.schema";
|
||||
import { ZNoShowInputSchema } from "./markNoShow.schema";
|
||||
import { ZOutOfOfficeInputSchema, ZOutOfOfficeDelete } from "./outOfOffice.schema";
|
||||
import { me } from "./procedures/me";
|
||||
import { myStats } from "./procedures/myStats";
|
||||
import { platformMe } from "./procedures/platformMe";
|
||||
import { teamsAndUserProfilesQuery } from "./procedures/teamsAndUserProfilesQuery";
|
||||
import { ZRemoveNotificationsSubscriptionInputSchema } from "./removeNotificationsSubscription.schema";
|
||||
@@ -32,6 +33,7 @@ const namespaced = (s: string) => `${NAMESPACE}.${s}`;
|
||||
|
||||
type AppsRouterHandlerCache = {
|
||||
me?: typeof import("./me.handler").meHandler;
|
||||
myStats?: typeof import("./myStats.handler").myStatsHandler;
|
||||
platformMe?: typeof import("./platformMe.handler").platformMeHandler;
|
||||
shouldVerifyEmail?: typeof import("./shouldVerifyEmail.handler").shouldVerifyEmailHandler;
|
||||
deleteMe?: typeof import("./deleteMe.handler").deleteMeHandler;
|
||||
@@ -72,6 +74,7 @@ const UNSTABLE_HANDLER_CACHE: AppsRouterHandlerCache = {};
|
||||
|
||||
export const loggedInViewerRouter = router({
|
||||
me,
|
||||
myStats,
|
||||
platformMe,
|
||||
|
||||
deleteMe: authedProcedure.input(ZDeleteMeInputSchema).mutation(async ({ ctx, input }) => {
|
||||
|
||||
@@ -72,36 +72,6 @@ export const meHandler = async ({ ctx, input }: MeOptions) => {
|
||||
identityProviderEmail = account?.providerEmail || "";
|
||||
}
|
||||
|
||||
const additionalUserInfo = await prisma.user.findFirst({
|
||||
where: {
|
||||
id: user.id,
|
||||
},
|
||||
select: {
|
||||
bookings: {
|
||||
select: { id: true },
|
||||
},
|
||||
selectedCalendars: true,
|
||||
teams: {
|
||||
select: {
|
||||
team: {
|
||||
select: {
|
||||
id: true,
|
||||
eventTypes: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
eventTypes: {
|
||||
select: { id: true },
|
||||
},
|
||||
},
|
||||
});
|
||||
let sumOfTeamEventTypes = 0;
|
||||
for (const team of additionalUserInfo?.teams || []) {
|
||||
for (const _eventType of team.team.eventTypes) {
|
||||
sumOfTeamEventTypes++;
|
||||
}
|
||||
}
|
||||
const userMetadataPrased = userMetadata.parse(user.metadata);
|
||||
|
||||
// Destructuring here only makes it more illegible
|
||||
@@ -159,12 +129,7 @@ export const meHandler = async ({ ctx, input }: MeOptions) => {
|
||||
receiveMonthlyDigestEmail: user.receiveMonthlyDigestEmail,
|
||||
...profileData,
|
||||
secondaryEmails,
|
||||
sumOfBookings: additionalUserInfo?.bookings.length,
|
||||
sumOfCalendars: additionalUserInfo?.selectedCalendars.length,
|
||||
sumOfTeams: additionalUserInfo?.teams.length,
|
||||
sumOfEventTypes: additionalUserInfo?.eventTypes.length,
|
||||
isPremium: userMetadataPrased?.isPremium,
|
||||
sumOfTeamEventTypes,
|
||||
...(passwordAdded ? { passwordAdded } : {}),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import type { Session } from "next-auth";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { TrpcSessionUser } from "@calcom/trpc/server/trpc";
|
||||
|
||||
type MyStatsOptions = {
|
||||
ctx: {
|
||||
user: NonNullable<TrpcSessionUser>;
|
||||
session: Session;
|
||||
};
|
||||
};
|
||||
|
||||
export const myStatsHandler = async ({ ctx }: MyStatsOptions) => {
|
||||
const { user: sessionUser } = ctx;
|
||||
|
||||
const additionalUserInfo = await prisma.user.findFirst({
|
||||
where: {
|
||||
id: sessionUser.id,
|
||||
},
|
||||
select: {
|
||||
_count: {
|
||||
select: {
|
||||
bookings: true,
|
||||
selectedCalendars: true,
|
||||
teams: true,
|
||||
eventTypes: true,
|
||||
},
|
||||
},
|
||||
teams: {
|
||||
select: {
|
||||
team: {
|
||||
select: {
|
||||
eventTypes: {
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
const sumOfTeamEventTypes = additionalUserInfo?.teams.reduce(
|
||||
(sum, team) => sum + team.team.eventTypes.length,
|
||||
0
|
||||
);
|
||||
|
||||
return {
|
||||
id: sessionUser.id,
|
||||
sumOfBookings: additionalUserInfo?._count.bookings,
|
||||
sumOfCalendars: additionalUserInfo?._count.selectedCalendars,
|
||||
sumOfTeams: additionalUserInfo?._count.teams,
|
||||
sumOfEventTypes: additionalUserInfo?._count.eventTypes,
|
||||
sumOfTeamEventTypes,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export {};
|
||||
@@ -0,0 +1,7 @@
|
||||
import authedProcedure from "../../../procedures/authedProcedure";
|
||||
|
||||
export const myStats = authedProcedure.query(async ({ ctx, input }) => {
|
||||
const handler = (await import("../myStats.handler")).myStatsHandler;
|
||||
|
||||
return handler({ ctx });
|
||||
});
|
||||
Reference in New Issue
Block a user