fix: add wrapper function for caching

This commit is contained in:
Christel Westerberg
2024-11-25 13:47:25 +01:00
parent 503b0bf186
commit 8bfc4065ed
7 changed files with 55 additions and 53 deletions

View File

@@ -1,6 +1,6 @@
import { Lang } from "@/constants/languages"
import { dt } from "@/lib/dt"
import { getRoomAvailability } from "@/lib/trpc/memoizedRequests"
import { getRoomsAvailability } from "@/lib/trpc/memoizedRequests"
import Alert from "@/components/TempDesignSystem/Alert"
import { getIntl } from "@/i18n"
@@ -31,7 +31,7 @@ export async function NoRoomsAlert({
lang,
}: Props) {
const [availability, availabilityError] = await safeTry(
getRoomAvailability({
getRoomsAvailability({
hotelId: hotelId,
roomStayStartDate: dt(fromDate).format("YYYY-MM-DD"),
roomStayEndDate: dt(toDate).format("YYYY-MM-DD"),

View File

@@ -4,7 +4,7 @@ import {
getHotelData,
getPackages,
getProfileSafely,
getRoomAvailability,
getRoomsAvailability,
} from "@/lib/trpc/memoizedRequests"
import { safeTry } from "@/utils/safeTry"
@@ -57,7 +57,7 @@ export async function RoomsContainer({
)
const roomsAvailabilityPromise = safeTry(
getRoomAvailability({
getRoomsAvailability({
hotelId: hotelId,
roomStayStartDate: fromDateString,
roomStayEndDate: toDateString,

View File

@@ -1,11 +1,12 @@
import { cache } from "react"
import { Lang } from "@/constants/languages"
import {
GetRoomsAvailabilityInput,
GetSelectedRoomAvailabilityInput,
HotelDataInput,
} from "@/server/routers/hotels/input"
import { cache } from "@/utils/cache"
import { serverClient } from "../server"
import type {
@@ -59,46 +60,20 @@ export const getUserTracking = cache(async function getMemoizedUserTracking() {
return serverClient().user.tracking()
})
export const getHotelData = cache(async function getMemoizedHotelData({
hotelId,
language,
isCardOnlyPayment,
}: {
hotelId: string
language: string
isCardOnlyPayment?: boolean
}) {
return serverClient().hotel.hotelData.get({
hotelId,
language,
isCardOnlyPayment,
})
export const getHotelData = cache(function getMemoizedHotelData(
props: HotelDataInput
) {
return serverClient().hotel.hotelData.get(props)
})
export const getRoomAvailability = cache(
async function getMemoizedRoomAvailability({
hotelId,
adults,
roomStayStartDate,
roomStayEndDate,
children,
bookingCode,
rateCode,
}: GetRoomsAvailabilityInput) {
return serverClient().hotel.availability.rooms({
hotelId,
adults,
roomStayStartDate,
roomStayEndDate,
children,
bookingCode,
rateCode,
})
}
)
export const getRoomsAvailability = cache(function getMemoizedRoomAvailability(
args: GetRoomsAvailabilityInput
) {
return serverClient().hotel.availability.rooms(args)
})
export const getSelectedRoomAvailability = cache(
async function getMemoizedRoomAvailability(
function getMemoizedSelectedRoomAvailability(
args: GetSelectedRoomAvailabilityInput
) {
return serverClient().hotel.availability.room(args)
@@ -141,13 +116,13 @@ export const getSiteConfig = cache(async function getMemoizedSiteConfig() {
return serverClient().contentstack.base.siteConfig()
})
export const getBreakfastPackages = cache(async function getMemoizedPackages(
export const getBreakfastPackages = cache(function getMemoizedBreakfastPackages(
input: BreackfastPackagesInput
) {
return serverClient().hotel.packages.breakfast(input)
})
export const getPackages = cache(async function getMemoizedPackages(
export const getPackages = cache(function getMemoizedPackages(
input: PackagesInput
) {
return serverClient().hotel.packages.get(input)

11
package-lock.json generated
View File

@@ -41,6 +41,7 @@
"graphql-request": "^6.1.0",
"graphql-tag": "^2.12.6",
"immer": "10.1.1",
"json-stable-stringify-without-jsonify": "^1.0.1",
"libphonenumber-js": "^1.10.60",
"next": "^14.2.18",
"next-auth": "^5.0.0-beta.19",
@@ -64,6 +65,7 @@
"@testing-library/react": "^16.0.0",
"@testing-library/user-event": "^14.5.2",
"@types/jest": "^29.5.12",
"@types/json-stable-stringify-without-jsonify": "^1.0.2",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
@@ -6850,6 +6852,12 @@
"parse5": "^7.0.0"
}
},
"node_modules/@types/json-stable-stringify-without-jsonify": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.2.tgz",
"integrity": "sha512-X/Kn5f5fv1KBGqGDaegrj72Dlh+qEKN3ELwMAB6RdVlVzkf6NTeEnJpgR/Hr0AlpgTlYq/Vd0U3f79lavn6aDA==",
"dev": true
},
"node_modules/@types/json5": {
"version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
@@ -13939,8 +13947,7 @@
"node_modules/json-stable-stringify-without-jsonify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
"dev": true
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="
},
"node_modules/json-stringify-safe": {
"version": "5.0.1",

View File

@@ -56,6 +56,7 @@
"graphql-request": "^6.1.0",
"graphql-tag": "^2.12.6",
"immer": "10.1.1",
"json-stable-stringify-without-jsonify": "^1.0.1",
"libphonenumber-js": "^1.10.60",
"next": "^14.2.18",
"next-auth": "^5.0.0-beta.19",
@@ -79,6 +80,7 @@
"@testing-library/react": "^16.0.0",
"@testing-library/user-event": "^14.5.2",
"@types/jest": "^29.5.12",
"@types/json-stable-stringify-without-jsonify": "^1.0.2",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",

View File

@@ -1,16 +1,11 @@
import { metrics } from "@opentelemetry/api"
import { cache } from "react"
import { Lang } from "@/constants/languages"
import * as api from "@/lib/api"
import { dt } from "@/lib/dt"
import { GetHotelPage } from "@/lib/graphql/Query/HotelPage/HotelPage.graphql"
import { request } from "@/lib/graphql/request"
import {
badRequestError,
notFound,
serverErrorByStatus,
} from "@/server/errors/trpc"
import { badRequestError, notFound } from "@/server/errors/trpc"
import {
contentStackUidWithServiceProcedure,
publicProcedure,
@@ -20,6 +15,8 @@ import {
} from "@/server/trpc"
import { toApiLang } from "@/server/utils"
import { cache } from "@/utils/cache"
import { hotelPageSchema } from "../contentstack/hotelPage/output"
import {
fetchHotelPageRefs,
@@ -57,7 +54,6 @@ import {
import { FacilityCardTypeEnum } from "@/types/components/hotelPage/facilities"
import type { BedTypeSelection } from "@/types/components/hotelReservation/enterDetails/bedType"
import { AvailabilityEnum } from "@/types/components/hotelReservation/selectHotel/selectHotel"
import { BreakfastPackageEnum } from "@/types/enums/breakfast"
import { HotelTypeEnum } from "@/types/enums/hotelType"
import type { RequestOptionsWithOutBody } from "@/types/fetch"

22
utils/cache.ts Normal file
View File

@@ -0,0 +1,22 @@
import stringify from "json-stable-stringify-without-jsonify"
import { cache as reactCache } from "react"
/**
* Wrapper function to handle caching of memoized requests that recieve objects as args.
* React Cache will use shallow equality of the arguments to determine if there is a cache hit,
* therefore we need to stringify the arguments to ensure that the cache works as expected.
* This function will handle the stingification of the arguments, the caching of the function,
* and the parsing of the arguments back to their original form.
*
* @param fn - The function to memoize
*/
export function cache<T extends (...args: any[]) => any>(fn: T) {
const cachedFunction = reactCache((stringifiedParams: string) => {
return fn(...JSON.parse(stringifiedParams))
})
return (...args: Parameters<T>): ReturnType<T> => {
const stringifiedParams = stringify(args)
return cachedFunction(stringifiedParams)
}
}