Skip to content

[Fix] Implement efficient directory query in handleGetMusicDirectoryRequest() - #880

Open
JonnieCache wants to merge 3 commits into
epoupon:developfrom
JonnieCache:subsonic-child-releases
Open

JonnieCache wants to merge 3 commits into
epoupon:developfrom
JonnieCache:subsonic-child-releases

Conversation

@JonnieCache

@JonnieCache JonnieCache commented Aug 18, 2026

Copy link
Copy Markdown

The problem

The current handleGetMusicDirectoryRequest() function, the handler for the /getMusicDirectory endpoint in the subsonic API does an N+1 query pattern when looking up the releases for the subdirectories of a queried directory. When querying a directory with N children, you get N additional Release::find queries. Each gets their own nested db transaction. This is very slow.

The change

This PR adds Directory::findChildReleases() which returns all releases for direct children of a given directory in a single query.

As this is intended as a unified query interface for both the subsonic API and my upcoming second attempt at the Folder Browsing UI, I return a vector of ChildRelease structs containing the Release as well as the count of releases found inside the directory. This so that the folder UI can direct-link to the release only if it's alone in its directory, whereas subsonic wants to link an arbitrary release even if there are several candidates.

Performance

I measured on a raspberry pi 4 using the Dockerfile-release container, calling /getMusicDirectory with my real database file, with some large directories with a lot of subdirs. I observed a 1.26x mean speedup.

I also noted that it's still very slow on the raspi, with the biggest dir going from 3253ms to 2780ms. This is because createAlbumNode() runs 8 further database queries per-release to retrieve Genre, Mood and so on, essentially the same problem this PR solves but more so. The solution would be to do all of this in one large chain of JOINs and have sqlite sort it all out inside one query. This will be a lot faster.

@JonnieCache
JonnieCache changed the base branch from master to develop August 18, 2026 16:34
Returns the releases held by the direct children of a directory in a single
query, for callers that list a directory and need each child's release.
The subdirectory loop looked up each child's release separately, so listing a
directory cost one query per child, each in its own nested transaction. Resolve
them all up front instead.
@JonnieCache
JonnieCache force-pushed the subsonic-child-releases branch from 77ec387 to 3e2258b Compare August 18, 2026 18:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant