don't let pending cache to build up

This commit is contained in:
k00b 2024-10-08 17:58:15 -05:00
parent 8c0cafa3ec
commit 449568e3a2
1 changed files with 47 additions and 6 deletions

View File

@ -38,33 +38,74 @@ class LRUCache {
export function cachedFetcher (fetcher, { maxSize = 100, cacheExpiry, forceRefreshThreshold, keyGenerator }) {
const cache = new LRUCache(maxSize)
console.log(`[CACHE] Initializing cache: maxSize=${maxSize}, cacheExpiry=${cacheExpiry}, forceRefreshThreshold=${forceRefreshThreshold}`)
if (!keyGenerator) {
throw new Error('keyGenerator is required')
}
let totalFetches = 0
let cacheMisses = 0
let cacheHits = 0
let backgroundRefreshes = 0
setInterval(() => {
console.log(`[CACHE] Stats: total=${totalFetches}, hits=${cacheHits}, misses=${cacheMisses}, backgroundRefreshes=${backgroundRefreshes}, cacheSize=${cache.cache.size}`)
}, 60000) // Log stats every minute
return async function cachedFetch (...args) {
const key = keyGenerator ? keyGenerator(...args) : JSON.stringify(args)
const key = keyGenerator(...args)
const now = Date.now()
totalFetches++
async function fetchAndCache () {
console.log(`[CACHE] Fetching data for key: ${key}`)
const result = await fetcher(...args)
cache.set(key, { data: result, createdAt: now })
console.log(`[CACHE] Data fetched and cached for key: ${key}`)
return result
}
const cached = cache.get(key)
if (cached) {
if (cached.pendingPromise) {
console.log(`[CACHE] Waiting for pending promise for key: ${key}`)
return await cached.pendingPromise
}
const age = now - cached.createdAt
if (cacheExpiry === 0 || age < cacheExpiry) {
cacheHits++
console.log(`[CACHE] Cache hit for key: ${key}, age: ${age}ms`)
return cached.data
} else if (forceRefreshThreshold === 0 || age < forceRefreshThreshold) {
fetchAndCache().catch(console.error)
backgroundRefreshes++
console.log(`[CACHE] Background refresh for key: ${key}, age: ${age}ms`)
cached.pendingPromise = fetchAndCache()
cached.pendingPromise.finally(() => {
console.log(`[CACHE] Background refresh completed for key: ${key}`)
delete cached.pendingPromise
})
return cached.data
}
} else if (forceRefreshThreshold === 0) {
fetchAndCache().catch(console.error)
return null
}
return await fetchAndCache()
cacheMisses++
console.log(`[CACHE] Cache miss for key: ${key}`)
const entry = { createdAt: now, pendingPromise: fetchAndCache() }
cache.set(key, entry)
try {
entry.data = await entry.pendingPromise
return entry.data
} catch (error) {
console.error(`[CACHE] Error fetching data for key: ${key}`, error)
cache.delete(key)
throw error
} finally {
console.log(`[CACHE] Fetch completed for key: ${key}`)
delete entry.pendingPromise
}
}
}