fixed caching
This commit is contained in:
@@ -21,11 +21,22 @@ export type LibraryCacheSnapshot = {
|
||||
searchCache: Record<string, number[]>
|
||||
}
|
||||
|
||||
export type LibraryCacheStats = {
|
||||
snapshotCount: number
|
||||
staleSnapshotCount: number
|
||||
totalBytes: number
|
||||
activeBytes: number
|
||||
trackCount: number
|
||||
searchEntryCount: number
|
||||
updatedAt: number | null
|
||||
}
|
||||
|
||||
const DATABASE_NAME = 'api-mediaplayer-library-cache'
|
||||
const DATABASE_VERSION = 1
|
||||
const STORE_NAME = 'snapshots'
|
||||
const MAX_TRACKS = 5000
|
||||
const MAX_SEARCHES = 250
|
||||
const textEncoder = typeof TextEncoder !== 'undefined' ? new TextEncoder() : null
|
||||
|
||||
export function buildLibraryCacheKey(servers: CacheServerDescriptor[]) {
|
||||
return servers.map((server) => `${server.id}:${server.host}:${server.port ?? ''}:${server.ssl ? 'https' : 'http'}`).join('|')
|
||||
@@ -66,6 +77,18 @@ function withStore<T>(mode: IDBTransactionMode, handler: (store: IDBObjectStore)
|
||||
})
|
||||
}
|
||||
|
||||
function estimateRecordBytes(record: LibraryCacheRecord) {
|
||||
const payload = JSON.stringify(record)
|
||||
if (!textEncoder) return payload.length
|
||||
return textEncoder.encode(payload).length
|
||||
}
|
||||
|
||||
async function listLibraryCacheRecords(): Promise<LibraryCacheRecord[]> {
|
||||
if (typeof indexedDB === 'undefined') return []
|
||||
const records = await withStore<LibraryCacheRecord[]>('readonly', (store) => store.getAll())
|
||||
return Array.isArray(records) ? records : []
|
||||
}
|
||||
|
||||
export async function loadLibraryCache(cacheKey: string): Promise<LibraryCacheSnapshot | null> {
|
||||
if (!cacheKey || typeof indexedDB === 'undefined') return null
|
||||
|
||||
@@ -78,6 +101,47 @@ export async function loadLibraryCache(cacheKey: string): Promise<LibraryCacheSn
|
||||
}
|
||||
}
|
||||
|
||||
export async function pruneLibraryCache(activeCacheKey: string) {
|
||||
if (!activeCacheKey || typeof indexedDB === 'undefined') return 0
|
||||
|
||||
const records = await listLibraryCacheRecords()
|
||||
const staleKeys = records
|
||||
.map((record) => record.cacheKey)
|
||||
.filter((cacheKey) => cacheKey !== activeCacheKey)
|
||||
|
||||
if (staleKeys.length === 0) return 0
|
||||
|
||||
await Promise.all(staleKeys.map((cacheKey) => withStore('readwrite', (store) => store.delete(cacheKey))))
|
||||
return staleKeys.length
|
||||
}
|
||||
|
||||
export async function getLibraryCacheStats(activeCacheKey: string): Promise<LibraryCacheStats> {
|
||||
if (!activeCacheKey || typeof indexedDB === 'undefined') {
|
||||
return {
|
||||
snapshotCount: 0,
|
||||
staleSnapshotCount: 0,
|
||||
totalBytes: 0,
|
||||
activeBytes: 0,
|
||||
trackCount: 0,
|
||||
searchEntryCount: 0,
|
||||
updatedAt: null,
|
||||
}
|
||||
}
|
||||
|
||||
const records = await listLibraryCacheRecords()
|
||||
const activeRecord = records.find((record) => record.cacheKey === activeCacheKey)
|
||||
|
||||
return {
|
||||
snapshotCount: records.length,
|
||||
staleSnapshotCount: records.filter((record) => record.cacheKey !== activeCacheKey).length,
|
||||
totalBytes: records.reduce((sum, record) => sum + estimateRecordBytes(record), 0),
|
||||
activeBytes: activeRecord ? estimateRecordBytes(activeRecord) : 0,
|
||||
trackCount: activeRecord?.tracks.length ?? 0,
|
||||
searchEntryCount: activeRecord ? Object.keys(activeRecord.searchCache || {}).length : 0,
|
||||
updatedAt: activeRecord?.updatedAt ?? null,
|
||||
}
|
||||
}
|
||||
|
||||
export async function saveLibraryCache(cacheKey: string, tracks: Track[], searchCache: Record<string, number[]>) {
|
||||
if (!cacheKey || typeof indexedDB === 'undefined') return
|
||||
|
||||
@@ -96,4 +160,5 @@ export async function saveLibraryCache(cacheKey: string, tracks: Track[], search
|
||||
}
|
||||
|
||||
await withStore('readwrite', (store) => store.put(record))
|
||||
await pruneLibraryCache(cacheKey)
|
||||
}
|
||||
Reference in New Issue
Block a user