Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate SSG Page used as cache for user's third-party calendar #6775

Merged
merged 79 commits into from Feb 13, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
902279c
Generate SSG Page used as cache for user's third-party calendars
roae Jan 29, 2023
750a4c2
remove next-build-id dependency
roae Feb 2, 2023
46b3ffe
yarn.lock from main
roae Feb 2, 2023
d1fe6d1
Merge branch 'main' into pr/6775
zomars Feb 2, 2023
77d8405
add support to get cached data from multiple months
roae Feb 3, 2023
1f85dae
Update apps/web/pages/[user]/calendar-cache/[month].tsx
roae Feb 3, 2023
76eaf89
Update apps/web/pages/[user]/calendar-cache/[month].tsx
roae Feb 3, 2023
eb94f0c
Update packages/core/CalendarManager.ts
roae Feb 3, 2023
12a9e46
Merge branch 'event_page_performance' of https://github.com/roae/cal.…
roae Feb 3, 2023
c75ac14
Add api endpoint that revalidates the current month and 3 more ahead
roae Feb 8, 2023
8dc5d47
Revalidate calendar cache when user connect new calendar.
roae Feb 8, 2023
a0c81eb
Revalidate calendar cache when user remove a calendar.
roae Feb 8, 2023
fb2412b
Revalidate calendar cache when user change de selected calendars-
roae Feb 8, 2023
2a386e4
Change revalidateCalendarCache function to @calcom/lib/server
roae Feb 9, 2023
ae73393
Remove the memory cache from getCachedResults
roae Feb 9, 2023
0d39452
refetch availability slots in a 3 seconds interval
roae Feb 9, 2023
34da780
Hotfix: Event Name (#6863) (#6864)
hariombalhara Feb 3, 2023
fdfb8a1
feat: make key unique (#6861)
G3root Feb 3, 2023
6bfa6e1
version 2.5.9 (#6868)
Hybes Feb 3, 2023
fbc5d2c
Use Calendar component view=day for drop-in replacement troubleshoote…
emrysal Feb 3, 2023
19b595b
lots of small changes by me and ciaran (#6871)
PeerRich Feb 3, 2023
8202c2c
Hotfix: For old Plausible installs enabled in an EventType, give a de…
hariombalhara Feb 3, 2023
6cab0e7
fix: filter booking in upcoming (#6406)
Udit-takkar Feb 3, 2023
f1b1afb
fix workflows when duplicating event types (#6873)
CarinaWolli Feb 4, 2023
5805e78
fix: get location url from metadata (#6774)
Udit-takkar Feb 5, 2023
dd9f013
Updates heroku deployment template (#6879)
alishaz-polymath Feb 5, 2023
8987222
Hide button (#6895)
sean-brydon Feb 5, 2023
1d27b10
Fixed some inconsistencies within single event type page (#6887)
emrysal Feb 5, 2023
5719700
fix(date-overrides): alignment of edit & delete btns (#6892)
saideepesh000 Feb 6, 2023
f7fbfec
When unchecking the common schedule, schedule should be nulled (#6898)
emrysal Feb 6, 2023
6e13ade
theme for storybook
PeerRich Feb 6, 2023
5b7125b
nit border change (#6899)
PeerRich Feb 6, 2023
0311771
fix: metadata not saved while creating a booking. (#6866)
G3root Feb 6, 2023
826bf55
Beginning of Strict CSP Compliance (#6841)
hariombalhara Feb 6, 2023
52c6ab4
v2.5.10
zomars Feb 6, 2023
8716146
fix: add req.headers (#6921)
Udit-takkar Feb 7, 2023
e51e746
add-console-vars (#6929)
alannnc Feb 7, 2023
fe0c2a5
Admin Wizard Choose License (#6574)
leog Feb 8, 2023
a96da8c
added two new tips (#6915)
PeerRich Feb 8, 2023
67afb4b
[CAL-488] Timezone selection has a weird double dropdown (#6851)
gitstart-calcom Feb 8, 2023
e3ae0c5
fix: color and line height of icon (#6913)
Udit-takkar Feb 8, 2023
acd0902
fix: use destination calendar email (#6886)
Udit-takkar Feb 8, 2023
098221b
fix: dropdown title in bookings page (#6924)
joe-shajan Feb 8, 2023
4533f20
fixes the broken max size of members on teams page (#6926)
Hybes Feb 8, 2023
7428667
fix: display provider name instead of url (#6914)
Udit-takkar Feb 8, 2023
afea3a9
fix: add sortByLabel (#6797)
Udit-takkar Feb 8, 2023
df8080c
Email Variables Bug (#6943)
Udit-takkar Feb 8, 2023
0d62be0
Remove _subject translations for zh-CN, needs retranslation
emrysal Feb 8, 2023
085a449
minor timezone-select improvements (#6944)
PeerRich Feb 8, 2023
5bb5ac8
Give trackingId a default value because if user doesnt interact with …
hariombalhara Feb 8, 2023
d274d7d
Block /auth/:path, nothing else. (#6949)
emrysal Feb 8, 2023
ecf91b8
fix start icon in button (#6950)
CarinaWolli Feb 8, 2023
f7523b7
Fixes localisation of {EVENT_DATE} in workflows (#6907)
CarinaWolli Feb 8, 2023
01db31c
Allow account linking for Google and SAML providers (#6874)
deepakprabhakara Feb 8, 2023
ee0dbe3
feat/payment-service-6438-cal-767 (#6677)
alannnc Feb 8, 2023
01c8b24
Small UI fixes for seats & destination calendars (#6859)
joeauyeung Feb 8, 2023
4ba61e4
fix: use typedquery hook in duplicate dialog (#6730)
Udit-takkar Feb 8, 2023
7195f5a
Fixing admin wizard step done (#6954)
leog Feb 8, 2023
2ef73d3
Feature/maintenance mode (#6930)
emrysal Feb 8, 2023
4bf89d6
Update package.json
zomars Feb 8, 2023
be77464
I18N Caching (#6823)
AaronPresley Feb 9, 2023
f35d52f
feat: return `x-vercel-ip-timezone` in headers (#6849)
G3root Feb 9, 2023
6199c86
Merge branch 'main' into pr/6775
zomars Feb 9, 2023
33dce23
Merge branch 'main' into pr/6775
zomars Feb 9, 2023
5b219a5
log the json url for testing
roae Feb 9, 2023
b572591
use WEBAPP_URL constant instead env.NEXT_PUBLIC_WEBAPP_URL
roae Feb 9, 2023
d80f7fb
remove the commented selectedCalendars var, it is not necessary
roae Feb 9, 2023
bfc930a
Caching fixes
zomars Feb 10, 2023
d73aaf0
Separate selectedDate slots from month slots
roae Feb 10, 2023
b732f0e
Update [trpc].ts
zomars Feb 10, 2023
67cae24
Log headers
zomars Feb 10, 2023
e93f808
Update [trpc].ts
zomars Feb 10, 2023
d5ecdaa
Update package.json
zomars Feb 10, 2023
17c374e
Merge branch 'main' into pr/6775
zomars Feb 10, 2023
56f32d0
Fixes/trpc headers (#7045)
zomars Feb 10, 2023
418306d
Merge branch 'main' into pr/6775
zomars Feb 10, 2023
5da47dd
Prevent refetching day on month switch
zomars Feb 10, 2023
33a1584
Merge branch 'calcom:main' into event_page_performance
roae Feb 13, 2023
0f13639
Skeleton fixes
zomars Feb 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 3 additions & 2 deletions apps/web/next.config.js
Expand Up @@ -76,7 +76,6 @@ if (process.env.ANALYZE === "true") {

plugins.push(withTM);
plugins.push(withAxiom);

/** @type {import("next").NextConfig} */
const nextConfig = {
i18n,
Expand All @@ -98,7 +97,7 @@ const nextConfig = {
images: {
unoptimized: true,
},
webpack: (config) => {
webpack: (config, { webpack, buildId }) => {
config.plugins.push(
new CopyWebpackPlugin({
patterns: [
Expand All @@ -120,6 +119,8 @@ const nextConfig = {
})
);

config.plugins.push(new webpack.DefinePlugin({ "process.env.BUILD_ID": JSON.stringify(buildId) }));

config.resolve.fallback = {
...config.resolve.fallback, // if you miss it, all the other options in fallback, specified
// by next.js will be dropped. Doesn't make much sense, but how it is
Expand Down
54 changes: 54 additions & 0 deletions apps/web/pages/[user]/calendar-cache/[month].tsx
@@ -0,0 +1,54 @@
/**
* 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 { GetStaticPaths, GetStaticProps } from "next";
import { z } from "zod";

import { getCachedResults } from "@calcom/core";
import dayjs from "@calcom/dayjs";
import prisma from "@calcom/prisma";

type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;

const CalendarCache = () => <div />;
roae marked this conversation as resolved.
Show resolved Hide resolved

const paramsSchema = z.object({ user: z.string(), month: z.string() });
export const getStaticProps: GetStaticProps<
{ results: UnwrapPromise<ReturnType<typeof getCachedResults>> },
roae marked this conversation as resolved.
Show resolved Hide resolved
{ user: string }
> = async (context) => {
const { user: username, month } = paramsSchema.parse(context.params);
const user = await prisma.user.findUnique({
where: {
username,
},
select: {
id: true,
username: true,
credentials: true,
selectedCalendars: true,
},
});
const startDate = (
dayjs(month, "YYYY-MM").isSame(dayjs(), "month") ? dayjs() : dayjs(month, "YYYY-MM")
).startOf("day");
const endDate = startDate.endOf("month");
const results = user?.credentials
? await getCachedResults(user?.credentials, startDate.format(), endDate.format(), user?.selectedCalendars)
: [];
return {
props: { results, date: new Date().toISOString() },
revalidate: 1,
};
};

export const getStaticPaths: GetStaticPaths = () => {
return {
paths: [],
fallback: "blocking",
};
};

export default CalendarCache;
48 changes: 36 additions & 12 deletions packages/core/CalendarManager.ts
Expand Up @@ -2,9 +2,11 @@ import { SelectedCalendar } from "@prisma/client";
import { createHash } from "crypto";
import _ from "lodash";
import cache from "memory-cache";
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 logger from "@calcom/lib/logger";
import { performance } from "@calcom/lib/server/perfObserver";
Expand Down Expand Up @@ -115,15 +117,15 @@ const cleanIntegrationKeys = (

const CACHING_TIME = 30_000; // 30 seconds

const getCachedResults = async (
// here I will fetch the page json file.
export const getCachedResults = async (
withCredentials: CredentialPayload[],
dateFrom: string,
dateTo: string,
selectedCalendars: SelectedCalendar[]
) => {
): Promise<EventBusyDate[][]> => {
const calendarCredentials = withCredentials.filter((credential) => credential.type.endsWith("_calendar"));
const calendars = calendarCredentials.map((credential) => getCalendar(credential));

performance.mark("getBusyCalendarTimesStart");
const results = calendars.map(async (c, i) => {
/** Filter out nulls */
Expand Down Expand Up @@ -173,18 +175,40 @@ const getCachedResults = async (
return awaitedResults;
};

/**
* This function fetch the json file that NextJS generates and uses to hydrate the static page on browser.
zomars marked this conversation as resolved.
Show resolved Hide resolved
* If for some reason NextJS still doesn't generate this file, it will wait until it finishes generating it.
* @param username
* @param month
roae marked this conversation as resolved.
Show resolved Hide resolved
*/
const getNextCache = async (username: string, month: string): Promise<EventBusyDate[][]> => {
let localCache: EventBusyDate[][] = [];
try {
const { NEXT_PUBLIC_WEBAPP_URL, NODE_ENV } = process.env;
const cacheDir = `${NODE_ENV === "development" ? NODE_ENV : process.env.BUILD_ID}`;
const baseUrl = `${NEXT_PUBLIC_WEBAPP_URL}/_next/data/${cacheDir}/en`;
localCache = await fetch(
`${baseUrl}/${username}/calendar-cache/${month}.json?user=${username}&month=${month}`
)
.then((r) => r.json())
.then((json) => json?.pageProps?.results);
} catch (e) {
log.warn(e);
}
return localCache;
};

export const getBusyCalendarTimes = async (
username: string,
withCredentials: CredentialPayload[],
dateFrom: string,
dateTo: string,
selectedCalendars: SelectedCalendar[]
dateFrom: string
// TODO: Make sure it's necessary
// selectedCalendars: SelectedCalendar[]
) => {
let results: EventBusyDate[][] = [];
try {
results = await getCachedResults(withCredentials, dateFrom, dateTo, selectedCalendars);
} catch (error) {
log.warn(error);
}
/* Fetch the cached JSON file on development environment it takes a long time because Next must compiles the whole
page and reduces the cache time,*/
const results: EventBusyDate[][] = await getNextCache(username, dayjs(dateFrom).format("YYYY-MM"));

return results.reduce((acc, availability) => acc.concat(availability), []);
};

Expand Down
11 changes: 9 additions & 2 deletions packages/core/getBusyTimes.ts
Expand Up @@ -10,6 +10,7 @@ import type { EventBusyDetails } from "@calcom/types/Calendar";
export async function getBusyTimes(params: {
credentials: Credential[];
userId: number;
username: string;
eventTypeId?: number;
startTime: string;
beforeEventBuffer?: number;
Expand All @@ -20,10 +21,11 @@ export async function getBusyTimes(params: {
const {
credentials,
userId,
username,
eventTypeId,
startTime,
endTime,
selectedCalendars,
//selectedCalendars,
beforeEventBuffer,
afterEventBuffer,
} = params;
Expand Down Expand Up @@ -75,7 +77,12 @@ export async function getBusyTimes(params: {
performance.mark("prismaBookingGetEnd");
performance.measure(`prisma booking get took $1'`, "prismaBookingGetStart", "prismaBookingGetEnd");
if (credentials?.length > 0) {
const calendarBusyTimes = await getBusyCalendarTimes(credentials, startTime, endTime, selectedCalendars);
const calendarBusyTimes = await getBusyCalendarTimes(
username,
credentials,
startTime
// selectedCalendars
);
busyTimes.push(
...calendarBusyTimes.map((value) => ({
...value,
Expand Down
1 change: 1 addition & 0 deletions packages/core/getUserAvailability.ts
Expand Up @@ -145,6 +145,7 @@ export async function getUserAvailability(
endTime: dateTo.toISOString(),
eventTypeId,
userId: currentUser.id,
username: `${currentUser.username}`,
selectedCalendars,
beforeEventBuffer,
afterEventBuffer,
Expand Down
1 change: 1 addition & 0 deletions turbo.json
Expand Up @@ -236,6 +236,7 @@
"$NEXTAUTH_SECRET",
"$NEXTAUTH_URL",
"$NODE_ENV",
"$BUILD_ID",
"$PLAYWRIGHT_HEADLESS",
"$PLAYWRIGHT_TEST_BASE_URL",
"$PRISMA_FIELD_ENCRYPTION_KEY",
Expand Down