Files
web/packages/trpc/lib/routers/contentstack/hotelPage/utils.ts
Joakim Jäderberg 8b94540d19 Merged in chore/redirect-counter (pull request #3302)
Counter name is now searchable and add counter for redirects

* refactor: createCounter() only takes one argument, the name of the counter. Makes it easier to search for

* feat: add counter when we do a redirect from redirect-service


Approved-by: Linus Flood
2025-12-08 10:24:05 +00:00

138 lines
4.2 KiB
TypeScript

import { createCounter } from "@scandic-hotels/common/telemetry"
import { GetHotelPageCount } from "../../../graphql/Query/HotelPage/HotelPageCount.graphql"
import { GetHotelPageUrls } from "../../../graphql/Query/HotelPage/HotelPageUrl.graphql"
import { request } from "../../../graphql/request"
import { batchedHotelPageUrlsSchema, hotelPageCountSchema } from "./output"
import type { Lang } from "@scandic-hotels/common/constants/language"
import type { Campaigns } from "../../../types/campaignPage"
import type {
GetHotelPageCountData,
GetHotelPageUrlsData,
} from "../../../types/hotelPage"
export async function getHotelPageCount(lang: Lang) {
const getHotelPageCountCounter = createCounter(
"trpc.contentstack.hotelPageCount.get"
)
const metricsGetHotelPageCount = getHotelPageCountCounter.init({ lang })
metricsGetHotelPageCount.start()
const response = await request<GetHotelPageCountData>(
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<GetHotelPageUrlsData>(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
}
export function getSortedCampaigns(
prioritizedCampaignUids: string[],
campaigns: Campaigns
) {
// First we'll sort on the list of prioritizedCampaignUids provided by the
// hotel page. If the campaign is not in the prioritized list, it will be
// added to the end of the sorted list using the default order from Contentstack.
const prioritizedSet = new Set(prioritizedCampaignUids)
const prioritized = prioritizedCampaignUids.flatMap((id) => {
const found = campaigns.find((c) => c.id === id)
return found ? [found] : []
})
const others = campaigns.filter((c) => !prioritizedSet.has(c.id))
const sortedCampaigns = [...prioritized, ...others]
// Finally, we'll sort the campaigns by their sort_order, which gets higher priority
// than the order by prioritizedCampaignUids. If sort_order is not provided,
// we'll keep the original order. The higher the sort_order value, the higher the priority.
return sortedCampaigns.sort((a, b) => {
const aSortOrder = a.sort_order
const bSortOrder = b.sort_order
const aHasSortOrder = typeof aSortOrder === "number"
const bHasSortOrder = typeof bSortOrder === "number"
if (aHasSortOrder && bHasSortOrder) {
// Descending order: higher sort_order comes first
return bSortOrder - aSortOrder
}
if (aHasSortOrder && !bHasSortOrder) {
return -1
}
if (!aHasSortOrder && bHasSortOrder) {
return 1
}
return 0
})
}