Merged in fix/reward-remove-cache (pull request #1542)
fix(reward): remove cache from profile service * fix(reward): remove cache from profile service Approved-by: Anton Gunnarsson
This commit is contained in:
@@ -10,8 +10,6 @@ import {
|
|||||||
} from "@/server/trpc"
|
} from "@/server/trpc"
|
||||||
import { langInput } from "@/server/utils"
|
import { langInput } from "@/server/utils"
|
||||||
|
|
||||||
import { getCacheClient } from "@/services/dataCache"
|
|
||||||
|
|
||||||
import { getAllLoyaltyLevels, getLoyaltyLevel } from "../loyaltyLevel/query"
|
import { getAllLoyaltyLevels, getLoyaltyLevel } from "../loyaltyLevel/query"
|
||||||
import {
|
import {
|
||||||
rewardsAllInput,
|
rewardsAllInput,
|
||||||
@@ -174,139 +172,129 @@ export const rewardQueryRouter = router({
|
|||||||
? api.endpoints.v1.Profile.Reward.reward
|
? api.endpoints.v1.Profile.Reward.reward
|
||||||
: api.endpoints.v1.Profile.reward
|
: api.endpoints.v1.Profile.reward
|
||||||
|
|
||||||
const cacheClient = await getCacheClient()
|
const apiResponse = await api.get(endpoint, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${ctx.session.token.access_token}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
return cacheClient.cacheOrGet(
|
if (!apiResponse.ok) {
|
||||||
endpoint,
|
const text = await apiResponse.text()
|
||||||
async () => {
|
getCurrentRewardFailCounter.add(1, {
|
||||||
const apiResponse = await api.get(endpoint, {
|
error_type: "http_error",
|
||||||
headers: {
|
error: JSON.stringify({
|
||||||
Authorization: `Bearer ${ctx.session.token.access_token}`,
|
status: apiResponse.status,
|
||||||
|
statusText: apiResponse.statusText,
|
||||||
|
text,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
console.error(
|
||||||
|
"api.reward error ",
|
||||||
|
JSON.stringify({
|
||||||
|
error: {
|
||||||
|
status: apiResponse.status,
|
||||||
|
statusText: apiResponse.statusText,
|
||||||
|
text,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
if (!apiResponse.ok) {
|
const data = await apiResponse.json()
|
||||||
const text = await apiResponse.text()
|
|
||||||
getCurrentRewardFailCounter.add(1, {
|
|
||||||
error_type: "http_error",
|
|
||||||
error: JSON.stringify({
|
|
||||||
status: apiResponse.status,
|
|
||||||
statusText: apiResponse.statusText,
|
|
||||||
text,
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
console.error(
|
|
||||||
"api.reward error ",
|
|
||||||
JSON.stringify({
|
|
||||||
error: {
|
|
||||||
status: apiResponse.status,
|
|
||||||
statusText: apiResponse.statusText,
|
|
||||||
text,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await apiResponse.json()
|
const validatedApiRewards = isNewEndpoint
|
||||||
|
? validateCategorizedRewardsSchema.safeParse(data)
|
||||||
|
: validateApiRewardSchema.safeParse(data)
|
||||||
|
|
||||||
const validatedApiRewards = isNewEndpoint
|
if (!validatedApiRewards.success) {
|
||||||
? validateCategorizedRewardsSchema.safeParse(data)
|
getCurrentRewardFailCounter.add(1, {
|
||||||
: validateApiRewardSchema.safeParse(data)
|
locale: ctx.lang,
|
||||||
|
error_type: "validation_error",
|
||||||
|
error: JSON.stringify(validatedApiRewards.error),
|
||||||
|
})
|
||||||
|
console.error(validatedApiRewards.error)
|
||||||
|
console.error(
|
||||||
|
"contentstack.rewards validation error",
|
||||||
|
JSON.stringify({
|
||||||
|
query: { locale: ctx.lang },
|
||||||
|
error: validatedApiRewards.error,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
if (!validatedApiRewards.success) {
|
const rewardIds = getNonRedeemedRewardIds(validatedApiRewards.data)
|
||||||
getCurrentRewardFailCounter.add(1, {
|
|
||||||
locale: ctx.lang,
|
|
||||||
error_type: "validation_error",
|
|
||||||
error: JSON.stringify(validatedApiRewards.error),
|
|
||||||
})
|
|
||||||
console.error(validatedApiRewards.error)
|
|
||||||
console.error(
|
|
||||||
"contentstack.rewards validation error",
|
|
||||||
JSON.stringify({
|
|
||||||
query: { locale: ctx.lang },
|
|
||||||
error: validatedApiRewards.error,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
const rewardIds = getNonRedeemedRewardIds(validatedApiRewards.data)
|
const cmsRewards = await getCmsRewards(ctx.lang, rewardIds)
|
||||||
|
|
||||||
const cmsRewards = await getCmsRewards(ctx.lang, rewardIds)
|
if (!cmsRewards) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
if (!cmsRewards) {
|
const wrappedSurprisesIds = validatedApiRewards.data
|
||||||
return null
|
.filter(
|
||||||
}
|
(reward) =>
|
||||||
|
reward.type === "coupon" &&
|
||||||
|
reward.rewardType === "Surprise" &&
|
||||||
|
"coupon" in reward &&
|
||||||
|
reward.coupon.some(({ unwrapped }) => !unwrapped)
|
||||||
|
)
|
||||||
|
.map(({ rewardId }) => rewardId)
|
||||||
|
|
||||||
const wrappedSurprisesIds = validatedApiRewards.data
|
const rewards = cmsRewards
|
||||||
.filter(
|
.filter(
|
||||||
(reward) =>
|
(cmsReward) => !wrappedSurprisesIds.includes(cmsReward.reward_id)
|
||||||
reward.type === "coupon" &&
|
)
|
||||||
reward.rewardType === "Surprise" &&
|
.map((cmsReward) => {
|
||||||
"coupon" in reward &&
|
const apiReward = validatedApiRewards.data.find(
|
||||||
reward.coupon.some(({ unwrapped }) => !unwrapped)
|
({ rewardId }) => rewardId === cmsReward.reward_id
|
||||||
)
|
)
|
||||||
.map(({ rewardId }) => rewardId)
|
|
||||||
|
|
||||||
const rewards = cmsRewards
|
const redeemableCoupons =
|
||||||
.filter(
|
(apiReward &&
|
||||||
(cmsReward) => !wrappedSurprisesIds.includes(cmsReward.reward_id)
|
"coupon" in apiReward &&
|
||||||
)
|
apiReward.coupon.filter(
|
||||||
.map((cmsReward) => {
|
(coupon) => coupon.state !== "redeemed" && coupon.unwrapped
|
||||||
const apiReward = validatedApiRewards.data.find(
|
)) ||
|
||||||
({ rewardId }) => rewardId === cmsReward.reward_id
|
[]
|
||||||
)
|
|
||||||
|
|
||||||
const redeemableCoupons =
|
const firstRedeemableCouponToExpire = redeemableCoupons.reduce(
|
||||||
(apiReward &&
|
(earliest, coupon) => {
|
||||||
"coupon" in apiReward &&
|
if (dt(coupon.expiresAt).isBefore(dt(earliest.expiresAt))) {
|
||||||
apiReward.coupon.filter(
|
return coupon
|
||||||
(coupon) => coupon.state !== "redeemed" && coupon.unwrapped
|
|
||||||
)) ||
|
|
||||||
[]
|
|
||||||
|
|
||||||
const firstRedeemableCouponToExpire = redeemableCoupons.reduce(
|
|
||||||
(earliest, coupon) => {
|
|
||||||
if (dt(coupon.expiresAt).isBefore(dt(earliest.expiresAt))) {
|
|
||||||
return coupon
|
|
||||||
}
|
|
||||||
return earliest
|
|
||||||
},
|
|
||||||
redeemableCoupons[0]
|
|
||||||
)?.couponCode
|
|
||||||
|
|
||||||
return {
|
|
||||||
...cmsReward,
|
|
||||||
id: apiReward?.id,
|
|
||||||
rewardType: apiReward?.rewardType,
|
|
||||||
redeemLocation: apiReward?.redeemLocation,
|
|
||||||
rewardTierLevel:
|
|
||||||
apiReward && "rewardTierLevel" in apiReward
|
|
||||||
? apiReward.rewardTierLevel
|
|
||||||
: undefined,
|
|
||||||
operaRewardId:
|
|
||||||
apiReward && "operaRewardId" in apiReward
|
|
||||||
? apiReward.operaRewardId
|
|
||||||
: "",
|
|
||||||
categories:
|
|
||||||
apiReward && "categories" in apiReward
|
|
||||||
? apiReward.categories || []
|
|
||||||
: [],
|
|
||||||
couponCode: firstRedeemableCouponToExpire,
|
|
||||||
coupons:
|
|
||||||
apiReward && "coupon" in apiReward
|
|
||||||
? apiReward.coupon || []
|
|
||||||
: [],
|
|
||||||
}
|
}
|
||||||
})
|
return earliest
|
||||||
|
},
|
||||||
|
redeemableCoupons[0]
|
||||||
|
)?.couponCode
|
||||||
|
|
||||||
getCurrentRewardSuccessCounter.add(1)
|
return {
|
||||||
|
...cmsReward,
|
||||||
|
id: apiReward?.id,
|
||||||
|
rewardType: apiReward?.rewardType,
|
||||||
|
redeemLocation: apiReward?.redeemLocation,
|
||||||
|
rewardTierLevel:
|
||||||
|
apiReward && "rewardTierLevel" in apiReward
|
||||||
|
? apiReward.rewardTierLevel
|
||||||
|
: undefined,
|
||||||
|
operaRewardId:
|
||||||
|
apiReward && "operaRewardId" in apiReward
|
||||||
|
? apiReward.operaRewardId
|
||||||
|
: "",
|
||||||
|
categories:
|
||||||
|
apiReward && "categories" in apiReward
|
||||||
|
? apiReward.categories || []
|
||||||
|
: [],
|
||||||
|
couponCode: firstRedeemableCouponToExpire,
|
||||||
|
coupons:
|
||||||
|
apiReward && "coupon" in apiReward ? apiReward.coupon || [] : [],
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return { rewards }
|
getCurrentRewardSuccessCounter.add(1)
|
||||||
},
|
|
||||||
"1h"
|
return { rewards }
|
||||||
)
|
|
||||||
}),
|
}),
|
||||||
surprises: contentStackBaseWithProtectedProcedure
|
surprises: contentStackBaseWithProtectedProcedure
|
||||||
.input(langInput.optional()) // lang is required for client, but not for server
|
.input(langInput.optional()) // lang is required for client, but not for server
|
||||||
@@ -318,120 +306,113 @@ export const rewardQueryRouter = router({
|
|||||||
? api.endpoints.v1.Profile.Reward.reward
|
? api.endpoints.v1.Profile.Reward.reward
|
||||||
: api.endpoints.v1.Profile.reward
|
: api.endpoints.v1.Profile.reward
|
||||||
|
|
||||||
const cacheClient = await getCacheClient()
|
const apiResponse = await api.get(endpoint, {
|
||||||
return await cacheClient.cacheOrGet(
|
cache: undefined,
|
||||||
endpoint,
|
headers: {
|
||||||
async () => {
|
Authorization: `Bearer ${ctx.session.token.access_token}`,
|
||||||
const apiResponse = await api.get(endpoint, {
|
},
|
||||||
cache: undefined,
|
})
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${ctx.session.token.access_token}`,
|
if (!apiResponse.ok) {
|
||||||
|
const text = await apiResponse.text()
|
||||||
|
getCurrentRewardFailCounter.add(1, {
|
||||||
|
error_type: "http_error",
|
||||||
|
error: JSON.stringify({
|
||||||
|
status: apiResponse.status,
|
||||||
|
statusText: apiResponse.statusText,
|
||||||
|
text,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
console.error(
|
||||||
|
"api.reward error ",
|
||||||
|
JSON.stringify({
|
||||||
|
error: {
|
||||||
|
status: apiResponse.status,
|
||||||
|
statusText: apiResponse.statusText,
|
||||||
|
text,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
if (!apiResponse.ok) {
|
const data = await apiResponse.json()
|
||||||
const text = await apiResponse.text()
|
const validatedApiRewards = isNewEndpoint
|
||||||
getCurrentRewardFailCounter.add(1, {
|
? validateCategorizedRewardsSchema.safeParse(data)
|
||||||
error_type: "http_error",
|
: validateApiRewardSchema.safeParse(data)
|
||||||
error: JSON.stringify({
|
|
||||||
status: apiResponse.status,
|
if (!validatedApiRewards.success) {
|
||||||
statusText: apiResponse.statusText,
|
getCurrentRewardFailCounter.add(1, {
|
||||||
text,
|
locale: ctx.lang,
|
||||||
}),
|
error_type: "validation_error",
|
||||||
})
|
error: JSON.stringify(validatedApiRewards.error),
|
||||||
console.error(
|
})
|
||||||
"api.reward error ",
|
console.error(validatedApiRewards.error)
|
||||||
JSON.stringify({
|
console.error(
|
||||||
error: {
|
"contentstack.surprises validation error",
|
||||||
status: apiResponse.status,
|
JSON.stringify({
|
||||||
statusText: apiResponse.statusText,
|
query: { locale: ctx.lang },
|
||||||
text,
|
error: validatedApiRewards.error,
|
||||||
},
|
})
|
||||||
})
|
)
|
||||||
)
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const rewardIds = validatedApiRewards.data
|
||||||
|
.map((reward) => reward?.rewardId)
|
||||||
|
.filter((rewardId): rewardId is string => !!rewardId)
|
||||||
|
.sort()
|
||||||
|
|
||||||
|
const cmsRewards = await getCmsRewards(ctx.lang, rewardIds)
|
||||||
|
|
||||||
|
if (!cmsRewards) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrentRewardSuccessCounter.add(1)
|
||||||
|
|
||||||
|
const surprises: Surprise[] = validatedApiRewards.data
|
||||||
|
// TODO: Add predicates once legacy endpoints are removed
|
||||||
|
.filter((reward) => {
|
||||||
|
if (reward?.rewardType !== "Surprise") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!("coupon" in reward)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const unwrappedCoupons =
|
||||||
|
reward.coupon.filter((coupon) => !coupon.unwrapped) || []
|
||||||
|
if (unwrappedCoupons.length === 0) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
.map((surprise) => {
|
||||||
|
const reward = cmsRewards.find(
|
||||||
|
({ reward_id }) => surprise.rewardId === reward_id
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!reward) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await apiResponse.json()
|
return {
|
||||||
const validatedApiRewards = isNewEndpoint
|
...reward,
|
||||||
? validateCategorizedRewardsSchema.safeParse(data)
|
id: surprise.id,
|
||||||
: validateApiRewardSchema.safeParse(data)
|
rewardType: surprise.rewardType,
|
||||||
|
rewardTierLevel: undefined,
|
||||||
if (!validatedApiRewards.success) {
|
redeemLocation: surprise.redeemLocation,
|
||||||
getCurrentRewardFailCounter.add(1, {
|
coupons: "coupon" in surprise ? surprise.coupon || [] : [],
|
||||||
locale: ctx.lang,
|
categories:
|
||||||
error_type: "validation_error",
|
"categories" in surprise ? surprise.categories || [] : [],
|
||||||
error: JSON.stringify(validatedApiRewards.error),
|
|
||||||
})
|
|
||||||
console.error(validatedApiRewards.error)
|
|
||||||
console.error(
|
|
||||||
"contentstack.surprises validation error",
|
|
||||||
JSON.stringify({
|
|
||||||
query: { locale: ctx.lang },
|
|
||||||
error: validatedApiRewards.error,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.flatMap((surprises) => (surprises ? [surprises] : []))
|
||||||
|
|
||||||
const rewardIds = validatedApiRewards.data
|
return surprises
|
||||||
.map((reward) => reward?.rewardId)
|
|
||||||
.filter((rewardId): rewardId is string => !!rewardId)
|
|
||||||
.sort()
|
|
||||||
|
|
||||||
const cmsRewards = await getCmsRewards(ctx.lang, rewardIds)
|
|
||||||
|
|
||||||
if (!cmsRewards) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
getCurrentRewardSuccessCounter.add(1)
|
|
||||||
|
|
||||||
const surprises: Surprise[] = validatedApiRewards.data
|
|
||||||
// TODO: Add predicates once legacy endpoints are removed
|
|
||||||
.filter((reward) => {
|
|
||||||
if (reward?.rewardType !== "Surprise") {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!("coupon" in reward)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
const unwrappedCoupons =
|
|
||||||
reward.coupon.filter((coupon) => !coupon.unwrapped) || []
|
|
||||||
if (unwrappedCoupons.length === 0) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
.map((surprise) => {
|
|
||||||
const reward = cmsRewards.find(
|
|
||||||
({ reward_id }) => surprise.rewardId === reward_id
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!reward) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...reward,
|
|
||||||
id: surprise.id,
|
|
||||||
rewardType: surprise.rewardType,
|
|
||||||
rewardTierLevel: undefined,
|
|
||||||
redeemLocation: surprise.redeemLocation,
|
|
||||||
coupons: "coupon" in surprise ? surprise.coupon || [] : [],
|
|
||||||
categories:
|
|
||||||
"categories" in surprise ? surprise.categories || [] : [],
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.flatMap((surprises) => (surprises ? [surprises] : []))
|
|
||||||
|
|
||||||
return surprises
|
|
||||||
},
|
|
||||||
"1h"
|
|
||||||
)
|
|
||||||
}),
|
}),
|
||||||
unwrap: protectedProcedure
|
unwrap: protectedProcedure
|
||||||
.input(rewardsUpdateInput)
|
.input(rewardsUpdateInput)
|
||||||
|
|||||||
Reference in New Issue
Block a user