fix: correct LRU cache eviction and expiration logic in cache-manager

This commit is contained in:
2025-11-11 19:16:43 +00:00
parent 18be9bbd55
commit a688945df2

View File

@@ -32,6 +32,7 @@ export async function initDatabase(): Promise<IDBDatabase> {
export async function cacheChapter(chapter: BibleChapter): Promise<void> {
if (!db) await initDatabase()
return new Promise((resolve, reject) => {
const entry: CacheEntry = {
chapterId: chapter.id,
data: chapter,
@@ -39,28 +40,39 @@ export async function cacheChapter(chapter: BibleChapter): Promise<void> {
expiresAt: Date.now() + CACHE_DURATION_MS
}
return new Promise((resolve, reject) => {
const transaction = db!.transaction([STORE_NAME], 'readwrite')
const store = transaction.objectStore(STORE_NAME)
// Delete oldest entries if over limit
// First, check if we need to delete oldest entry
const countRequest = store.count()
countRequest.onsuccess = () => {
if (countRequest.result >= MAX_CACHE_SIZE) {
// Delete oldest entry
const index = store.index('timestamp')
const oldestRequest = index.openCursor()
oldestRequest.onsuccess = (event) => {
const deleteRequest = index.openCursor()
let deleted = false
deleteRequest.onsuccess = (event) => {
const cursor = (event.target as IDBRequest).result
if (cursor) {
if (cursor && !deleted) {
cursor.delete()
deleted = true
// Continue with adding new entry after delete
const putRequest = store.put(entry)
putRequest.onerror = () => reject(putRequest.error)
putRequest.onsuccess = () => resolve()
}
}
deleteRequest.onerror = () => reject(deleteRequest.error)
} else {
// Just add the entry
const putRequest = store.put(entry)
putRequest.onerror = () => reject(putRequest.error)
putRequest.onsuccess = () => resolve()
}
}
const request = store.put(entry)
request.onerror = () => reject(request.error)
request.onsuccess = () => resolve()
countRequest.onerror = () => reject(countRequest.error)
})
}
@@ -90,16 +102,19 @@ export async function clearExpiredCache(): Promise<void> {
return new Promise((resolve, reject) => {
const transaction = db!.transaction([STORE_NAME], 'readwrite')
const store = transaction.objectStore(STORE_NAME)
const index = store.index('timestamp')
const range = IDBKeyRange.upperBound(Date.now() - CACHE_DURATION_MS)
const request = index.openCursor(range)
const request = store.openCursor()
const now = Date.now()
request.onsuccess = (event) => {
const cursor = (event.target as IDBRequest).result
if (cursor) {
const entry = cursor.value as CacheEntry
if (entry.expiresAt < now) {
cursor.delete()
}
cursor.continue()
} else {
// Cursor is done, resolve
resolve()
}
}