Merged in fix/cache-service-token (pull request #1571)

fix(servicetoken): cache it when using unstable_cache

* fix(servicetoken): cache it when using unstable_cache

* Refactor and using cacheOrGet as get/set

* Refactor

* Use expiresAt from cached token


Approved-by: Anton Gunnarsson
This commit is contained in:
Linus Flood
2025-03-19 09:16:11 +00:00
parent 8d1e9954d4
commit dd3fed9423
3 changed files with 34 additions and 20 deletions

View File

@@ -1,4 +1,4 @@
import { metrics, trace } from "@opentelemetry/api"
import { metrics, trace, type Tracer } from "@opentelemetry/api"
import { env } from "@/env/server"
@@ -20,32 +20,47 @@ export async function getServiceToken() {
const tracer = trace.getTracer("getServiceToken")
return await tracer.startActiveSpan("getServiceToken", async () => {
let scopes: string[] = []
if (env.ENABLE_BOOKING_FLOW) {
scopes = ["profile", "hotel", "booking", "package", "availability"]
} else {
scopes = ["profile"]
}
const scopes = env.ENABLE_BOOKING_FLOW
? ["profile", "hotel", "booking", "package", "availability"]
: ["profile"]
const cacheKey = getServiceTokenCacheKey(scopes)
const cacheClient = await getCacheClient()
const token =
await cacheClient.get<Awaited<ReturnType<typeof getJwt>>>(cacheKey)
console.log("[DEBUG] getServiceToken", typeof token, token)
if (!token || token.expiresAt < Date.now()) {
return await tracer.startActiveSpan("fetch new token", async () => {
const newToken = await getJwt(scopes)
const relativeTime = (newToken.expiresAt - Date.now()) / 1000
await cacheClient.set(cacheKey, newToken, relativeTime)
const token = await getOrSetServiceTokenFromCache(cacheKey, scopes, tracer)
return newToken.jwt
})
if (token.expiresAt < Date.now()) {
await cacheClient.deleteKey(cacheKey)
const newToken = await getOrSetServiceTokenFromCache(
cacheKey,
scopes,
tracer
)
return newToken.jwt
}
return token.jwt
})
}
async function getOrSetServiceTokenFromCache(
cacheKey: string,
scopes: string[],
tracer: Tracer
) {
const cacheClient = await getCacheClient()
const token = await cacheClient.cacheOrGet(
cacheKey,
async () => {
return await tracer.startActiveSpan("fetch new token", async () => {
const newToken = await getJwt(scopes)
return newToken
})
},
"1h"
)
return token
}
async function getJwt(scopes: string[]) {
fetchServiceTokenCounter.add(1)
const jwt = await fetchServiceToken(scopes)

View File

@@ -139,7 +139,6 @@ export const safeProtectedProcedure = baseProcedure.use(async function (opts) {
export const serviceProcedure = baseProcedure.use(async (opts) => {
const token = await getServiceToken()
console.log("[DEBUG] token", typeof token, token)
const { access_token } = token
if (!access_token) {
throw internalServerError(`[serviceProcedure] No service token`)

View File

@@ -10,7 +10,7 @@ import { cacheLogger } from "../../logger"
export const cacheOrGet: DataCache["cacheOrGet"] = async <T>(
key: string | string[],
callback: (overrideTTL?: (cacheTime: CacheTime) => void) => Promise<T>,
callback: () => Promise<T>,
ttl: CacheTime
): Promise<T> => {
if (!Array.isArray(key)) {