batch jellyfin song list requests when fetching by albumId (#922)

This commit is contained in:
jeffvli 2025-05-07 01:42:32 -07:00
parent 58f6535ba6
commit f03d88cd8c

View file

@ -695,15 +695,58 @@ export const JellyfinController: ControllerEndpoint = {
} }
const yearsFilter = yearsGroup.length ? formatCommaDelimitedString(yearsGroup) : undefined; const yearsFilter = yearsGroup.length ? formatCommaDelimitedString(yearsGroup) : undefined;
const albumIdsFilter = query.albumIds
? formatCommaDelimitedString(query.albumIds)
: undefined;
const artistIdsFilter = query.artistIds const artistIdsFilter = query.artistIds
? formatCommaDelimitedString(query.artistIds) ? formatCommaDelimitedString(query.artistIds)
: query.albumArtistIds : query.albumArtistIds
? formatCommaDelimitedString(query.albumArtistIds) ? formatCommaDelimitedString(query.albumArtistIds)
: undefined; : undefined;
let items: z.infer<typeof jfType._response.song>[] = [];
let totalRecordCount = 0;
const batchSize = 50;
// Handle albumIds fetches in batches to prevent HTTP 414 errors
if (query.albumIds && query.albumIds.length > batchSize) {
const albumIdBatches = chunk(query.albumIds, batchSize);
for (const batch of albumIdBatches) {
const albumIdsFilter = formatCommaDelimitedString(batch);
const res = await jfApiClient(apiClientProps).getSongList({
params: {
userId: apiClientProps.server?.userId,
},
query: {
AlbumIds: albumIdsFilter,
ArtistIds: artistIdsFilter,
Fields: 'Genres, DateCreated, MediaSources, ParentId',
GenreIds: query.genreIds?.join(','),
IncludeItemTypes: 'Audio',
IsFavorite: query.favorite,
Limit: query.limit,
ParentId: query.musicFolderId,
Recursive: true,
SearchTerm: query.searchTerm,
SortBy: songListSortMap.jellyfin[query.sortBy] || 'Album,SortName',
SortOrder: sortOrderMap.jellyfin[query.sortOrder],
StartIndex: query.startIndex,
...query._custom?.jellyfin,
Years: yearsFilter,
},
});
if (res.status !== 200) {
throw new Error('Failed to get song list');
}
items = [...items, ...res.body.Items];
totalRecordCount += res.body.Items.length;
}
} else {
const albumIdsFilter = query.albumIds
? formatCommaDelimitedString(query.albumIds)
: undefined;
const res = await jfApiClient(apiClientProps).getSongList({ const res = await jfApiClient(apiClientProps).getSongList({
params: { params: {
userId: apiClientProps.server?.userId, userId: apiClientProps.server?.userId,
@ -731,8 +774,6 @@ export const JellyfinController: ControllerEndpoint = {
throw new Error('Failed to get song list'); throw new Error('Failed to get song list');
} }
let items: z.infer<typeof jfType._response.song>[];
// Jellyfin Bodge because of code from https://github.com/jellyfin/jellyfin/blob/c566ccb63bf61f9c36743ddb2108a57c65a2519b/Emby.Server.Implementations/Data/SqliteItemRepository.cs#L3622 // Jellyfin Bodge because of code from https://github.com/jellyfin/jellyfin/blob/c566ccb63bf61f9c36743ddb2108a57c65a2519b/Emby.Server.Implementations/Data/SqliteItemRepository.cs#L3622
// If the Album ID filter is passed, Jellyfin will search for // If the Album ID filter is passed, Jellyfin will search for
// 1. the matching album id // 1. the matching album id
@ -741,12 +782,11 @@ export const JellyfinController: ControllerEndpoint = {
if (query.albumIds) { if (query.albumIds) {
const albumIdSet = new Set(query.albumIds); const albumIdSet = new Set(query.albumIds);
items = res.body.Items.filter((item) => albumIdSet.has(item.AlbumId!)); items = res.body.Items.filter((item) => albumIdSet.has(item.AlbumId!));
totalRecordCount = items.length;
if (items.length < res.body.Items.length) {
res.body.TotalRecordCount -= res.body.Items.length - items.length;
}
} else { } else {
items = res.body.Items; items = res.body.Items;
totalRecordCount = res.body.TotalRecordCount;
}
} }
return { return {
@ -754,7 +794,7 @@ export const JellyfinController: ControllerEndpoint = {
jfNormalize.song(item, apiClientProps.server, '', query.imageSize), jfNormalize.song(item, apiClientProps.server, '', query.imageSize),
), ),
startIndex: query.startIndex, startIndex: query.startIndex,
totalRecordCount: res.body.TotalRecordCount, totalRecordCount,
}; };
}, },
getSongListCount: async ({ apiClientProps, query }) => getSongListCount: async ({ apiClientProps, query }) =>