feat: harmonize log and metrics
This commit is contained in:
@@ -1,88 +0,0 @@
|
||||
import { metrics as opentelemetryMetrics } from "@opentelemetry/api"
|
||||
|
||||
const meter = opentelemetryMetrics.getMeter("trpc.hotels")
|
||||
export const metrics = {
|
||||
additionalData: {
|
||||
counter: meter.createCounter("trpc.hotels.additionalData"),
|
||||
fail: meter.createCounter("trpc.hotels.additionalData-fail"),
|
||||
success: meter.createCounter("trpc.hotels.additionalData-success"),
|
||||
},
|
||||
breakfastPackage: {
|
||||
counter: meter.createCounter("trpc.package.breakfast"),
|
||||
fail: meter.createCounter("trpc.package.breakfast-fail"),
|
||||
success: meter.createCounter("trpc.package.breakfast-success"),
|
||||
},
|
||||
ancillaryPackage: {
|
||||
counter: meter.createCounter("trpc.package.ancillary"),
|
||||
fail: meter.createCounter("trpc.package.ancillary-fail"),
|
||||
success: meter.createCounter("trpc.package.ancillary-success"),
|
||||
},
|
||||
hotel: {
|
||||
counter: meter.createCounter("trpc.hotel.get"),
|
||||
fail: meter.createCounter("trpc.hotel.get-fail"),
|
||||
success: meter.createCounter("trpc.hotel.get-success"),
|
||||
},
|
||||
hotels: {
|
||||
counter: meter.createCounter("trpc.hotel.hotels.get"),
|
||||
fail: meter.createCounter("trpc.hotel.hotels.get-fail"),
|
||||
success: meter.createCounter("trpc.hotel.hotels.get-success"),
|
||||
},
|
||||
hotelIds: {
|
||||
counter: meter.createCounter("trpc.hotel.hotel-ids.get"),
|
||||
fail: meter.createCounter("trpc.hotel.hotel-ids.get-fail"),
|
||||
success: meter.createCounter("trpc.hotel.hotel-ids.get-success"),
|
||||
},
|
||||
hotelsAvailability: {
|
||||
counter: meter.createCounter("trpc.hotel.availability.hotels"),
|
||||
fail: meter.createCounter("trpc.hotel.availability.hotels-fail"),
|
||||
success: meter.createCounter("trpc.hotel.availability.hotels-success"),
|
||||
},
|
||||
hotelsAvailabilityBookingCode: {
|
||||
counter: meter.createCounter("trpc.hotel.availability.hotels-booking-code"),
|
||||
fail: meter.createCounter(
|
||||
"trpc.hotel.availability.hotels-booking-code-fail"
|
||||
),
|
||||
success: meter.createCounter(
|
||||
"trpc.hotel.availability.hotels-booking-code-success"
|
||||
),
|
||||
},
|
||||
hotelsByHotelIdAvailability: {
|
||||
counter: meter.createCounter("trpc.hotel.availability.hotels-by-hotel-id"),
|
||||
fail: meter.createCounter(
|
||||
"trpc.hotel.availability.hotels-by-hotel-id-fail"
|
||||
),
|
||||
success: meter.createCounter(
|
||||
"trpc.hotel.availability.hotels-by-hotel-id-success"
|
||||
),
|
||||
},
|
||||
meetingRooms: {
|
||||
counter: meter.createCounter("trpc.hotels.meetingRooms"),
|
||||
fail: meter.createCounter("trpc.hotels.meetingRooms-fail"),
|
||||
success: meter.createCounter("trpc.hotels.meetingRooms-success"),
|
||||
},
|
||||
nearbyHotelIds: {
|
||||
counter: meter.createCounter("trpc.hotel.nearby-hotel-ids.get"),
|
||||
fail: meter.createCounter("trpc.hotel.nearby-hotel-ids.get-fail"),
|
||||
success: meter.createCounter("trpc.hotel.nearby-hotel-ids.get-success"),
|
||||
},
|
||||
packages: {
|
||||
counter: meter.createCounter("trpc.hotel.packages.get"),
|
||||
fail: meter.createCounter("trpc.hotel.packages.get-fail"),
|
||||
success: meter.createCounter("trpc.hotel.packages.get-success"),
|
||||
},
|
||||
roomsAvailability: {
|
||||
counter: meter.createCounter("trpc.hotel.roomsAvailability.rooms"),
|
||||
fail: meter.createCounter("trpc.hotel.roomsAvailability.rooms-fail"),
|
||||
success: meter.createCounter("trpc.hotel.roomsAvailability.rooms-success"),
|
||||
},
|
||||
selectedRoomAvailability: {
|
||||
counter: meter.createCounter("trpc.hotel.availability.room"),
|
||||
fail: meter.createCounter("trpc.hotel.availability.room-fail"),
|
||||
success: meter.createCounter("trpc.hotel.availability.room-success"),
|
||||
},
|
||||
roomFeatures: {
|
||||
counter: meter.createCounter("trpc.availability.roomfeature"),
|
||||
fail: meter.createCounter("trpc.availability.roomfeature-fail"),
|
||||
success: meter.createCounter("trpc.availability.roomfeature-success"),
|
||||
},
|
||||
}
|
||||
@@ -5,6 +5,8 @@ import * as api from "@/lib/api"
|
||||
import { dt } from "@/lib/dt"
|
||||
import { badRequestError, unauthorizedError } from "@/server/errors/trpc"
|
||||
import { getCityPageUrls } from "@/server/routers/contentstack/destinationCityPage/utils"
|
||||
import { getVerifiedUser } from "@/server/routers/user/utils"
|
||||
import { createCounter } from "@/server/telemetry"
|
||||
import {
|
||||
contentStackBaseWithServiceProcedure,
|
||||
publicProcedure,
|
||||
@@ -17,7 +19,6 @@ import { toApiLang } from "@/server/utils"
|
||||
import { getCacheClient } from "@/services/dataCache"
|
||||
|
||||
import { getHotelPageUrls } from "../contentstack/hotelPage/utils"
|
||||
import { getVerifiedUser } from "../user/query"
|
||||
import { additionalDataSchema } from "./schemas/hotel/include/additionalData"
|
||||
import { meetingRoomsSchema } from "./schemas/meetingRoom"
|
||||
import {
|
||||
@@ -42,17 +43,11 @@ import {
|
||||
selectRateRoomAvailabilityInputSchema,
|
||||
selectRateRoomsAvailabilityInputSchema,
|
||||
} from "./input"
|
||||
import { metrics } from "./metrics"
|
||||
import {
|
||||
ancillaryPackagesSchema,
|
||||
breakfastPackagesSchema,
|
||||
getNearbyHotelIdsSchema,
|
||||
} from "./output"
|
||||
import {
|
||||
locationsUrlsCounter,
|
||||
locationsUrlsFailCounter,
|
||||
locationsUrlsSuccessCounter,
|
||||
} from "./telemetry"
|
||||
import {
|
||||
getBedTypes,
|
||||
getCitiesByCountry,
|
||||
@@ -431,36 +426,24 @@ export const hotelQueryRouter = router({
|
||||
const { lang } = ctx
|
||||
const apiLang = toApiLang(lang)
|
||||
|
||||
metrics.hotelsAvailabilityBookingCode.counter.add(1, {
|
||||
...input,
|
||||
})
|
||||
const bookingCodeAvailabilityResponse =
|
||||
await getHotelsAvailabilityByCity(input, apiLang, ctx.serviceToken)
|
||||
|
||||
// If API or network failed with no response
|
||||
if (!bookingCodeAvailabilityResponse) {
|
||||
metrics.hotelsAvailabilityBookingCode.fail.add(1, {
|
||||
...input,
|
||||
error_type: "unknown",
|
||||
})
|
||||
return null
|
||||
}
|
||||
|
||||
// Get regular availability of hotels which don't have availability with booking code.
|
||||
const unavailableHotelIds =
|
||||
bookingCodeAvailabilityResponse?.availability
|
||||
.filter((hotel) => {
|
||||
return hotel.status === "NotAvailable"
|
||||
})
|
||||
.flatMap((hotel) => {
|
||||
return hotel.hotelId
|
||||
})
|
||||
const unavailableHotelIds = bookingCodeAvailabilityResponse.availability
|
||||
.filter((hotel) => {
|
||||
return hotel.status === "NotAvailable"
|
||||
})
|
||||
.flatMap((hotel) => {
|
||||
return hotel.hotelId
|
||||
})
|
||||
|
||||
// All hotels have availability with booking code no need to fetch regular prices.
|
||||
// return response as is without any filtering as below.
|
||||
if (!unavailableHotelIds || !unavailableHotelIds.length) {
|
||||
return bookingCodeAvailabilityResponse
|
||||
}
|
||||
|
||||
const unavailableHotelsInput = {
|
||||
...input,
|
||||
bookingCode: "",
|
||||
@@ -472,11 +455,6 @@ export const hotelQueryRouter = router({
|
||||
ctx.serviceToken
|
||||
)
|
||||
|
||||
metrics.hotelsAvailabilityBookingCode.success.add(1, {
|
||||
...input,
|
||||
})
|
||||
console.info("api.hotels.hotelsAvailabilityBookingCode success")
|
||||
|
||||
// No regular rates available due to network or API failure (no need to filter & merge).
|
||||
if (!unavailableHotels) {
|
||||
return bookingCodeAvailabilityResponse
|
||||
@@ -537,19 +515,16 @@ export const hotelQueryRouter = router({
|
||||
const language = ctx.lang
|
||||
let hotelsToFetch: string[] = []
|
||||
|
||||
metrics.hotels.counter.add(1, {
|
||||
input: JSON.stringify(input),
|
||||
const getHotelsByCSFilterCounter = createCounter(
|
||||
"trpc.hotel.hotels",
|
||||
"byCSFilter"
|
||||
)
|
||||
const metricsGetHotelsByCSFilter = getHotelsByCSFilterCounter.init({
|
||||
input,
|
||||
language,
|
||||
})
|
||||
console.info(
|
||||
"api.hotel.hotels start",
|
||||
JSON.stringify({
|
||||
query: {
|
||||
...input,
|
||||
language,
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
metricsGetHotelsByCSFilter.start()
|
||||
|
||||
if (hotelsToInclude.length) {
|
||||
hotelsToFetch = hotelsToInclude
|
||||
@@ -571,20 +546,13 @@ export const hotelQueryRouter = router({
|
||||
.find((loc) => loc.cityIdentifier === locationFilter.city)?.id
|
||||
|
||||
if (!cityId) {
|
||||
metrics.hotels.fail.add(1, {
|
||||
input: JSON.stringify(input),
|
||||
language,
|
||||
error_type: "not_found",
|
||||
error: `CityId not found for cityIdentifier: ${locationFilter.city}`,
|
||||
})
|
||||
|
||||
console.error(
|
||||
"api.hotel.hotels not found error",
|
||||
JSON.stringify({
|
||||
query: { ...input, language },
|
||||
error: `CityId not found for cityIdentifier: ${locationFilter.city}`,
|
||||
})
|
||||
metricsGetHotelsByCSFilter.dataError(
|
||||
`CityId not found for cityIdentifier: ${locationFilter.city}`,
|
||||
{
|
||||
cityIdentifier: locationFilter.city,
|
||||
}
|
||||
)
|
||||
|
||||
return []
|
||||
}
|
||||
|
||||
@@ -594,20 +562,13 @@ export const hotelQueryRouter = router({
|
||||
})
|
||||
|
||||
if (!hotelIds?.length) {
|
||||
metrics.hotels.fail.add(1, {
|
||||
cityId,
|
||||
language,
|
||||
error_type: "not_found",
|
||||
error: `No hotelIds found for cityId: ${cityId}`,
|
||||
})
|
||||
|
||||
console.error(
|
||||
"api.hotel.hotels not found error",
|
||||
JSON.stringify({
|
||||
query: { cityId, language },
|
||||
error: `No hotelIds found for cityId: ${cityId}`,
|
||||
})
|
||||
metricsGetHotelsByCSFilter.dataError(
|
||||
`No hotelIds found for cityId: ${cityId}`,
|
||||
{
|
||||
cityId,
|
||||
}
|
||||
)
|
||||
|
||||
return []
|
||||
}
|
||||
|
||||
@@ -623,20 +584,13 @@ export const hotelQueryRouter = router({
|
||||
})
|
||||
|
||||
if (!hotelIds?.length) {
|
||||
metrics.hotels.fail.add(1, {
|
||||
country: locationFilter.country,
|
||||
language,
|
||||
error_type: "not_found",
|
||||
error: `No hotelIds found for country: ${locationFilter.country}`,
|
||||
})
|
||||
|
||||
console.error(
|
||||
"api.hotel.hotels not found error",
|
||||
JSON.stringify({
|
||||
query: { country: locationFilter.country, language },
|
||||
error: `No hotelIds found for cityId: ${locationFilter.country}`,
|
||||
})
|
||||
metricsGetHotelsByCSFilter.dataError(
|
||||
`No hotelIds found for country: ${locationFilter.country}`,
|
||||
{
|
||||
country: locationFilter.country,
|
||||
}
|
||||
)
|
||||
|
||||
return []
|
||||
}
|
||||
|
||||
@@ -648,20 +602,11 @@ export const hotelQueryRouter = router({
|
||||
}
|
||||
|
||||
if (!hotelsToFetch.length) {
|
||||
metrics.hotels.fail.add(1, {
|
||||
input: JSON.stringify(input),
|
||||
language,
|
||||
error_type: "not_found",
|
||||
error: `Couldn't find any hotels for given input: ${JSON.stringify(input)}`,
|
||||
})
|
||||
|
||||
console.error(
|
||||
"api.hotel.hotels not found error",
|
||||
JSON.stringify({
|
||||
query: JSON.stringify(input),
|
||||
error: `Couldn't find any hotels for given input: ${JSON.stringify(input)}`,
|
||||
})
|
||||
metricsGetHotelsByCSFilter.dataError(
|
||||
`Couldn't find any hotels for given input: ${JSON.stringify(input)}`,
|
||||
input
|
||||
)
|
||||
|
||||
return []
|
||||
}
|
||||
const hotelPages = await getHotelPageUrls(language)
|
||||
@@ -684,20 +629,7 @@ export const hotelQueryRouter = router({
|
||||
})
|
||||
)
|
||||
|
||||
metrics.hotels.success.add(1, {
|
||||
input: JSON.stringify(input),
|
||||
language,
|
||||
})
|
||||
|
||||
console.info(
|
||||
"api.hotels success",
|
||||
JSON.stringify({
|
||||
query: {
|
||||
input: JSON.stringify(input),
|
||||
language,
|
||||
},
|
||||
})
|
||||
)
|
||||
metricsGetHotelsByCSFilter.success()
|
||||
|
||||
return hotels.filter((hotel): hotel is HotelDataWithUrl => !!hotel)
|
||||
}),
|
||||
@@ -769,13 +701,17 @@ export const hotelQueryRouter = router({
|
||||
return cacheClient.cacheOrGet(
|
||||
`${apiLang}:nearbyHotels:${hotelId}`,
|
||||
async () => {
|
||||
metrics.nearbyHotelIds.counter.add(1, {
|
||||
const nearbyHotelsCounter = createCounter(
|
||||
"trpc.hotel",
|
||||
"nearbyHotelIds"
|
||||
)
|
||||
const metricsNearbyHotels = nearbyHotelsCounter.init({
|
||||
params,
|
||||
hotelId,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.nearbyHotelIds start",
|
||||
JSON.stringify({ query: { hotelId, params } })
|
||||
)
|
||||
|
||||
metricsNearbyHotels.start()
|
||||
|
||||
const apiResponse = await api.get(
|
||||
api.endpoints.v1.Hotel.Hotels.nearbyHotels(hotelId),
|
||||
{
|
||||
@@ -786,55 +722,18 @@ export const hotelQueryRouter = router({
|
||||
params
|
||||
)
|
||||
if (!apiResponse.ok) {
|
||||
const text = await apiResponse.text()
|
||||
metrics.nearbyHotelIds.fail.add(1, {
|
||||
hotelId,
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
}),
|
||||
})
|
||||
console.error(
|
||||
"api.hotels.nearbyHotelIds error",
|
||||
JSON.stringify({
|
||||
query: { hotelId, params },
|
||||
error: {
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
},
|
||||
})
|
||||
)
|
||||
await metricsNearbyHotels.httpError(apiResponse)
|
||||
return null
|
||||
}
|
||||
|
||||
const apiJson = await apiResponse.json()
|
||||
const validateHotelData = getNearbyHotelIdsSchema.safeParse(apiJson)
|
||||
if (!validateHotelData.success) {
|
||||
metrics.nearbyHotelIds.fail.add(1, {
|
||||
hotelId,
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(validateHotelData.error),
|
||||
})
|
||||
console.error(
|
||||
"api.hotels.nearbyHotelIds validation error",
|
||||
JSON.stringify({
|
||||
query: { hotelId, params },
|
||||
error: validateHotelData.error,
|
||||
})
|
||||
)
|
||||
metricsNearbyHotels.validationError(validateHotelData.error)
|
||||
throw badRequestError()
|
||||
}
|
||||
metrics.nearbyHotelIds.success.add(1, {
|
||||
hotelId,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.nearbyHotelIds success",
|
||||
JSON.stringify({
|
||||
query: { hotelId, params },
|
||||
})
|
||||
)
|
||||
|
||||
metricsNearbyHotels.success()
|
||||
|
||||
return validateHotelData.data.map((id: string) => parseInt(id, 10))
|
||||
},
|
||||
@@ -884,16 +783,17 @@ export const hotelQueryRouter = router({
|
||||
urls: publicProcedure
|
||||
.input(getLocationsUrlsInput)
|
||||
.query(async ({ input }) => {
|
||||
const procedureName = "hotels.locations.urls"
|
||||
|
||||
const { lang } = input
|
||||
|
||||
locationsUrlsCounter.add(1, { lang })
|
||||
|
||||
console.info(
|
||||
`${procedureName}: start`,
|
||||
JSON.stringify({ query: { lang } })
|
||||
const locationsUrlsCounter = createCounter(
|
||||
"trpc.hotel.locations",
|
||||
"urls"
|
||||
)
|
||||
const metricsLocationsUrls = locationsUrlsCounter.init({
|
||||
lang,
|
||||
})
|
||||
|
||||
metricsLocationsUrls.start()
|
||||
|
||||
const [hotelPageUrlsResult, cityPageUrlsResult] =
|
||||
await Promise.allSettled([
|
||||
@@ -905,32 +805,15 @@ export const hotelQueryRouter = router({
|
||||
hotelPageUrlsResult.status === "rejected" ||
|
||||
cityPageUrlsResult.status === "rejected"
|
||||
) {
|
||||
locationsUrlsFailCounter.add(1, {
|
||||
lang,
|
||||
error_type: "no_data",
|
||||
response: JSON.stringify({
|
||||
hotelPageUrlsResult,
|
||||
cityPageUrlsResult,
|
||||
}),
|
||||
})
|
||||
|
||||
console.error(`${procedureName}: no data`, {
|
||||
variables: { lang },
|
||||
error_type: "no_data",
|
||||
response: {
|
||||
hotelPageUrlsResult,
|
||||
cityPageUrlsResult,
|
||||
},
|
||||
metricsLocationsUrls.dataError(`Failed to get data for page URLs`, {
|
||||
hotelPageUrlsResult,
|
||||
cityPageUrlsResult,
|
||||
})
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
locationsUrlsSuccessCounter.add(1, { lang })
|
||||
|
||||
console.info(`${procedureName}: success`, {
|
||||
variables: { lang },
|
||||
})
|
||||
metricsLocationsUrls.success()
|
||||
|
||||
return {
|
||||
hotels: hotelPageUrlsResult.value,
|
||||
@@ -992,12 +875,12 @@ export const hotelQueryRouter = router({
|
||||
hotelId,
|
||||
language,
|
||||
}
|
||||
const metricsData = { ...params, hotelId: input.hotelId }
|
||||
metrics.meetingRooms.counter.add(1, metricsData)
|
||||
console.info(
|
||||
"api.hotels.meetingRooms start",
|
||||
JSON.stringify({ query: { hotelId, params } })
|
||||
)
|
||||
const meetingRoomsCounter = createCounter("trpc.hotel", "meetingRooms")
|
||||
const metricsMeetingRooms = meetingRoomsCounter.init({
|
||||
params,
|
||||
})
|
||||
|
||||
metricsMeetingRooms.start()
|
||||
|
||||
const cacheClient = await getCacheClient()
|
||||
return cacheClient.cacheOrGet(
|
||||
@@ -1014,28 +897,7 @@ export const hotelQueryRouter = router({
|
||||
)
|
||||
|
||||
if (!apiResponse.ok) {
|
||||
const text = await apiResponse.text()
|
||||
metrics.meetingRooms.fail.add(1, {
|
||||
...metricsData,
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
}),
|
||||
})
|
||||
console.error(
|
||||
"api.hotels.meetingRooms error",
|
||||
JSON.stringify({
|
||||
query: { params },
|
||||
error: {
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
await metricsMeetingRooms.httpError(apiResponse)
|
||||
throw new Error("Failed to fetch meeting rooms")
|
||||
}
|
||||
|
||||
@@ -1043,22 +905,10 @@ export const hotelQueryRouter = router({
|
||||
const validatedMeetingRooms = meetingRoomsSchema.safeParse(apiJson)
|
||||
|
||||
if (!validatedMeetingRooms.success) {
|
||||
console.error(
|
||||
"api.hotels.meetingRooms validation error",
|
||||
JSON.stringify({
|
||||
query: { params },
|
||||
error: validatedMeetingRooms.error,
|
||||
})
|
||||
)
|
||||
metricsMeetingRooms.validationError(validatedMeetingRooms.error)
|
||||
throw badRequestError()
|
||||
}
|
||||
metrics.meetingRooms.success.add(1, {
|
||||
hotelId,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.meetingRooms success",
|
||||
JSON.stringify({ query: { params } })
|
||||
)
|
||||
metricsMeetingRooms.success()
|
||||
|
||||
return validatedMeetingRooms.data.data
|
||||
},
|
||||
@@ -1074,12 +924,16 @@ export const hotelQueryRouter = router({
|
||||
hotelId,
|
||||
language,
|
||||
}
|
||||
const metricsData = { ...params, hotelId: input.hotelId }
|
||||
metrics.additionalData.counter.add(1, metricsData)
|
||||
console.info(
|
||||
"api.hotels.additionalData start",
|
||||
JSON.stringify({ query: { hotelId, params } })
|
||||
|
||||
const additionalDataCounter = createCounter(
|
||||
"trpc.hotel",
|
||||
"additionalData"
|
||||
)
|
||||
const metricsAdditionalData = additionalDataCounter.init({
|
||||
params,
|
||||
})
|
||||
|
||||
metricsAdditionalData.start()
|
||||
|
||||
const cacheClient = await getCacheClient()
|
||||
return cacheClient.cacheOrGet(
|
||||
@@ -1096,28 +950,7 @@ export const hotelQueryRouter = router({
|
||||
)
|
||||
|
||||
if (!apiResponse.ok) {
|
||||
const text = await apiResponse.text()
|
||||
metrics.additionalData.fail.add(1, {
|
||||
...metricsData,
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
}),
|
||||
})
|
||||
console.error(
|
||||
"api.hotels.additionalData error",
|
||||
JSON.stringify({
|
||||
query: { params },
|
||||
error: {
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
await metricsAdditionalData.httpError(apiResponse)
|
||||
throw new Error("Unable to fetch additional data for hotel")
|
||||
}
|
||||
|
||||
@@ -1126,22 +959,11 @@ export const hotelQueryRouter = router({
|
||||
additionalDataSchema.safeParse(apiJson)
|
||||
|
||||
if (!validatedAdditionalData.success) {
|
||||
console.error(
|
||||
"api.hotels.additionalData validation error",
|
||||
JSON.stringify({
|
||||
query: { params },
|
||||
error: validatedAdditionalData.error,
|
||||
})
|
||||
)
|
||||
metricsAdditionalData.validationError(validatedAdditionalData.error)
|
||||
throw badRequestError()
|
||||
}
|
||||
metrics.additionalData.success.add(1, {
|
||||
hotelId,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.additionalData success",
|
||||
JSON.stringify({ query: { params } })
|
||||
)
|
||||
|
||||
metricsAdditionalData.success()
|
||||
|
||||
return validatedAdditionalData.data
|
||||
},
|
||||
@@ -1167,12 +989,16 @@ export const hotelQueryRouter = router({
|
||||
language: apiLang,
|
||||
}
|
||||
|
||||
const metricsData = { ...params, hotelId: input.hotelId }
|
||||
metrics.breakfastPackage.counter.add(1, metricsData)
|
||||
console.info(
|
||||
"api.package.breakfast start",
|
||||
JSON.stringify({ query: metricsData })
|
||||
const breakfastCounter = createCounter(
|
||||
"trpc.hotel.packages",
|
||||
"breakfast"
|
||||
)
|
||||
const metricsBreakfast = breakfastCounter.init({
|
||||
params,
|
||||
hotelId: input.hotelId,
|
||||
})
|
||||
|
||||
metricsBreakfast.start()
|
||||
|
||||
const cacheClient = await getCacheClient()
|
||||
const breakfastPackages = await cacheClient.cacheOrGet(
|
||||
@@ -1189,57 +1015,17 @@ export const hotelQueryRouter = router({
|
||||
)
|
||||
|
||||
if (!apiResponse.ok) {
|
||||
const text = await apiResponse.text()
|
||||
metrics.breakfastPackage.fail.add(1, {
|
||||
...metricsData,
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
}),
|
||||
})
|
||||
console.error(
|
||||
"api.package.breakfast error",
|
||||
JSON.stringify({
|
||||
query: metricsData,
|
||||
error: {
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
},
|
||||
})
|
||||
)
|
||||
await metricsBreakfast.httpError(apiResponse)
|
||||
throw new Error("Unable to fetch breakfast packages")
|
||||
}
|
||||
|
||||
const apiJson = await apiResponse.json()
|
||||
const breakfastPackages = breakfastPackagesSchema.safeParse(apiJson)
|
||||
if (!breakfastPackages.success) {
|
||||
metrics.breakfastPackage.fail.add(1, {
|
||||
...metricsData,
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(breakfastPackages.error),
|
||||
})
|
||||
console.error(
|
||||
"api.package.breakfast validation error",
|
||||
JSON.stringify({
|
||||
query: metricsData,
|
||||
error: breakfastPackages.error,
|
||||
})
|
||||
)
|
||||
|
||||
metricsBreakfast.validationError(breakfastPackages.error)
|
||||
throw new Error("Unable to parse breakfast packages")
|
||||
}
|
||||
|
||||
metrics.breakfastPackage.success.add(1, metricsData)
|
||||
console.info(
|
||||
"api.package.breakfast success",
|
||||
JSON.stringify({
|
||||
query: metricsData,
|
||||
})
|
||||
)
|
||||
|
||||
return breakfastPackages.data
|
||||
},
|
||||
"1h"
|
||||
@@ -1265,6 +1051,8 @@ export const hotelQueryRouter = router({
|
||||
// }
|
||||
// }
|
||||
|
||||
metricsBreakfast.success()
|
||||
|
||||
return breakfastPackages.filter(
|
||||
(pkg) => pkg.code !== BreakfastPackageEnum.FREE_MEMBER_BREAKFAST
|
||||
)
|
||||
@@ -1281,16 +1069,21 @@ export const hotelQueryRouter = router({
|
||||
language: apiLang,
|
||||
}
|
||||
|
||||
const ancillaryCounter = createCounter(
|
||||
"trpc.hotel.packages",
|
||||
"ancillary"
|
||||
)
|
||||
const metricsAncillary = ancillaryCounter.init({
|
||||
params,
|
||||
hotelId: input.hotelId,
|
||||
})
|
||||
|
||||
metricsAncillary.start()
|
||||
|
||||
const cacheClient = await getCacheClient()
|
||||
return await cacheClient.cacheOrGet(
|
||||
const result = await cacheClient.cacheOrGet(
|
||||
`${apiLang}:hotel:${input.hotelId}:ancillaries:startDate:${params.StartDate}:endDate:${params.EndDate}`,
|
||||
async () => {
|
||||
const metricsData = { ...params, hotelId: input.hotelId }
|
||||
metrics.ancillaryPackage.counter.add(1, metricsData)
|
||||
console.info(
|
||||
"api.package.ancillary start",
|
||||
JSON.stringify({ query: metricsData })
|
||||
)
|
||||
const apiResponse = await api.get(
|
||||
api.endpoints.v1.Package.Ancillary.hotel(input.hotelId),
|
||||
{
|
||||
@@ -1302,59 +1095,25 @@ export const hotelQueryRouter = router({
|
||||
)
|
||||
|
||||
if (!apiResponse.ok) {
|
||||
const text = await apiResponse.text()
|
||||
metrics.ancillaryPackage.fail.add(1, {
|
||||
...metricsData,
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
}),
|
||||
})
|
||||
console.error(
|
||||
"api.package.ancillary start error",
|
||||
JSON.stringify({
|
||||
query: metricsData,
|
||||
error: {
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
},
|
||||
})
|
||||
)
|
||||
await metricsAncillary.httpError(apiResponse)
|
||||
return null
|
||||
}
|
||||
|
||||
const apiJson = await apiResponse.json()
|
||||
const ancillaryPackages = ancillaryPackagesSchema.safeParse(apiJson)
|
||||
if (!ancillaryPackages.success) {
|
||||
metrics.ancillaryPackage.fail.add(1, {
|
||||
...metricsData,
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(ancillaryPackages.error),
|
||||
})
|
||||
console.error(
|
||||
"api.package.ancillary validation error",
|
||||
JSON.stringify({
|
||||
query: metricsData,
|
||||
error: ancillaryPackages.error,
|
||||
})
|
||||
)
|
||||
metricsAncillary.validationError(ancillaryPackages.error)
|
||||
return null
|
||||
}
|
||||
|
||||
metrics.ancillaryPackage.success.add(1, metricsData)
|
||||
console.info(
|
||||
"api.package.ancillary success",
|
||||
JSON.stringify({
|
||||
query: metricsData,
|
||||
})
|
||||
)
|
||||
return ancillaryPackages.data
|
||||
},
|
||||
"1h"
|
||||
)
|
||||
|
||||
metricsAncillary.success()
|
||||
|
||||
return result
|
||||
}),
|
||||
}),
|
||||
})
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
import { metrics } from "@opentelemetry/api"
|
||||
|
||||
const meter = metrics.getMeter("trpc.hotels")
|
||||
export const getHotelCounter = meter.createCounter("trpc.hotel.get")
|
||||
export const getHotelSuccessCounter = meter.createCounter(
|
||||
"trpc.hotel.get-success"
|
||||
)
|
||||
export const getHotelFailCounter = meter.createCounter("trpc.hotel.get-fail")
|
||||
|
||||
export const getPackagesCounter = meter.createCounter("trpc.hotel.packages.get")
|
||||
export const getPackagesSuccessCounter = meter.createCounter(
|
||||
"trpc.hotel.packages.get-success"
|
||||
)
|
||||
export const getPackagesFailCounter = meter.createCounter(
|
||||
"trpc.hotel.packages.get-fail"
|
||||
)
|
||||
|
||||
export const hotelsAvailabilityCounter = meter.createCounter(
|
||||
"trpc.hotel.availability.hotels"
|
||||
)
|
||||
export const hotelsAvailabilitySuccessCounter = meter.createCounter(
|
||||
"trpc.hotel.availability.hotels-success"
|
||||
)
|
||||
export const hotelsAvailabilityFailCounter = meter.createCounter(
|
||||
"trpc.hotel.availability.hotels-fail"
|
||||
)
|
||||
|
||||
export const hotelsByHotelIdAvailabilityCounter = meter.createCounter(
|
||||
"trpc.hotel.availability.hotels-by-hotel-id"
|
||||
)
|
||||
export const hotelsByHotelIdAvailabilitySuccessCounter = meter.createCounter(
|
||||
"trpc.hotel.availability.hotels-by-hotel-id-success"
|
||||
)
|
||||
export const hotelsByHotelIdAvailabilityFailCounter = meter.createCounter(
|
||||
"trpc.hotel.availability.hotels-by-hotel-id-fail"
|
||||
)
|
||||
|
||||
export const selectedRoomAvailabilityCounter = meter.createCounter(
|
||||
"trpc.hotel.availability.room"
|
||||
)
|
||||
export const selectedRoomAvailabilitySuccessCounter = meter.createCounter(
|
||||
"trpc.hotel.availability.room-success"
|
||||
)
|
||||
export const selectedRoomAvailabilityFailCounter = meter.createCounter(
|
||||
"trpc.hotel.availability.room-fail"
|
||||
)
|
||||
|
||||
export const breakfastPackagesCounter = meter.createCounter(
|
||||
"trpc.package.breakfast"
|
||||
)
|
||||
export const breakfastPackagesSuccessCounter = meter.createCounter(
|
||||
"trpc.package.breakfast-success"
|
||||
)
|
||||
export const breakfastPackagesFailCounter = meter.createCounter(
|
||||
"trpc.package.breakfast-fail"
|
||||
)
|
||||
|
||||
export const getHotelsCounter = meter.createCounter("trpc.hotel.hotels.get")
|
||||
export const getHotelsSuccessCounter = meter.createCounter(
|
||||
"trpc.hotel.hotels.get-success"
|
||||
)
|
||||
export const getHotelsFailCounter = meter.createCounter(
|
||||
"trpc.hotel.hotels.get-fail"
|
||||
)
|
||||
|
||||
export const getHotelIdsCounter = meter.createCounter(
|
||||
"trpc.hotel.hotel-ids.get"
|
||||
)
|
||||
export const getHotelIdsSuccessCounter = meter.createCounter(
|
||||
"trpc.hotel.hotel-ids.get-success"
|
||||
)
|
||||
export const getHotelIdsFailCounter = meter.createCounter(
|
||||
"trpc.hotel.hotel-ids.get-fail"
|
||||
)
|
||||
|
||||
export const nearbyHotelIdsCounter = meter.createCounter(
|
||||
"trpc.hotel.nearby-hotel-ids.get"
|
||||
)
|
||||
export const nearbyHotelIdsSuccessCounter = meter.createCounter(
|
||||
"trpc.hotel.nearby-hotel-ids.get-success"
|
||||
)
|
||||
export const nearbyHotelIdsFailCounter = meter.createCounter(
|
||||
"trpc.hotel.nearby-hotel-ids.get-fail"
|
||||
)
|
||||
|
||||
export const meetingRoomsCounter = meter.createCounter(
|
||||
"trpc.hotels.meetingRooms"
|
||||
)
|
||||
export const meetingRoomsSuccessCounter = meter.createCounter(
|
||||
"trpc.hotels.meetingRooms-success"
|
||||
)
|
||||
export const meetingRoomsFailCounter = meter.createCounter(
|
||||
"trpc.hotels.meetingRooms-fail"
|
||||
)
|
||||
|
||||
export const additionalDataCounter = meter.createCounter(
|
||||
"trpc.hotels.additionalData"
|
||||
)
|
||||
export const additionalDataSuccessCounter = meter.createCounter(
|
||||
"trpc.hotels.additionalData-success"
|
||||
)
|
||||
export const additionalDataFailCounter = meter.createCounter(
|
||||
"trpc.hotels.additionalData-fail"
|
||||
)
|
||||
|
||||
export const locationsUrlsCounter = meter.createCounter(
|
||||
"trpc.hotels.locations.urls"
|
||||
)
|
||||
export const locationsUrlsSuccessCounter = meter.createCounter(
|
||||
"trpc.hotels.locations.urls-success"
|
||||
)
|
||||
export const locationsUrlsFailCounter = meter.createCounter(
|
||||
"trpc.hotels.locations.urls-fail"
|
||||
)
|
||||
@@ -6,6 +6,7 @@ import { Lang } from "@/constants/languages"
|
||||
import { env } from "@/env/server"
|
||||
import * as api from "@/lib/api"
|
||||
import { badRequestError } from "@/server/errors/trpc"
|
||||
import { createCounter } from "@/server/telemetry"
|
||||
import { toApiLang } from "@/server/utils"
|
||||
|
||||
import { generateChildrenString } from "@/components/HotelReservation/utils"
|
||||
@@ -13,8 +14,7 @@ import { getCacheClient } from "@/services/dataCache"
|
||||
import { cache } from "@/utils/cache"
|
||||
|
||||
import { getHotelPageUrls } from "../contentstack/hotelPage/utils"
|
||||
import { type RoomFeaturesInput, roomPackagesInputSchema } from "./input"
|
||||
import { metrics } from "./metrics"
|
||||
import { type RoomFeaturesInput } from "./input"
|
||||
import {
|
||||
type Cities,
|
||||
citiesByCountrySchema,
|
||||
@@ -38,12 +38,12 @@ import type {
|
||||
DestinationPagesHotelData,
|
||||
Room as RoomCategory,
|
||||
} from "@/types/hotel"
|
||||
import type { PackagesInput } from "@/types/requests/packages"
|
||||
import type { PackagesOutput } from "@/types/requests/packages"
|
||||
import type {
|
||||
HotelsAvailabilityInputSchema,
|
||||
HotelsByHotelIdsAvailabilityInputSchema,
|
||||
RoomsAvailabilityInputRoom,
|
||||
RoomsAvailabilityInputSchema,
|
||||
RoomsAvailabilityOutputSchema,
|
||||
} from "@/types/trpc/routers/hotel/availability"
|
||||
import type { HotelInput } from "@/types/trpc/routers/hotel/hotel"
|
||||
import type {
|
||||
@@ -332,18 +332,23 @@ export async function getHotelIdsByCityId({
|
||||
cityId: string
|
||||
serviceToken: string
|
||||
}) {
|
||||
const getHotelIdsByCityIdCounter = createCounter(
|
||||
"hotel",
|
||||
"getHotelIdsByCityId"
|
||||
)
|
||||
const metricsGetHotelIdsByCityId = getHotelIdsByCityIdCounter.init({
|
||||
cityId,
|
||||
})
|
||||
|
||||
metricsGetHotelIdsByCityId.start()
|
||||
|
||||
const cacheClient = await getCacheClient()
|
||||
return await cacheClient.cacheOrGet(
|
||||
const result = await cacheClient.cacheOrGet(
|
||||
`${cityId}:hotelsByCityId`,
|
||||
async () => {
|
||||
const searchParams = new URLSearchParams({
|
||||
city: cityId,
|
||||
})
|
||||
metrics.hotelIds.counter.add(1, { params: searchParams.toString() })
|
||||
console.info(
|
||||
"api.hotel.hotel-ids start",
|
||||
JSON.stringify({ params: searchParams.toString() })
|
||||
)
|
||||
|
||||
const apiResponse = await api.get(
|
||||
api.endpoints.v1.Hotel.hotels,
|
||||
@@ -356,59 +361,25 @@ export async function getHotelIdsByCityId({
|
||||
)
|
||||
|
||||
if (!apiResponse.ok) {
|
||||
const responseMessage = await apiResponse.text()
|
||||
metrics.hotelIds.fail.add(1, {
|
||||
params: searchParams.toString(),
|
||||
error_type: "http_error",
|
||||
error: responseMessage,
|
||||
})
|
||||
console.error(
|
||||
"api.hotel.hotel-ids fetch error",
|
||||
JSON.stringify({
|
||||
params: searchParams.toString(),
|
||||
error: {
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text: responseMessage,
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
await metricsGetHotelIdsByCityId.httpError(apiResponse)
|
||||
throw new Error("Unable to fetch hotelIds by cityId")
|
||||
}
|
||||
|
||||
const apiJson = await apiResponse.json()
|
||||
const validatedHotelIds = getHotelIdsSchema.safeParse(apiJson)
|
||||
if (!validatedHotelIds.success) {
|
||||
metrics.hotelIds.fail.add(1, {
|
||||
params: searchParams.toString(),
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(validatedHotelIds.error),
|
||||
})
|
||||
console.error(
|
||||
"api.hotel.hotel-ids validation error",
|
||||
JSON.stringify({
|
||||
params: searchParams.toString(),
|
||||
error: validatedHotelIds.error,
|
||||
})
|
||||
)
|
||||
|
||||
metricsGetHotelIdsByCityId.validationError(validatedHotelIds.error)
|
||||
throw new Error("Unable to parse data for hotelIds by cityId")
|
||||
}
|
||||
|
||||
metrics.hotelIds.success.add(1, { cityId })
|
||||
console.info(
|
||||
"api.hotel.hotel-ids success",
|
||||
JSON.stringify({
|
||||
params: searchParams.toString(),
|
||||
response: validatedHotelIds.data,
|
||||
})
|
||||
)
|
||||
|
||||
return validatedHotelIds.data
|
||||
},
|
||||
env.CACHE_TIME_HOTELS
|
||||
)
|
||||
|
||||
metricsGetHotelIdsByCityId.success()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
export async function getHotelIdsByCountry({
|
||||
@@ -418,17 +389,22 @@ export async function getHotelIdsByCountry({
|
||||
country: string
|
||||
serviceToken: string
|
||||
}) {
|
||||
const getHotelIdsByCountryCounter = createCounter(
|
||||
"hotel",
|
||||
"getHotelIdsByCountry"
|
||||
)
|
||||
|
||||
const metricsGetHotelIdsByCountry = getHotelIdsByCountryCounter.init({
|
||||
country,
|
||||
})
|
||||
|
||||
metricsGetHotelIdsByCountry.start()
|
||||
|
||||
const cacheClient = await getCacheClient()
|
||||
|
||||
return await cacheClient.cacheOrGet(
|
||||
const result = await cacheClient.cacheOrGet(
|
||||
`${country}:hotelsByCountry`,
|
||||
async () => {
|
||||
metrics.hotelIds.counter.add(1, { country })
|
||||
console.info(
|
||||
"api.hotel.hotel-ids start",
|
||||
JSON.stringify({ query: { country } })
|
||||
)
|
||||
|
||||
const hotelIdsParams = new URLSearchParams({
|
||||
country,
|
||||
})
|
||||
@@ -444,55 +420,25 @@ export async function getHotelIdsByCountry({
|
||||
)
|
||||
|
||||
if (!apiResponse.ok) {
|
||||
const responseMessage = await apiResponse.text()
|
||||
metrics.hotelIds.fail.add(1, {
|
||||
country,
|
||||
error_type: "http_error",
|
||||
error: responseMessage,
|
||||
})
|
||||
console.error(
|
||||
"api.hotel.hotel-ids fetch error",
|
||||
JSON.stringify({
|
||||
query: { country },
|
||||
error: {
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text: responseMessage,
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
await metricsGetHotelIdsByCountry.httpError(apiResponse)
|
||||
throw new Error("Unable to fetch hotelIds by country")
|
||||
}
|
||||
|
||||
const apiJson = await apiResponse.json()
|
||||
const validatedHotelIds = getHotelIdsSchema.safeParse(apiJson)
|
||||
if (!validatedHotelIds.success) {
|
||||
metrics.hotelIds.fail.add(1, {
|
||||
country,
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(validatedHotelIds.error),
|
||||
})
|
||||
console.error(
|
||||
"api.hotel.hotel-ids validation error",
|
||||
JSON.stringify({
|
||||
query: { country },
|
||||
error: validatedHotelIds.error,
|
||||
})
|
||||
)
|
||||
metricsGetHotelIdsByCountry.validationError(validatedHotelIds.error)
|
||||
throw new Error("Unable to parse hotelIds by country")
|
||||
}
|
||||
|
||||
metrics.hotelIds.success.add(1, { country })
|
||||
console.info(
|
||||
"api.hotel.hotel-ids success",
|
||||
JSON.stringify({ query: { country } })
|
||||
)
|
||||
|
||||
return validatedHotelIds.data
|
||||
},
|
||||
env.CACHE_TIME_HOTELS
|
||||
)
|
||||
|
||||
metricsGetHotelIdsByCountry.success()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
export async function getHotelIdsByCityIdentifier(
|
||||
@@ -631,128 +577,84 @@ function findProduct(product: Products, rateDefinition: RateDefinition) {
|
||||
|
||||
export const getHotel = cache(
|
||||
async (input: HotelInput, serviceToken: string) => {
|
||||
const callable = async function (
|
||||
hotelId: HotelInput["hotelId"],
|
||||
language: HotelInput["language"],
|
||||
isCardOnlyPayment?: HotelInput["isCardOnlyPayment"]
|
||||
) {
|
||||
/**
|
||||
* Since API expects the params appended and not just
|
||||
* a comma separated string we need to initialize the
|
||||
* SearchParams with a sequence of pairs
|
||||
* (include=City&include=NearbyHotels&include=Restaurants etc.)
|
||||
**/
|
||||
const params = new URLSearchParams([
|
||||
["include", "AdditionalData"],
|
||||
["include", "City"],
|
||||
["include", "NearbyHotels"],
|
||||
["include", "Restaurants"],
|
||||
["include", "RoomCategories"],
|
||||
["language", toApiLang(language)],
|
||||
])
|
||||
metrics.hotel.counter.add(1, {
|
||||
hotelId,
|
||||
language,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.hotelData start",
|
||||
JSON.stringify({ query: { hotelId, params: params.toString() } })
|
||||
)
|
||||
const { hotelId, language, isCardOnlyPayment } = input
|
||||
|
||||
const apiResponse = await api.get(
|
||||
api.endpoints.v1.Hotel.Hotels.hotel(hotelId),
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${serviceToken}`,
|
||||
},
|
||||
},
|
||||
params
|
||||
)
|
||||
const getHotelCounter = createCounter("hotel", "getHotel")
|
||||
const metricsGetHotel = getHotelCounter.init({
|
||||
hotelId,
|
||||
language,
|
||||
isCardOnlyPayment,
|
||||
})
|
||||
|
||||
if (!apiResponse.ok) {
|
||||
const text = await apiResponse.text()
|
||||
metrics.hotel.fail.add(1, {
|
||||
hotelId,
|
||||
language,
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
}),
|
||||
})
|
||||
console.error(
|
||||
"api.hotels.hotelData error",
|
||||
JSON.stringify({
|
||||
query: { hotelId, params: params.toString() },
|
||||
error: {
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
},
|
||||
})
|
||||
)
|
||||
return null
|
||||
}
|
||||
|
||||
const apiJson = await apiResponse.json()
|
||||
const validateHotelData = hotelSchema.safeParse(apiJson)
|
||||
|
||||
if (!validateHotelData.success) {
|
||||
metrics.hotel.fail.add(1, {
|
||||
hotelId,
|
||||
language,
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(validateHotelData.error),
|
||||
})
|
||||
|
||||
console.error(
|
||||
"api.hotels.hotelData validation error",
|
||||
JSON.stringify({
|
||||
query: { hotelId, params: params.toString() },
|
||||
error: validateHotelData.error,
|
||||
})
|
||||
)
|
||||
throw badRequestError()
|
||||
}
|
||||
|
||||
metrics.hotel.success.add(1, {
|
||||
hotelId,
|
||||
language,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.hotelData success",
|
||||
JSON.stringify({
|
||||
query: { hotelId, params: params.toString() },
|
||||
})
|
||||
)
|
||||
const hotelData = validateHotelData.data
|
||||
|
||||
if (isCardOnlyPayment) {
|
||||
hotelData.hotel.merchantInformationData.alternatePaymentOptions = []
|
||||
}
|
||||
|
||||
const gallery = hotelData.additionalData?.gallery
|
||||
if (gallery) {
|
||||
const smallerImages = gallery.smallerImages
|
||||
const hotelGalleryImages =
|
||||
hotelData.hotel.hotelType === HotelTypeEnum.Signature
|
||||
? smallerImages.slice(0, 10)
|
||||
: smallerImages.slice(0, 6)
|
||||
hotelData.hotel.galleryImages = hotelGalleryImages
|
||||
}
|
||||
|
||||
return hotelData
|
||||
}
|
||||
metricsGetHotel.start()
|
||||
|
||||
const cacheClient = await getCacheClient()
|
||||
return await cacheClient.cacheOrGet(
|
||||
|
||||
const result = await cacheClient.cacheOrGet(
|
||||
`${input.language}:hotel:${input.hotelId}:${!!input.isCardOnlyPayment}`,
|
||||
async () => {
|
||||
return callable(input.hotelId, input.language, input.isCardOnlyPayment)
|
||||
/**
|
||||
* Since API expects the params appended and not just
|
||||
* a comma separated string we need to initialize the
|
||||
* SearchParams with a sequence of pairs
|
||||
* (include=City&include=NearbyHotels&include=Restaurants etc.)
|
||||
**/
|
||||
const params = new URLSearchParams([
|
||||
["include", "AdditionalData"],
|
||||
["include", "City"],
|
||||
["include", "NearbyHotels"],
|
||||
["include", "Restaurants"],
|
||||
["include", "RoomCategories"],
|
||||
["language", toApiLang(language)],
|
||||
])
|
||||
|
||||
const apiResponse = await api.get(
|
||||
api.endpoints.v1.Hotel.Hotels.hotel(hotelId),
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${serviceToken}`,
|
||||
},
|
||||
},
|
||||
params
|
||||
)
|
||||
|
||||
if (!apiResponse.ok) {
|
||||
await metricsGetHotel.httpError(apiResponse)
|
||||
return null
|
||||
}
|
||||
|
||||
const apiJson = await apiResponse.json()
|
||||
const validateHotelData = hotelSchema.safeParse(apiJson)
|
||||
|
||||
if (!validateHotelData.success) {
|
||||
metricsGetHotel.validationError(validateHotelData.error)
|
||||
throw badRequestError()
|
||||
}
|
||||
|
||||
const hotelData = validateHotelData.data
|
||||
|
||||
if (isCardOnlyPayment) {
|
||||
hotelData.hotel.merchantInformationData.alternatePaymentOptions = []
|
||||
}
|
||||
|
||||
const gallery = hotelData.additionalData?.gallery
|
||||
if (gallery) {
|
||||
const smallerImages = gallery.smallerImages
|
||||
const hotelGalleryImages =
|
||||
hotelData.hotel.hotelType === HotelTypeEnum.Signature
|
||||
? smallerImages.slice(0, 10)
|
||||
: smallerImages.slice(0, 6)
|
||||
hotelData.hotel.galleryImages = hotelGalleryImages
|
||||
}
|
||||
|
||||
return hotelData
|
||||
},
|
||||
env.CACHE_TIME_HOTELS
|
||||
)
|
||||
|
||||
metricsGetHotel.success()
|
||||
|
||||
return result
|
||||
}
|
||||
)
|
||||
|
||||
@@ -781,19 +683,25 @@ export async function getHotelsAvailabilityByCity(
|
||||
...(redemption ? { isRedemption: "true" } : {}),
|
||||
language: apiLang,
|
||||
}
|
||||
metrics.hotelsAvailability.counter.add(1, {
|
||||
cityId,
|
||||
roomStayStartDate,
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
bookingCode,
|
||||
redemption,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.hotelsAvailability start",
|
||||
JSON.stringify({ query: { cityId, params } })
|
||||
|
||||
const getHotelsAvailabilityByCityCounter = createCounter(
|
||||
"hotel",
|
||||
"getHotelsAvailabilityByCity"
|
||||
)
|
||||
const metricsGetHotelsAvailabilityByCity =
|
||||
getHotelsAvailabilityByCityCounter.init({
|
||||
apiLang,
|
||||
cityId,
|
||||
roomStayStartDate,
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
bookingCode,
|
||||
redemption,
|
||||
})
|
||||
|
||||
metricsGetHotelsAvailabilityByCity.start()
|
||||
|
||||
const apiResponse = await api.get(
|
||||
api.endpoints.v1.Availability.city(cityId),
|
||||
{
|
||||
@@ -804,74 +712,19 @@ export async function getHotelsAvailabilityByCity(
|
||||
params
|
||||
)
|
||||
if (!apiResponse.ok) {
|
||||
const text = await apiResponse.text()
|
||||
metrics.hotelsAvailability.fail.add(1, {
|
||||
cityId,
|
||||
roomStayStartDate,
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
bookingCode,
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
}),
|
||||
})
|
||||
console.error(
|
||||
"api.hotels.hotelsAvailability error",
|
||||
JSON.stringify({
|
||||
query: { cityId, params },
|
||||
error: {
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
await metricsGetHotelsAvailabilityByCity.httpError(apiResponse)
|
||||
throw new Error("Failed to fetch hotels availability by city")
|
||||
}
|
||||
|
||||
const apiJson = await apiResponse.json()
|
||||
const validateAvailabilityData = hotelsAvailabilitySchema.safeParse(apiJson)
|
||||
if (!validateAvailabilityData.success) {
|
||||
metrics.hotelsAvailability.fail.add(1, {
|
||||
cityId,
|
||||
roomStayStartDate,
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
bookingCode,
|
||||
redemption,
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(validateAvailabilityData.error),
|
||||
})
|
||||
console.error(
|
||||
"api.hotels.hotelsAvailability validation error",
|
||||
JSON.stringify({
|
||||
query: { cityId, params },
|
||||
error: validateAvailabilityData.error,
|
||||
})
|
||||
metricsGetHotelsAvailabilityByCity.validationError(
|
||||
validateAvailabilityData.error
|
||||
)
|
||||
throw badRequestError()
|
||||
}
|
||||
metrics.hotelsAvailability.success.add(1, {
|
||||
cityId,
|
||||
roomStayStartDate,
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
bookingCode,
|
||||
redemption,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.hotelsAvailability success",
|
||||
JSON.stringify({
|
||||
query: { cityId, params: params },
|
||||
})
|
||||
)
|
||||
|
||||
if (redemption) {
|
||||
validateAvailabilityData.data.data.forEach((data) => {
|
||||
data.attributes.productType?.redemptions?.forEach((r) => {
|
||||
@@ -880,11 +733,15 @@ export async function getHotelsAvailabilityByCity(
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
const result = {
|
||||
availability: validateAvailabilityData.data.data.flatMap(
|
||||
(hotels) => hotels.attributes
|
||||
),
|
||||
}
|
||||
|
||||
metricsGetHotelsAvailabilityByCity.success()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
export async function getHotelsAvailabilityByHotelIds(
|
||||
@@ -910,8 +767,26 @@ export async function getHotelsAvailabilityByHotelIds(
|
||||
["language", apiLang],
|
||||
])
|
||||
|
||||
const getHotelsAvailabilityByHotelIdsCounter = createCounter(
|
||||
"hotel",
|
||||
"getHotelsAvailabilityByHotelIds"
|
||||
)
|
||||
const metricsGetHotelsAvailabilityByHotelIds =
|
||||
getHotelsAvailabilityByHotelIdsCounter.init({
|
||||
apiLang,
|
||||
hotelIds,
|
||||
roomStayStartDate,
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
bookingCode,
|
||||
})
|
||||
|
||||
metricsGetHotelsAvailabilityByHotelIds.start()
|
||||
|
||||
const cacheClient = await getCacheClient()
|
||||
return cacheClient.cacheOrGet(
|
||||
|
||||
const result = cacheClient.cacheOrGet(
|
||||
`${apiLang}:hotels:availability:${hotelIds.join(",")}:${roomStayStartDate}:${roomStayEndDate}:${adults}:${children}:${bookingCode}`,
|
||||
async () => {
|
||||
/**
|
||||
@@ -924,18 +799,7 @@ export async function getHotelsAvailabilityByHotelIds(
|
||||
hotelIds.forEach((hotelId) =>
|
||||
params.append("hotelIds", hotelId.toString())
|
||||
)
|
||||
metrics.hotelsByHotelIdAvailability.counter.add(1, {
|
||||
hotelIds,
|
||||
roomStayStartDate,
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
bookingCode,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.hotelsByHotelIdAvailability start",
|
||||
JSON.stringify({ query: { params } })
|
||||
)
|
||||
|
||||
const apiResponse = await api.get(
|
||||
api.endpoints.v1.Availability.hotels(),
|
||||
{
|
||||
@@ -946,72 +810,20 @@ export async function getHotelsAvailabilityByHotelIds(
|
||||
params
|
||||
)
|
||||
if (!apiResponse.ok) {
|
||||
const text = await apiResponse.text()
|
||||
metrics.hotelsByHotelIdAvailability.fail.add(1, {
|
||||
hotelIds,
|
||||
roomStayStartDate,
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
bookingCode,
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
}),
|
||||
})
|
||||
console.error(
|
||||
"api.hotels.hotelsByHotelIdAvailability error",
|
||||
JSON.stringify({
|
||||
query: { params },
|
||||
error: {
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
await metricsGetHotelsAvailabilityByHotelIds.httpError(apiResponse)
|
||||
throw new Error("Failed to fetch hotels availability by hotelIds")
|
||||
}
|
||||
|
||||
const apiJson = await apiResponse.json()
|
||||
const validateAvailabilityData =
|
||||
hotelsAvailabilitySchema.safeParse(apiJson)
|
||||
if (!validateAvailabilityData.success) {
|
||||
metrics.hotelsByHotelIdAvailability.fail.add(1, {
|
||||
hotelIds,
|
||||
roomStayStartDate,
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
bookingCode,
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(validateAvailabilityData.error),
|
||||
})
|
||||
console.error(
|
||||
"api.hotels.hotelsByHotelIdAvailability validation error",
|
||||
JSON.stringify({
|
||||
query: { params },
|
||||
error: validateAvailabilityData.error,
|
||||
})
|
||||
metricsGetHotelsAvailabilityByHotelIds.validationError(
|
||||
validateAvailabilityData.error
|
||||
)
|
||||
throw badRequestError()
|
||||
}
|
||||
metrics.hotelsByHotelIdAvailability.success.add(1, {
|
||||
hotelIds,
|
||||
roomStayStartDate,
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
bookingCode,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.hotelsByHotelIdAvailability success",
|
||||
JSON.stringify({
|
||||
query: { params },
|
||||
})
|
||||
)
|
||||
|
||||
return {
|
||||
availability: validateAvailabilityData.data.data.flatMap(
|
||||
(hotels) => hotels.attributes
|
||||
@@ -1020,6 +832,10 @@ export async function getHotelsAvailabilityByHotelIds(
|
||||
},
|
||||
env.CACHE_TIME_CITY_SEARCH
|
||||
)
|
||||
|
||||
metricsGetHotelsAvailabilityByHotelIds.success()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
async function getRoomFeaturesInventory(
|
||||
@@ -1034,23 +850,32 @@ async function getRoomFeaturesInventory(
|
||||
roomFeatureCodes,
|
||||
startDate,
|
||||
} = input
|
||||
|
||||
const params = {
|
||||
adults,
|
||||
hotelId,
|
||||
roomFeatureCode: roomFeatureCodes,
|
||||
roomStayEndDate: endDate,
|
||||
roomStayStartDate: startDate,
|
||||
...(childrenInRoom?.length && {
|
||||
children: generateChildrenString(childrenInRoom),
|
||||
}),
|
||||
}
|
||||
|
||||
const getRoomFeaturesInventoryCounter = createCounter(
|
||||
"hotel",
|
||||
"getRoomFeaturesInventory"
|
||||
)
|
||||
const metricsGetRoomFeaturesInventory =
|
||||
getRoomFeaturesInventoryCounter.init(params)
|
||||
|
||||
metricsGetRoomFeaturesInventory.start()
|
||||
|
||||
const cacheClient = await getCacheClient()
|
||||
return cacheClient.cacheOrGet(
|
||||
|
||||
const result = cacheClient.cacheOrGet(
|
||||
stringify(input),
|
||||
async function () {
|
||||
const params = {
|
||||
adults,
|
||||
hotelId,
|
||||
roomFeatureCode: roomFeatureCodes,
|
||||
roomStayEndDate: endDate,
|
||||
roomStayStartDate: startDate,
|
||||
...(childrenInRoom?.length && {
|
||||
children: generateChildrenString(childrenInRoom),
|
||||
}),
|
||||
}
|
||||
|
||||
metrics.roomFeatures.counter.add(1, params)
|
||||
|
||||
const apiResponse = await api.get(
|
||||
api.endpoints.v1.Availability.roomFeatures(hotelId),
|
||||
{
|
||||
@@ -1062,67 +887,45 @@ async function getRoomFeaturesInventory(
|
||||
)
|
||||
|
||||
if (!apiResponse.ok) {
|
||||
const text = apiResponse.text()
|
||||
console.error(
|
||||
"api.availability.roomfeature error",
|
||||
JSON.stringify({
|
||||
query: { hotelId, params },
|
||||
error: {
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
},
|
||||
})
|
||||
)
|
||||
metrics.roomFeatures.fail.add(1, params)
|
||||
await metricsGetRoomFeaturesInventory.httpError(apiResponse)
|
||||
return null
|
||||
}
|
||||
|
||||
const data = await apiResponse.json()
|
||||
const validatedRoomFeaturesData = roomFeaturesSchema.safeParse(data)
|
||||
if (!validatedRoomFeaturesData.success) {
|
||||
console.error(
|
||||
"api.availability.roomfeature error",
|
||||
JSON.stringify({
|
||||
query: { hotelId, params },
|
||||
error: validatedRoomFeaturesData.error,
|
||||
})
|
||||
metricsGetRoomFeaturesInventory.validationError(
|
||||
validatedRoomFeaturesData.error
|
||||
)
|
||||
return null
|
||||
}
|
||||
|
||||
metrics.roomFeatures.success.add(1, params)
|
||||
|
||||
return validatedRoomFeaturesData.data
|
||||
},
|
||||
"5m"
|
||||
)
|
||||
|
||||
metricsGetRoomFeaturesInventory.success()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
export async function getPackages(
|
||||
rawInput: PackagesInput,
|
||||
serviceToken: string
|
||||
) {
|
||||
const parsedInput = roomPackagesInputSchema.safeParse(rawInput)
|
||||
if (!parsedInput.success) {
|
||||
console.info(`Failed to parse input for Get Packages`)
|
||||
console.error(parsedInput.error)
|
||||
return null
|
||||
}
|
||||
const input = parsedInput.data
|
||||
export async function getPackages(input: PackagesOutput, serviceToken: string) {
|
||||
const { adults, children, endDate, hotelId, lang, packageCodes, startDate } =
|
||||
input
|
||||
|
||||
const getPackagesCounter = createCounter("hotel", "getPackages")
|
||||
const metricsGetPackages = getPackagesCounter.init({
|
||||
input,
|
||||
})
|
||||
|
||||
metricsGetPackages.start()
|
||||
|
||||
const cacheClient = await getCacheClient()
|
||||
return cacheClient.cacheOrGet(
|
||||
|
||||
const result = cacheClient.cacheOrGet(
|
||||
stringify(input),
|
||||
async function () {
|
||||
const {
|
||||
adults,
|
||||
children,
|
||||
endDate,
|
||||
hotelId,
|
||||
lang,
|
||||
packageCodes,
|
||||
startDate,
|
||||
} = input
|
||||
const apiLang = toApiLang(lang)
|
||||
|
||||
const searchParams = new URLSearchParams({
|
||||
@@ -1137,16 +940,6 @@ export async function getPackages(
|
||||
searchParams.append("packageCodes", code)
|
||||
})
|
||||
|
||||
const params = searchParams.toString()
|
||||
|
||||
metrics.packages.counter.add(1, {
|
||||
hotelId,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.packages start",
|
||||
JSON.stringify({ query: { hotelId, params } })
|
||||
)
|
||||
|
||||
const apiResponse = await api.get(
|
||||
api.endpoints.v1.Package.Packages.hotel(hotelId),
|
||||
{
|
||||
@@ -1158,56 +951,29 @@ export async function getPackages(
|
||||
)
|
||||
|
||||
if (!apiResponse.ok) {
|
||||
metrics.packages.fail.add(1, {
|
||||
hotelId,
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
}),
|
||||
})
|
||||
console.error(
|
||||
"api.hotels.packages error",
|
||||
JSON.stringify({ query: { hotelId, params } })
|
||||
)
|
||||
await metricsGetPackages.httpError(apiResponse)
|
||||
return null
|
||||
}
|
||||
|
||||
const apiJson = await apiResponse.json()
|
||||
const validatedPackagesData = packagesSchema.safeParse(apiJson)
|
||||
if (!validatedPackagesData.success) {
|
||||
metrics.packages.fail.add(1, {
|
||||
hotelId,
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(validatedPackagesData.error),
|
||||
})
|
||||
|
||||
console.error(
|
||||
"api.hotels.packages validation error",
|
||||
JSON.stringify({
|
||||
query: { hotelId, params },
|
||||
error: validatedPackagesData.error,
|
||||
})
|
||||
)
|
||||
metricsGetPackages.validationError(validatedPackagesData.error)
|
||||
return null
|
||||
}
|
||||
|
||||
metrics.packages.success.add(1, {
|
||||
hotelId,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.packages success",
|
||||
JSON.stringify({ query: { hotelId, params: params } })
|
||||
)
|
||||
|
||||
return validatedPackagesData.data
|
||||
},
|
||||
"3h"
|
||||
)
|
||||
|
||||
metricsGetPackages.success()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
export async function getRoomsAvailability(
|
||||
input: RoomsAvailabilityInputSchema,
|
||||
input: RoomsAvailabilityOutputSchema,
|
||||
token: string,
|
||||
serviceToken: string,
|
||||
userPoints: number | undefined
|
||||
@@ -1219,27 +985,18 @@ export async function getRoomsAvailability(
|
||||
|
||||
const redemption = searchType === REDEMPTION
|
||||
|
||||
const apiLang = toApiLang(lang)
|
||||
|
||||
const kids = rooms
|
||||
.map((r) => r.childrenInRoom)
|
||||
.filter(Boolean)
|
||||
.map((kid) => JSON.stringify(kid))
|
||||
const metricsData = {
|
||||
adultsCount: rooms.map((r) => r.adults),
|
||||
bookingCode,
|
||||
childArray: kids.length ? kids : undefined,
|
||||
hotelId,
|
||||
roomStayEndDate: toDate,
|
||||
roomStayStartDate: fromDate,
|
||||
}
|
||||
|
||||
metrics.roomsAvailability.counter.add(1, metricsData)
|
||||
|
||||
console.info(
|
||||
"api.hotels.roomsAvailability start",
|
||||
JSON.stringify({ query: { hotelId, params: metricsData } })
|
||||
const getRoomsAvailabilityCounter = createCounter(
|
||||
"hotel",
|
||||
"getRoomsAvailability"
|
||||
)
|
||||
const metricsGetRoomsAvailability = getRoomsAvailabilityCounter.init({
|
||||
input,
|
||||
redemption,
|
||||
})
|
||||
|
||||
metricsGetRoomsAvailability.start()
|
||||
|
||||
const apiLang = toApiLang(lang)
|
||||
|
||||
const baseCacheKey = {
|
||||
bookingCode,
|
||||
@@ -1257,7 +1014,7 @@ export async function getRoomsAvailability(
|
||||
...baseCacheKey,
|
||||
room,
|
||||
}
|
||||
return cacheClient.cacheOrGet(
|
||||
const result = cacheClient.cacheOrGet(
|
||||
stringify(cacheKey),
|
||||
async function () {
|
||||
{
|
||||
@@ -1287,9 +1044,8 @@ export async function getRoomsAvailability(
|
||||
)
|
||||
|
||||
if (!apiResponse.ok) {
|
||||
await metricsGetRoomsAvailability.httpError(apiResponse)
|
||||
const text = await apiResponse.text()
|
||||
metrics.roomsAvailability.fail.add(1, metricsData)
|
||||
console.error("Failed API call", { params, text })
|
||||
return { error: "http_error", details: text }
|
||||
}
|
||||
|
||||
@@ -1297,11 +1053,10 @@ export async function getRoomsAvailability(
|
||||
const validateAvailabilityData =
|
||||
roomsAvailabilitySchema.safeParse(apiJson)
|
||||
if (!validateAvailabilityData.success) {
|
||||
console.error("Validation error", {
|
||||
params,
|
||||
error: validateAvailabilityData.error,
|
||||
})
|
||||
metrics.roomsAvailability.fail.add(1, metricsData)
|
||||
metricsGetRoomsAvailability.validationError(
|
||||
validateAvailabilityData.error
|
||||
)
|
||||
|
||||
return {
|
||||
error: "validation_error",
|
||||
details: validateAvailabilityData.error,
|
||||
@@ -1323,7 +1078,7 @@ export async function getRoomsAvailability(
|
||||
const roomFeatures = await getPackages(
|
||||
{
|
||||
adults: room.adults,
|
||||
children: room.childrenInRoom?.length,
|
||||
children: room.childrenInRoom?.length || 0,
|
||||
endDate: input.booking.toDate,
|
||||
hotelId: input.booking.hotelId,
|
||||
lang,
|
||||
@@ -1387,9 +1142,10 @@ export async function getRoomsAvailability(
|
||||
},
|
||||
"1m"
|
||||
)
|
||||
|
||||
return result
|
||||
})
|
||||
)
|
||||
metrics.roomsAvailability.success.add(1, metricsData)
|
||||
|
||||
const data = availabilityResponses.map((availability) => {
|
||||
if (availability.status === "fulfilled") {
|
||||
@@ -1401,6 +1157,8 @@ export async function getRoomsAvailability(
|
||||
}
|
||||
})
|
||||
|
||||
metricsGetRoomsAvailability.success()
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user