import { metrics } from "@opentelemetry/api" import * as api from "@/lib/api" import { getVerifiedUser } from "@/server/routers/user/query" import { router, safeProtectedServiceProcedure } from "@/server/trpc" import { getMembership } from "@/utils/user" import { createBookingInput } from "./input" import { createBookingSchema } from "./output" import type { Session } from "next-auth" const meter = metrics.getMeter("trpc.bookings") const createBookingCounter = meter.createCounter("trpc.bookings.create") const createBookingSuccessCounter = meter.createCounter( "trpc.bookings.create-success" ) const createBookingFailCounter = meter.createCounter( "trpc.bookings.create-fail" ) async function getMembershipNumber( session: Session | null ): Promise { if (!session) return undefined const verifiedUser = await getVerifiedUser({ session }) if (!verifiedUser || "error" in verifiedUser) { return undefined } const membership = getMembership(verifiedUser.data.memberships) return membership?.membershipNumber } export const bookingMutationRouter = router({ create: safeProtectedServiceProcedure .input(createBookingInput) .mutation(async function ({ ctx, input }) { const accessToken = ctx.session?.token.access_token ?? ctx.serviceToken const { checkInDate, checkOutDate, hotelId } = input const loggingAttributes = { membershipNumber: await getMembershipNumber(ctx.session), checkInDate, checkOutDate, hotelId, } createBookingCounter.add(1, { hotelId, checkInDate, checkOutDate }) console.info( "api.booking.create start", JSON.stringify({ query: loggingAttributes, }) ) const headers = { Authorization: `Bearer ${accessToken}`, } const apiResponse = await api.post(api.endpoints.v1.Booking.bookings, { headers, body: input, }) if (!apiResponse.ok) { const text = await apiResponse.text() createBookingFailCounter.add(1, { hotelId, checkInDate, checkOutDate, error_type: "http_error", error: JSON.stringify({ status: apiResponse.status, }), }) console.error( "api.booking.create error", JSON.stringify({ query: loggingAttributes, error: { status: apiResponse.status, statusText: apiResponse.statusText, error: text, }, }) ) return null } const apiJson = await apiResponse.json() const verifiedData = createBookingSchema.safeParse(apiJson) if (!verifiedData.success) { createBookingFailCounter.add(1, { hotelId, checkInDate, checkOutDate, error_type: "validation_error", }) console.error( "api.booking.create validation error", JSON.stringify({ query: loggingAttributes, error: verifiedData.error, }) ) return null } createBookingSuccessCounter.add(1, { hotelId, checkInDate, checkOutDate, }) console.info( "api.booking.create success", JSON.stringify({ query: loggingAttributes, }) ) return verifiedData.data }), })