diff --git a/src/renderer/api/subsonic/subsonic-controller.ts b/src/renderer/api/subsonic/subsonic-controller.ts index a850f729..7d2318db 100644 --- a/src/renderer/api/subsonic/subsonic-controller.ts +++ b/src/renderer/api/subsonic/subsonic-controller.ts @@ -46,7 +46,9 @@ const ALBUM_LIST_SORT_MAPPING: Record { @@ -420,7 +422,7 @@ export const SubsonicController: ControllerEndpoint = { while (fetchNextPage) { const res = await ssApiClient(apiClientProps).search3({ query: { - albumCount: 500, + albumCount: MAX_SUBSONIC_ITEMS, albumOffset: startIndex, artistCount: 0, artistOffset: 0, @@ -439,8 +441,7 @@ export const SubsonicController: ControllerEndpoint = { totalRecordCount += albumCount; startIndex += albumCount; - // The max limit size for Subsonic is 500 - fetchNextPage = albumCount === 500; + fetchNextPage = albumCount === MAX_SUBSONIC_ITEMS; } return totalRecordCount; @@ -524,7 +525,7 @@ export const SubsonicController: ControllerEndpoint = { genre: query.genres?.length ? query.genres[0] : undefined, musicFolderId: query.musicFolderId, offset: startIndex, - size: 500, + size: MAX_SUBSONIC_ITEMS, toYear, type, }, @@ -548,8 +549,7 @@ export const SubsonicController: ControllerEndpoint = { totalRecordCount += albumCount; startIndex += albumCount; - // The max limit size for Subsonic is 500 - fetchNextPage = albumCount === 500; + fetchNextPage = albumCount === MAX_SUBSONIC_ITEMS; } return totalRecordCount; @@ -1089,7 +1089,7 @@ export const SubsonicController: ControllerEndpoint = { artistCount: 0, artistOffset: 0, query: query.searchTerm || '""', - songCount: 500, + songCount: MAX_SUBSONIC_ITEMS, songOffset: startIndex, }, }); @@ -1103,8 +1103,7 @@ export const SubsonicController: ControllerEndpoint = { totalRecordCount += songCount; startIndex += songCount; - // The max limit size for Subsonic is 500 - fetchNextPage = songCount === 500; + fetchNextPage = songCount === MAX_SUBSONIC_ITEMS; } return totalRecordCount; @@ -1112,6 +1111,10 @@ export const SubsonicController: ControllerEndpoint = { if (query.genreIds) { let totalRecordCount = 0; + + // Rather than just do `getSongsByGenre` by groups of 500, instead + // jump the offset 10x, and then backtrack on the last chunk. This improves + // performance for extremely large libraries while (fetchNextSection) { const res = await ssApiClient(apiClientProps).getSongsByGenre({ query: { @@ -1130,17 +1133,17 @@ export const SubsonicController: ControllerEndpoint = { if (numberOfResults !== 1) { fetchNextSection = false; - startIndex = sectionIndex === 0 ? 0 : sectionIndex - BATCH_SIZE; + startIndex = sectionIndex === 0 ? 0 : sectionIndex - SUBSONIC_FAST_BATCH_SIZE; break; } else { - sectionIndex += BATCH_SIZE; + sectionIndex += SUBSONIC_FAST_BATCH_SIZE; } } while (fetchNextPage) { const res = await ssApiClient(apiClientProps).getSongsByGenre({ query: { - count: BATCH_SIZE, + count: MAX_SUBSONIC_ITEMS, genre: query.genreIds[0], musicFolderId: query.musicFolderId, offset: startIndex, @@ -1156,7 +1159,7 @@ export const SubsonicController: ControllerEndpoint = { totalRecordCount = startIndex + numberOfResults; startIndex += numberOfResults; - fetchNextPage = numberOfResults === 500; + fetchNextPage = numberOfResults === MAX_SUBSONIC_ITEMS; } return totalRecordCount; @@ -1178,6 +1181,9 @@ export const SubsonicController: ControllerEndpoint = { let totalRecordCount = 0; + // Rather than just do `search3` by groups of 500, instead + // jump the offset 10x, and then backtrack on the last chunk. This improves + // performance for extremely large libraries while (fetchNextSection) { const res = await ssApiClient(apiClientProps).search3({ query: { @@ -1197,13 +1203,12 @@ export const SubsonicController: ControllerEndpoint = { const numberOfResults = (res.body.searchResult3?.song || []).length || 0; - // Check each batch of 500 songs to check for data - sectionIndex += BATCH_SIZE; - fetchNextSection = numberOfResults === 1; - - if (!fetchNextSection) { - // fetchNextBlock will be false on the next loop so we need to subtract 2 * BATCH_SIZE - startIndex = sectionIndex - 2 * BATCH_SIZE; + if (numberOfResults !== 1) { + fetchNextSection = false; + startIndex = sectionIndex === 0 ? 0 : sectionIndex - SUBSONIC_FAST_BATCH_SIZE; + break; + } else { + sectionIndex += SUBSONIC_FAST_BATCH_SIZE; } } @@ -1215,7 +1220,7 @@ export const SubsonicController: ControllerEndpoint = { artistCount: 0, artistOffset: 0, query: query.searchTerm || '""', - songCount: 500, + songCount: MAX_SUBSONIC_ITEMS, songOffset: startIndex, }, }); @@ -1229,8 +1234,7 @@ export const SubsonicController: ControllerEndpoint = { totalRecordCount = startIndex + numberOfResults; startIndex += numberOfResults; - // The max limit size for Subsonic is 500 - fetchNextPage = numberOfResults === 500; + fetchNextPage = numberOfResults === MAX_SUBSONIC_ITEMS; } return totalRecordCount;