import { GetHotelPageRefs } from "@/lib/graphql/Query/HotelPage/HotelPage.graphql" import { GetHotelPageCount } from "@/lib/graphql/Query/HotelPage/HotelPageCount.graphql" import { GetHotelPageUrls } from "@/lib/graphql/Query/HotelPage/HotelPageUrl.graphql" import { request } from "@/lib/graphql/request" import { notFound } from "@/server/errors/trpc" import { createCounter } from "@/server/telemetry" import { generateRefsResponseTag, generateTag, generateTagsFromSystem, } from "@/utils/generateTag" import { batchedHotelPageUrlsSchema, hotelPageCountSchema, hotelPageRefsSchema, } from "./output" import { HotelPageEnum } from "@/types/enums/hotelPage" import type { System } from "@/types/requests/system" import type { GetHotelPageCountData, GetHotelPageRefsSchema, GetHotelPageUrlsData, HotelPageRefs, } from "@/types/trpc/routers/contentstack/hotelPage" import type { Lang } from "@/constants/languages" export async function fetchHotelPageRefs(lang: Lang, uid: string) { const getHotelPageRefsCounter = createCounter( "trpc.contentstack", "hotelPage.get.refs" ) const metricsGetHotelPageRefs = getHotelPageRefsCounter.init({ lang, uid }) metricsGetHotelPageRefs.start() const refsResponse = await request( GetHotelPageRefs, { locale: lang, uid }, { key: generateRefsResponseTag(lang, uid), ttl: "max", } ) if (!refsResponse.data) { const notFoundError = notFound(refsResponse) metricsGetHotelPageRefs.noDataError() throw notFoundError } return refsResponse.data } export function validateHotelPageRefs( data: GetHotelPageRefsSchema, lang: Lang, uid: string ) { const getHotelPageRefsCounter = createCounter( "trpc.contentstack", "hotelPage.get.refs" ) const metricsGetHotelPageRefs = getHotelPageRefsCounter.init({ lang, uid }) const validatedData = hotelPageRefsSchema.safeParse(data) if (!validatedData.success) { metricsGetHotelPageRefs.validationError(validatedData.error) return null } metricsGetHotelPageRefs.success() return validatedData.data } export function generatePageTags( validatedData: HotelPageRefs, lang: Lang ): string[] { const connections = getConnections(validatedData) return [ generateTagsFromSystem(lang, connections), generateTag(lang, validatedData.hotel_page.system.uid), ].flat() } export function getConnections({ hotel_page }: HotelPageRefs) { const connections: System["system"][] = [hotel_page.system] if (hotel_page.content) { hotel_page.content.forEach((block) => { switch (block.__typename) { case HotelPageEnum.ContentStack.blocks.ActivitiesCard: { if (block.upcoming_activities_card.length) { connections.push(...block.upcoming_activities_card) } break } } if (hotel_page.faq) { connections.push(...hotel_page.faq) } }) } return connections } export async function getHotelPageCount(lang: Lang) { const getHotelPageCountCounter = createCounter( "trpc.contentstack", "hotelPageCount.get" ) const metricsGetHotelPageCount = getHotelPageCountCounter.init({ lang }) metricsGetHotelPageCount.start() const response = await request( GetHotelPageCount, { locale: lang, }, { key: `${lang}:hotel_page_count`, ttl: "max", } ) if (!response.data) { metricsGetHotelPageCount.noDataError() return 0 } const validatedResponse = hotelPageCountSchema.safeParse(response.data) if (!validatedResponse.success) { metricsGetHotelPageCount.validationError(validatedResponse.error) return 0 } metricsGetHotelPageCount.success() return validatedResponse.data } export async function getHotelPageUrls(lang: Lang) { const getHotelPageUrlsCounter = createCounter( "trpc.contentstack", "hotelPageUrls.get" ) const metricsGetHotelPageUrls = getHotelPageUrlsCounter.init({ lang }) metricsGetHotelPageUrls.start() const count = await getHotelPageCount(lang) if (count === 0) { return [] } // Calculating the amount of requests needed to fetch all hotel pages. // Contentstack has a limit of 100 items per request. // So we need to make multiple requests to fetch urls to all hotel pages. // The `batchRequest` function is not working here, because the arrayMerge is // used for other purposes. const amountOfRequests = Math.ceil(count / 100) const requests = Array.from({ length: amountOfRequests }).map((_, i) => ({ document: GetHotelPageUrls, variables: { locale: lang, skip: i * 100 }, cacheKey: `${lang}:hotel_page_urls_batch_${i}`, })) const batchedResponse = await Promise.all( requests.map((req) => request(req.document, req.variables, { key: req.cacheKey, ttl: "max", }) ) ) const validatedResponse = batchedHotelPageUrlsSchema.safeParse(batchedResponse) if (!validatedResponse.success) { metricsGetHotelPageUrls.validationError(validatedResponse.error) return [] } metricsGetHotelPageUrls.success() return validatedResponse.data }