From 4fe69b58646a32a6b87544636f2e55d935578bd1 Mon Sep 17 00:00:00 2001 From: Keith Williams Date: Tue, 27 Jun 2023 00:32:05 +0200 Subject: [PATCH] chore: Removing the calendar-cache because of perf issues (#9808) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Efraín Rochín --- .../calendar-cache/[month]/[orgSlug].tsx | 1 - .../[user]/calendar-cache/[month]/index.tsx | 69 ------------------- apps/web/pages/api/availability/calendar.ts | 5 -- apps/web/pages/api/integrations/[...args].ts | 7 -- .../revalidate-calendar-cache/[username].ts | 27 -------- packages/core/CalendarManager.ts | 63 ++--------------- .../lib/server/revalidateCalendarCache.ts | 18 ----- .../deleteCredential.handler.ts | 5 -- 8 files changed, 5 insertions(+), 190 deletions(-) delete mode 100644 apps/web/pages/[user]/calendar-cache/[month]/[orgSlug].tsx delete mode 100644 apps/web/pages/[user]/calendar-cache/[month]/index.tsx delete mode 100644 apps/web/pages/api/revalidate-calendar-cache/[username].ts delete mode 100644 packages/lib/server/revalidateCalendarCache.ts diff --git a/apps/web/pages/[user]/calendar-cache/[month]/[orgSlug].tsx b/apps/web/pages/[user]/calendar-cache/[month]/[orgSlug].tsx deleted file mode 100644 index 647d6f6347..0000000000 --- a/apps/web/pages/[user]/calendar-cache/[month]/[orgSlug].tsx +++ /dev/null @@ -1 +0,0 @@ -export { getStaticProps, getStaticPaths, default } from "./index"; diff --git a/apps/web/pages/[user]/calendar-cache/[month]/index.tsx b/apps/web/pages/[user]/calendar-cache/[month]/index.tsx deleted file mode 100644 index 6e4dbaa34b..0000000000 --- a/apps/web/pages/[user]/calendar-cache/[month]/index.tsx +++ /dev/null @@ -1,69 +0,0 @@ -/** - * This page is empty for the user, it is used only to take advantage of the - * caching system that NextJS uses SSG pages. - * TODO: Redirect to user profile on browser - */ -import type { GetStaticPaths, GetStaticProps, InferGetStaticPropsType } from "next"; -import { z } from "zod"; - -import getCalendarsEvents from "@calcom/core/getCalendarsEvents"; -import dayjs from "@calcom/dayjs"; -import prisma from "@calcom/prisma"; - -const paramsSchema = z.object({ user: z.string(), month: z.string() }); -export const getStaticProps: GetStaticProps< - { results: Awaited> }, - { user: string } -> = async (context) => { - const { user: username, month } = paramsSchema.parse(context.params); - const userWithCredentials = await prisma.user.findFirst({ - where: { - username, - }, - select: { - id: true, - username: true, - credentials: true, - selectedCalendars: true, - }, - }); - // Subtract 11 hours from the start date to avoid problems in UTC- time zones. - const startDate = dayjs.utc(month, "YYYY-MM").startOf("day").subtract(11, "hours").format(); - // Add 14 hours from the start date to avoid problems in UTC+ time zones. - const endDate = dayjs.utc(month, "YYYY-MM").endOf("month").add(14, "hours").format(); - try { - const results = userWithCredentials?.credentials - ? await getCalendarsEvents( - userWithCredentials?.credentials, - startDate, - endDate, - userWithCredentials?.selectedCalendars - ) - : []; - - return { - props: { results, date: new Date().toISOString() }, - revalidate: 1, - }; - } catch (error) { - let message = "Unknown error while fetching calendar"; - if (error instanceof Error) message = error.message; - console.error(error, message); - return { - props: { results: [], date: new Date().toISOString(), message }, - revalidate: 1, - }; - } -}; - -export const getStaticPaths: GetStaticPaths = () => { - return { - paths: [], - fallback: "blocking", - }; -}; -type Props = InferGetStaticPropsType; -const CalendarCache = (props: Props) => - process.env.NODE_ENV === "development" ?
{JSON.stringify(props, null, "  ")}
:
; - -export default CalendarCache; diff --git a/apps/web/pages/api/availability/calendar.ts b/apps/web/pages/api/availability/calendar.ts index 36dbf6038b..c8ebfe3d5e 100644 --- a/apps/web/pages/api/availability/calendar.ts +++ b/apps/web/pages/api/availability/calendar.ts @@ -4,7 +4,6 @@ import { z } from "zod"; import { getCalendarCredentials, getConnectedCalendars } from "@calcom/core/CalendarManager"; import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; import notEmpty from "@calcom/lib/notEmpty"; -import { revalidateCalendarCache } from "@calcom/lib/server/revalidateCalendarCache"; import prisma from "@calcom/prisma"; const selectedCalendarSelectSchema = z.object({ @@ -73,10 +72,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) res.status(200).json({ message: "Calendar Selection Saved" }); } - if (["DELETE", "POST"].includes(req.method)) { - await revalidateCalendarCache(res.revalidate, `${session?.user?.username}`); - } - if (req.method === "GET") { const selectedCalendarIds = await prisma.selectedCalendar.findMany({ where: { diff --git a/apps/web/pages/api/integrations/[...args].ts b/apps/web/pages/api/integrations/[...args].ts index 5b789e8ffd..9ecd9e1b53 100644 --- a/apps/web/pages/api/integrations/[...args].ts +++ b/apps/web/pages/api/integrations/[...args].ts @@ -5,7 +5,6 @@ import getInstalledAppPath from "@calcom/app-store/_utils/getInstalledAppPath"; import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; import { deriveAppDictKeyFromType } from "@calcom/lib/deriveAppDictKeyFromType"; import { HttpError } from "@calcom/lib/http-error"; -import { revalidateCalendarCache } from "@calcom/lib/server/revalidateCalendarCache"; import prisma from "@calcom/prisma"; import type { AppDeclarativeHandler, AppHandler } from "@calcom/types/AppHandler"; @@ -62,14 +61,8 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { if (typeof handler === "function") { await handler(req, res); - if (appName.includes("calendar") && req.session?.user?.username) { - await revalidateCalendarCache(res.revalidate, req.session?.user?.username); - } } else { await defaultIntegrationAddHandler({ user: req.session?.user, ...handler }); - if (handler.appType.includes("calendar") && req.session?.user?.username) { - await revalidateCalendarCache(res.revalidate, req.session?.user?.username); - } redirectUrl = handler.redirect?.url || getInstalledAppPath(handler); res.json({ url: redirectUrl, newTab: handler.redirect?.newTab }); } diff --git a/apps/web/pages/api/revalidate-calendar-cache/[username].ts b/apps/web/pages/api/revalidate-calendar-cache/[username].ts deleted file mode 100644 index 3b42b64b46..0000000000 --- a/apps/web/pages/api/revalidate-calendar-cache/[username].ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { NextApiRequest, NextApiResponse } from "next"; -import { z } from "zod"; - -import { revalidateCalendarCache } from "@calcom/lib/server/revalidateCalendarCache"; - -const querySchema = z.object({ - username: z.string(), -}); - -/** - * This endpoint revalidates users calendar cache several months ahead - * Can be used as webhook - * @param req - * @param res - * @returns - */ - -export default async function handler(req: NextApiRequest, res: NextApiResponse) { - const { username } = querySchema.parse(req.query); - try { - await revalidateCalendarCache(res.revalidate, username); - - return res.status(200).json({ revalidated: true }); - } catch (err) { - return res.status(500).send({ message: "Error revalidating" }); - } -} diff --git a/packages/core/CalendarManager.ts b/packages/core/CalendarManager.ts index fe5fd7dc08..1ae89be41a 100644 --- a/packages/core/CalendarManager.ts +++ b/packages/core/CalendarManager.ts @@ -1,12 +1,10 @@ import type { SelectedCalendar } from "@prisma/client"; import { sortBy } from "lodash"; -import * as process from "process"; import { getCalendar } from "@calcom/app-store/_utils/getCalendar"; import getApps from "@calcom/app-store/utils"; import dayjs from "@calcom/dayjs"; import { getUid } from "@calcom/lib/CalEventParser"; -import { WEBAPP_URL } from "@calcom/lib/constants"; import logger from "@calcom/lib/logger"; import { performance } from "@calcom/lib/server/perfObserver"; import type { @@ -21,7 +19,6 @@ import type { EventResult } from "@calcom/types/EventManager"; import getCalendarsEvents from "./getCalendarsEvents"; const log = logger.getChildLogger({ prefix: ["CalendarManager"] }); -let coldStart = true; export const getCalendarCredentials = (credentials: Array) => { const calendarCredentials = getApps(credentials) @@ -179,35 +176,6 @@ export const getCachedResults = async ( return awaitedResults as any; }; -/** - * This function fetch the json file that NextJS generates and uses to hydrate the static page on browser. - * If for some reason NextJS still doesn't generate this file, it will wait until it finishes generating it. - * On development environment it takes a long time because Next must compiles the whole page. - * @param username - * @param month A string representing year and month using YYYY-MM format - * @param organizationSlug A string with the organization slug - */ -const getNextCache = async ( - username: string, - month: string, - organizationSlug?: string | null -): Promise => { - let localCache: EventBusyDate[][] = []; - const { NODE_ENV } = process.env; - const cacheDir = `${NODE_ENV === "development" ? NODE_ENV : process.env.BUILD_ID}`; - const baseUrl = `${WEBAPP_URL}/_next/data/${cacheDir}/en`; - const url = organizationSlug - ? `${baseUrl}/${username}/calendar-cache/${month}/${organizationSlug}.json?user=${username}&month=${month}&orgSlug=${organizationSlug}` - : `${baseUrl}/${username}/calendar-cache/${month}.json?user=${username}&month=${month}`; - try { - localCache = await fetch(url) - .then((r) => r.json()) - .then((json) => json?.pageProps?.results); - } catch (e) { - log.warn(url, e); - } - return localCache; -}; /** * Get months between given dates * @returns ["2023-04", "2024-05"] @@ -225,11 +193,6 @@ const getMonths = (dateFrom: string, dateTo: string): string[] => { return months; }; -const createCalendarCachePage = (username: string, month: string, organizationSlug?: string | null): void => { - // No need to wait for this, the purpose is to force re-validation every second as indicated - // in page getStaticProps. - fetch(`${WEBAPP_URL}/${username}/calendar-cache/${month}/${organizationSlug}`).catch(console.log); -}; export const getBusyCalendarTimes = async ( username: string, withCredentials: CredentialPayload[], @@ -241,30 +204,14 @@ export const getBusyCalendarTimes = async ( let results: EventBusyDate[][] = []; const months = getMonths(dateFrom, dateTo); try { - if (coldStart) { - // Subtract 11 hours from the start date to avoid problems in UTC- time zones. - const startDate = dayjs(dateFrom).subtract(11, "hours").format(); - // Add 14 hours from the start date to avoid problems in UTC+ time zones. - const endDate = dayjs(dateTo).endOf("month").add(14, "hours").format(); - results = await getCalendarsEvents(withCredentials, startDate, endDate, selectedCalendars); - console.log("Generating calendar cache in background"); - // on cold start the calendar cache page generated in the background - Promise.all(months.map((month) => createCalendarCachePage(username, month, organizationSlug))); - } else { - if (months.length === 1) { - results = await getNextCache(username, dayjs(dateFrom).format("YYYY-MM"), organizationSlug); - } else { - // if dateFrom and dateTo is from different months get cache by each month - const data: EventBusyDate[][][] = await Promise.all( - months.map((month) => getNextCache(username, month, organizationSlug)) - ); - results = data.flat(1); - } - } + // Subtract 11 hours from the start date to avoid problems in UTC- time zones. + const startDate = dayjs(dateFrom).subtract(11, "hours").format(); + // Add 14 hours from the start date to avoid problems in UTC+ time zones. + const endDate = dayjs(dateTo).endOf("month").add(14, "hours").format(); + results = await getCalendarsEvents(withCredentials, startDate, endDate, selectedCalendars); } catch (e) { logger.warn(e); } - coldStart = false; return results.reduce((acc, availability) => acc.concat(availability), []); }; diff --git a/packages/lib/server/revalidateCalendarCache.ts b/packages/lib/server/revalidateCalendarCache.ts deleted file mode 100644 index b8dd68e088..0000000000 --- a/packages/lib/server/revalidateCalendarCache.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { NextApiResponse } from "next"; - -import dayjs from "@calcom/dayjs"; - -export const revalidateCalendarCache = ( - revalidate: NextApiResponse["revalidate"], - username: string, - monthsToRevalidate = 4 -): Promise => { - return Promise.all( - new Array(monthsToRevalidate).fill(0).map((_, index): Promise => { - const date = dayjs().add(index, "month").format("YYYY-MM"); - const url = `/${username}/calendar-cache/${date}`; - console.log("revalidating", url); - return revalidate(url); - }) - ); -}; diff --git a/packages/trpc/server/routers/loggedInViewer/deleteCredential.handler.ts b/packages/trpc/server/routers/loggedInViewer/deleteCredential.handler.ts index 9b392ecfb2..0de95dbd76 100644 --- a/packages/trpc/server/routers/loggedInViewer/deleteCredential.handler.ts +++ b/packages/trpc/server/routers/loggedInViewer/deleteCredential.handler.ts @@ -5,7 +5,6 @@ import { DailyLocationType } from "@calcom/core/location"; import { sendCancelledEmails } from "@calcom/emails"; import { getCalEventResponses } from "@calcom/features/bookings/lib/getCalEventResponses"; import { isPrismaObjOrUndefined, parseRecurringEvent } from "@calcom/lib"; -import { WEBAPP_URL } from "@calcom/lib/constants"; import getPaymentAppData from "@calcom/lib/getPaymentAppData"; import { deletePayment } from "@calcom/lib/payment/deletePayment"; import { getTranslation } from "@calcom/lib/server/i18n"; @@ -344,8 +343,4 @@ export const deleteCredentialHandler = async ({ ctx, input }: DeleteCredentialOp id: id, }, }); - // Revalidate user calendar cache. - if (credential.app?.slug.includes("calendar")) { - await fetch(`${WEBAPP_URL}/api/revalidate-calendar-cache/${ctx?.user?.username}`); - } };