import { metrics } from "@opentelemetry/api" import { MembershipLevel, MembershipLevelEnum, } from "@/constants/membershipLevels" import { GetAllLoyaltyLevels, GetLoyaltyLevel, } from "@/lib/graphql/Query/LoyaltyLevels.graphql" import { request } from "@/lib/graphql/request" import { Context } from "@/server/context" import { notFound } from "@/server/errors/trpc" import { contentstackBaseProcedure, router } from "@/server/trpc" import { generateLoyaltyConfigTag } from "@/utils/generateTag" import { loyaltyLevelInput } from "./input" import { LoyaltyLevelsResponse, validateLoyaltyLevelsSchema } from "./output" const meter = metrics.getMeter("trpc.loyaltyLevel") // OpenTelemetry metrics: Loyalty Level const getAllLoyaltyLevelCounter = meter.createCounter( "trpc.contentstack.loyaltyLevel.all" ) const getAllLoyaltyLevelSuccessCounter = meter.createCounter( "trpc.contentstack.loyaltyLevel.all-success" ) const getAllLoyaltyLevelFailCounter = meter.createCounter( "trpc.contentstack.loyaltyLevel.all-fail" ) const getByLevelLoyaltyLevelCounter = meter.createCounter( "trpc.contentstack.loyaltyLevel.byLevel" ) const getByLevelLoyaltyLevelSuccessCounter = meter.createCounter( "trpc.contentstack.loyaltyLevel.byLevel-success" ) const getByLevelLoyaltyLevelFailCounter = meter.createCounter( "trpc.contentstack.loyaltyLevel.byLevel-fail" ) export async function getAllLoyaltyLevels(ctx: Context) { getAllLoyaltyLevelCounter.add(1) // Ideally we should fetch all available tiers from API, but since they // are static, we can just use the enum values. We want to know which // levels we are fetching so that we can use tags to cache them const allLevelIds = Object.values(MembershipLevelEnum) const tags = allLevelIds.map((levelId) => generateLoyaltyConfigTag(ctx.lang, "loyalty_level", levelId) ) const loyaltyLevelsConfigResponse = await request( GetAllLoyaltyLevels, { lang: ctx.lang, level_ids: allLevelIds }, { next: { tags }, cache: "force-cache" } ) if (!loyaltyLevelsConfigResponse.data) { getAllLoyaltyLevelFailCounter.add(1) const notFoundError = notFound(loyaltyLevelsConfigResponse) console.error( "contentstack.loyaltyLevels not found error", JSON.stringify({ query: { lang: ctx.lang, }, error: { code: notFoundError.code }, }) ) throw notFoundError } const validatedLoyaltyLevels = validateLoyaltyLevelsSchema.safeParse( loyaltyLevelsConfigResponse.data ) if (!validatedLoyaltyLevels.success) { getAllLoyaltyLevelFailCounter.add(1) console.error(validatedLoyaltyLevels.error) console.error( "contentstack.rewards validation error", JSON.stringify({ query: { lang: ctx.lang, }, error: validatedLoyaltyLevels.error, }) ) return [] } getAllLoyaltyLevelSuccessCounter.add(1) return validatedLoyaltyLevels.data } export async function getLoyaltyLevel(ctx: Context, level_id: MembershipLevel) { getByLevelLoyaltyLevelCounter.add(1, { query: JSON.stringify({ lang: ctx.lang, level_id }), }) const loyaltyLevelsConfigResponse = await request( GetLoyaltyLevel, { lang: ctx.lang, level_id }, { next: { tags: [generateLoyaltyConfigTag(ctx.lang, "loyalty_level", level_id)], }, cache: "force-cache", } ) if ( !loyaltyLevelsConfigResponse.data || !loyaltyLevelsConfigResponse.data.all_loyalty_level.items.length ) { getByLevelLoyaltyLevelFailCounter.add(1) const notFoundError = notFound(loyaltyLevelsConfigResponse) console.error( "contentstack.loyaltyLevel not found error", JSON.stringify({ query: { lang: ctx.lang, level_id }, error: { code: notFoundError.code }, }) ) throw notFoundError } const validatedLoyaltyLevels = validateLoyaltyLevelsSchema.safeParse( loyaltyLevelsConfigResponse.data ) if (!validatedLoyaltyLevels.success) { getByLevelLoyaltyLevelFailCounter.add(1) console.error(validatedLoyaltyLevels.error) console.error( "contentstack.loyaltyLevel validation error", JSON.stringify({ query: { lang: ctx.lang, level_id }, error: validatedLoyaltyLevels.error, }) ) return null } getByLevelLoyaltyLevelSuccessCounter.add(1) return validatedLoyaltyLevels.data[0] } export const loyaltyLevelQueryRouter = router({ byLevel: contentstackBaseProcedure .input(loyaltyLevelInput) .query(async function ({ ctx, input }) { return getLoyaltyLevel(ctx, input.level) }), all: contentstackBaseProcedure.query(async function ({ ctx }) { return getAllLoyaltyLevels(ctx) }), })