Optimize home/library loading and SQLite query performance

- Replace home preview N+1 queries with a single window-function batch query
- Cache library previews and series card lists (15s TTL, shared with media cache)
- Tune SQLite: larger page cache, mmap, wal_autocheckpoint, ANALYZE on migrate
- Defer history fetch on library page until last_played sort is selected
- Yield to browser between paginated library loads to keep UI responsive

Co-authored-by: truewhile <truewhile@users.noreply.github.com>
This commit is contained in:
Cursor Agent
2026-09-02 01:39:28 +00:00
parent deca7735a7
commit ba621cfc4a
10 changed files with 286 additions and 17 deletions
+7 -1
View File
@@ -45,9 +45,12 @@ export function LibraryPage() {
const [historyMap, setHistoryMap] = useState<Map<string, string>>(new Map())
useEffect(() => {
if (sortField !== 'last_played') return
let cancelled = false
historyAPI
.list(1000)
.then((historyItems) => {
if (cancelled) return
const map = new Map<string, string>()
for (const item of historyItems ?? []) {
if (item.media_id && item.watched_at) {
@@ -59,7 +62,10 @@ export function LibraryPage() {
setHistoryMap(map)
})
.catch(() => {})
}, [])
return () => {
cancelled = true
}
}, [sortField])
const handleSortChange = (field: SortField, order: SortOrder) => {
setSortField(field)
+12
View File
@@ -145,6 +145,16 @@ function isSeriesLibraryType(type?: string) {
return type === 'tv' || type === 'anime' || type === 'variety'
}
function yieldToBrowser(): Promise<void> {
return new Promise((resolve) => {
if (typeof requestIdleCallback !== 'undefined') {
requestIdleCallback(() => resolve(), { timeout: 48 })
} else {
setTimeout(resolve, 0)
}
})
}
async function loadAllSeriesCards(
libraryID: string,
isRemoteEmby: boolean | undefined,
@@ -161,6 +171,7 @@ async function loadAllSeriesCards(
onPage({ items: collected, total: data.total ?? collected.length, firstPage: page === 1 })
if (collected.length >= (data.total ?? 0) || pageItems.length < pageSize) break
page += 1
await yieldToBrowser()
}
return { items: collected }
}
@@ -181,6 +192,7 @@ async function loadAllMedia(
onPage({ items: collected, total: data.total ?? collected.length, firstPage: page === 1 })
if (collected.length >= (data.total ?? 0) || pageItems.length < pageSize) break
page += 1
await yieldToBrowser()
}
return { items: collected }
}