fix: wrap tier rewards endpoint in unstable_cache

This commit is contained in:
Christel Westerberg
2024-10-09 15:20:00 +02:00
committed by Pontus Dreij
parent ed3acce57c
commit 2886f537ee

View File

@@ -1,10 +1,10 @@
import { metrics } from "@opentelemetry/api" import { metrics } from "@opentelemetry/api"
import { unstable_cache } from "next/cache"
import { Lang } from "@/constants/languages" import { Lang } from "@/constants/languages"
import * as api from "@/lib/api" import * as api from "@/lib/api"
import { GetRewards } from "@/lib/graphql/Query/Rewards.graphql" import { GetRewards } from "@/lib/graphql/Query/Rewards.graphql"
import { request } from "@/lib/graphql/request" import { request } from "@/lib/graphql/request"
import { Context } from "@/server/context"
import { notFound } from "@/server/errors/trpc" import { notFound } from "@/server/errors/trpc"
import { import {
contentStackBaseWithProtectedProcedure, contentStackBaseWithProtectedProcedure,
@@ -62,69 +62,71 @@ const getAllRewardFailCounter = meter.createCounter(
"trpc.contentstack.reward.all-fail" "trpc.contentstack.reward.all-fail"
) )
const ONE_HOUR = 60 * 60
function getUniqueRewardIds(rewardIds: string[]) { function getUniqueRewardIds(rewardIds: string[]) {
const uniqueRewardIds = new Set(rewardIds) const uniqueRewardIds = new Set(rewardIds)
return Array.from(uniqueRewardIds) return Array.from(uniqueRewardIds)
} }
async function getAllApiRewards(ctx: Context & { serviceToken: string }) { const getAllCachedApiRewards = unstable_cache(
const apiResponse = await api.get(api.endpoints.v1.tierRewards, { async function (token) {
cache: undefined, // override defaultOptions const apiResponse = await api.get(api.endpoints.v1.tierRewards, {
headers: { headers: {
Authorization: `Bearer ${ctx.serviceToken}`, Authorization: `Bearer ${token}`,
}, },
// One hour. Since the service token is refreshed every hour, this is the longest cache we can have.
next: { revalidate: 60 * 60 },
})
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.rewards.tierRewards error ", if (!apiResponse.ok) {
JSON.stringify({ const text = await apiResponse.text()
error: { getCurrentRewardFailCounter.add(1, {
error_type: "http_error",
error: JSON.stringify({
status: apiResponse.status, status: apiResponse.status,
statusText: apiResponse.statusText, statusText: apiResponse.statusText,
text, text,
}, }),
}) })
) console.error(
} "api.rewards.tierRewards error ",
JSON.stringify({
error: {
status: apiResponse.status,
statusText: apiResponse.statusText,
text,
},
})
)
}
const data = await apiResponse.json() const data = await apiResponse.json()
const validatedApiTierRewards = validateApiTierRewardsSchema.safeParse(data) const validatedApiTierRewards = validateApiTierRewardsSchema.safeParse(data)
if (!validatedApiTierRewards.success) { if (!validatedApiTierRewards.success) {
getAllRewardFailCounter.add(1, { getAllRewardFailCounter.add(1, {
error_type: "validation_error", error_type: "validation_error",
error: JSON.stringify(validatedApiTierRewards.error), error: JSON.stringify(validatedApiTierRewards.error),
})
console.error(validatedApiTierRewards.error)
console.error(
"api.rewards validation error",
JSON.stringify({
error: validatedApiTierRewards.error,
}) })
) console.error(validatedApiTierRewards.error)
return null console.error(
} "api.rewards validation error",
JSON.stringify({
error: validatedApiTierRewards.error,
})
)
return null
}
return validatedApiTierRewards.data return validatedApiTierRewards.data
} },
["getAllApiRewards"],
{ revalidate: ONE_HOUR }
)
async function getCmsRewards(locale: Lang, rewardIds: string[]) { async function getCmsRewards(locale: Lang, rewardIds: string[]) {
const tags = rewardIds.map((id) => const tags = rewardIds.map((id) =>
generateLoyaltyConfigTag(locale, "reward", id) generateLoyaltyConfigTag(locale, "reward", id)
) )
const cmsRewardsResponse = await request<CmsRewardsResponse>( const cmsRewardsResponse = await request<CmsRewardsResponse>(
GetRewards, GetRewards,
{ {
@@ -266,7 +268,9 @@ export const rewardQueryRouter = router({
getByLevelRewardCounter.add(1) getByLevelRewardCounter.add(1)
const { level_id } = input const { level_id } = input
const allUpcomingApiRewards = await getAllApiRewards(ctx) const allUpcomingApiRewards = await getAllCachedApiRewards(
ctx.serviceToken
)
if (!allUpcomingApiRewards || !allUpcomingApiRewards[level_id]) { if (!allUpcomingApiRewards || !allUpcomingApiRewards[level_id]) {
getByLevelRewardFailCounter.add(1) getByLevelRewardFailCounter.add(1)
@@ -314,7 +318,7 @@ export const rewardQueryRouter = router({
.input(rewardsAllInput) .input(rewardsAllInput)
.query(async function ({ input, ctx }) { .query(async function ({ input, ctx }) {
getAllRewardCounter.add(1) getAllRewardCounter.add(1)
const allApiRewards = await getAllApiRewards(ctx) const allApiRewards = await getAllCachedApiRewards(ctx.serviceToken)
if (!allApiRewards) { if (!allApiRewards) {
return [] return []