Include more details when throwing errors for debugging in Sentry * WIP throw errors with more details for debugging in Sentry * Fix throwing response-data * Clearer message when a response fails * Add message to errors * better typings * . * Try to send profileID and membershipNumber to Sentry when we fail to parse the apiResponse * rename notFound -> notFoundError * Merge branch 'master' of bitbucket.org:scandic-swap/web into chore/add-error-details-for-sentry Approved-by: Linus Flood
170 lines
4.1 KiB
TypeScript
170 lines
4.1 KiB
TypeScript
import { getCacheClient } from "@scandic-hotels/common/dataCache"
|
|
import { createCounter } from "@scandic-hotels/common/telemetry"
|
|
|
|
import * as api from "../../../api"
|
|
import { notFoundError } from "../../../errors"
|
|
import {
|
|
GetRewards as GetRewards,
|
|
GetRewardsRef as GetRewardsRef,
|
|
} from "../../../graphql/Query/RewardsWithRedeem.graphql"
|
|
import { request } from "../../../graphql/request"
|
|
import {
|
|
generateLoyaltyConfigTag,
|
|
generateRefsResponseTag,
|
|
} from "../../../utils/generateTag"
|
|
import {
|
|
rewardRefsSchema,
|
|
validateApiAllTiersSchema,
|
|
validateCmsRewardsSchema,
|
|
} from "./output"
|
|
|
|
import type { Lang } from "@scandic-hotels/common/constants/language"
|
|
|
|
import type {
|
|
CMSRewardsResponse,
|
|
GetRewardRefsSchema,
|
|
} from "../../../types/reward"
|
|
|
|
export function getUniqueRewardIds(rewardIds: string[]) {
|
|
const uniqueRewardIds = new Set(rewardIds)
|
|
return Array.from(uniqueRewardIds)
|
|
}
|
|
|
|
/**
|
|
* Cached for 1 hour.
|
|
*/
|
|
export async function getCachedAllTierRewards(token: string) {
|
|
const cacheClient = await getCacheClient()
|
|
|
|
return await cacheClient.cacheOrGet(
|
|
"getAllTierRewards",
|
|
async () => {
|
|
const getApiRewardAllTiersCounter = createCounter(
|
|
"trpc.api.reward.allTiers"
|
|
)
|
|
const metricsGetApiRewardAllTiers = getApiRewardAllTiersCounter.init()
|
|
|
|
metricsGetApiRewardAllTiers.start()
|
|
|
|
const apiResponse = await api.get(
|
|
api.endpoints.v2.Profile.Reward.allTiers,
|
|
{
|
|
headers: {
|
|
Authorization: `Bearer ${token}`,
|
|
},
|
|
}
|
|
)
|
|
|
|
if (!apiResponse.ok) {
|
|
metricsGetApiRewardAllTiers.httpError(apiResponse)
|
|
throw apiResponse
|
|
}
|
|
|
|
const data = await apiResponse.json()
|
|
const validatedApiAllTierRewards =
|
|
validateApiAllTiersSchema.safeParse(data)
|
|
|
|
if (!validatedApiAllTierRewards.success) {
|
|
metricsGetApiRewardAllTiers.validationError(
|
|
validatedApiAllTierRewards.error
|
|
)
|
|
throw validatedApiAllTierRewards.error
|
|
}
|
|
|
|
metricsGetApiRewardAllTiers.success()
|
|
|
|
return validatedApiAllTierRewards.data
|
|
},
|
|
"1h"
|
|
)
|
|
}
|
|
|
|
export async function getCmsRewards(lang: Lang, rewardIds: string[]) {
|
|
if (!rewardIds.length) {
|
|
return null
|
|
}
|
|
|
|
const tags = rewardIds.map((id) =>
|
|
generateLoyaltyConfigTag(lang, "reward", id)
|
|
)
|
|
|
|
const getContentstackRewardAllRefsCounter = createCounter(
|
|
"trpc.contentstack.reward.all.refs"
|
|
)
|
|
const metricsGetContentstackRewardAllRefs =
|
|
getContentstackRewardAllRefsCounter.init({ lang, rewardIds })
|
|
|
|
metricsGetContentstackRewardAllRefs.start()
|
|
|
|
const refsResponse = await request<GetRewardRefsSchema>(
|
|
GetRewardsRef,
|
|
{
|
|
locale: lang,
|
|
rewardIds,
|
|
},
|
|
{
|
|
key: rewardIds.map((rewardId) => generateRefsResponseTag(lang, rewardId)),
|
|
ttl: "max",
|
|
}
|
|
)
|
|
|
|
if (!refsResponse.data) {
|
|
metricsGetContentstackRewardAllRefs.noDataError()
|
|
|
|
throw notFoundError({
|
|
message: "GetRewardsRef returned no data",
|
|
errorDetails: { lang, rewardIds },
|
|
})
|
|
}
|
|
|
|
const validatedRefsData = rewardRefsSchema.safeParse(refsResponse)
|
|
|
|
if (!validatedRefsData.success) {
|
|
metricsGetContentstackRewardAllRefs.validationError(validatedRefsData.error)
|
|
return null
|
|
}
|
|
|
|
metricsGetContentstackRewardAllRefs.success()
|
|
|
|
const getContentstackRewardAllCounter = createCounter(
|
|
"trpc.contentstack.reward.all"
|
|
)
|
|
const metricsGetContentstackRewardAll = getContentstackRewardAllCounter.init({
|
|
lang,
|
|
rewardIds,
|
|
})
|
|
|
|
const cmsRewardsResponse = await request<CMSRewardsResponse>(
|
|
GetRewards,
|
|
{
|
|
locale: lang,
|
|
rewardIds,
|
|
},
|
|
{
|
|
key: tags,
|
|
ttl: "max",
|
|
}
|
|
)
|
|
|
|
if (!cmsRewardsResponse.data) {
|
|
metricsGetContentstackRewardAll.noDataError()
|
|
|
|
throw notFoundError({
|
|
message: "GetRewards not found",
|
|
errorDetails: { lang, rewardIds },
|
|
})
|
|
}
|
|
|
|
const validatedCmsRewards =
|
|
validateCmsRewardsSchema.safeParse(cmsRewardsResponse)
|
|
|
|
if (!validatedCmsRewards.success) {
|
|
metricsGetContentstackRewardAll.validationError(validatedCmsRewards.error)
|
|
return null
|
|
}
|
|
|
|
metricsGetContentstackRewardAll.success()
|
|
|
|
return validatedCmsRewards.data
|
|
}
|