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:
@@ -1,4 +1,4 @@
|
|||||||
import { metrics, trace } from "@opentelemetry/api"
|
import { metrics, trace, type Tracer } from "@opentelemetry/api"
|
||||||
|
|
||||||
import { env } from "@/env/server"
|
import { env } from "@/env/server"
|
||||||
|
|
||||||
@@ -20,32 +20,47 @@ export async function getServiceToken() {
|
|||||||
const tracer = trace.getTracer("getServiceToken")
|
const tracer = trace.getTracer("getServiceToken")
|
||||||
|
|
||||||
return await tracer.startActiveSpan("getServiceToken", async () => {
|
return await tracer.startActiveSpan("getServiceToken", async () => {
|
||||||
let scopes: string[] = []
|
const scopes = env.ENABLE_BOOKING_FLOW
|
||||||
if (env.ENABLE_BOOKING_FLOW) {
|
? ["profile", "hotel", "booking", "package", "availability"]
|
||||||
scopes = ["profile", "hotel", "booking", "package", "availability"]
|
: ["profile"]
|
||||||
} else {
|
|
||||||
scopes = ["profile"]
|
|
||||||
}
|
|
||||||
const cacheKey = getServiceTokenCacheKey(scopes)
|
const cacheKey = getServiceTokenCacheKey(scopes)
|
||||||
|
|
||||||
const cacheClient = await getCacheClient()
|
const cacheClient = await getCacheClient()
|
||||||
const token =
|
const token = await getOrSetServiceTokenFromCache(cacheKey, scopes, tracer)
|
||||||
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)
|
|
||||||
|
|
||||||
|
if (token.expiresAt < Date.now()) {
|
||||||
|
await cacheClient.deleteKey(cacheKey)
|
||||||
|
|
||||||
|
const newToken = await getOrSetServiceTokenFromCache(
|
||||||
|
cacheKey,
|
||||||
|
scopes,
|
||||||
|
tracer
|
||||||
|
)
|
||||||
return newToken.jwt
|
return newToken.jwt
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return token.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[]) {
|
async function getJwt(scopes: string[]) {
|
||||||
fetchServiceTokenCounter.add(1)
|
fetchServiceTokenCounter.add(1)
|
||||||
const jwt = await fetchServiceToken(scopes)
|
const jwt = await fetchServiceToken(scopes)
|
||||||
|
|||||||
@@ -139,7 +139,6 @@ export const safeProtectedProcedure = baseProcedure.use(async function (opts) {
|
|||||||
|
|
||||||
export const serviceProcedure = baseProcedure.use(async (opts) => {
|
export const serviceProcedure = baseProcedure.use(async (opts) => {
|
||||||
const token = await getServiceToken()
|
const token = await getServiceToken()
|
||||||
console.log("[DEBUG] token", typeof token, token)
|
|
||||||
const { access_token } = token
|
const { access_token } = token
|
||||||
if (!access_token) {
|
if (!access_token) {
|
||||||
throw internalServerError(`[serviceProcedure] No service token`)
|
throw internalServerError(`[serviceProcedure] No service token`)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { cacheLogger } from "../../logger"
|
|||||||
|
|
||||||
export const cacheOrGet: DataCache["cacheOrGet"] = async <T>(
|
export const cacheOrGet: DataCache["cacheOrGet"] = async <T>(
|
||||||
key: string | string[],
|
key: string | string[],
|
||||||
callback: (overrideTTL?: (cacheTime: CacheTime) => void) => Promise<T>,
|
callback: () => Promise<T>,
|
||||||
ttl: CacheTime
|
ttl: CacheTime
|
||||||
): Promise<T> => {
|
): Promise<T> => {
|
||||||
if (!Array.isArray(key)) {
|
if (!Array.isArray(key)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user