Optimize and reduce Jellyfin API calls and patch various issues - #267
Open
MattKercher wants to merge 2 commits into
Open
Optimize and reduce Jellyfin API calls and patch various issues#267MattKercher wants to merge 2 commits into
MattKercher wants to merge 2 commits into
Conversation
MattKercher
force-pushed
the
feature/jellyfin-api-fixes
branch
from
August 22, 2026 00:11
69aa7f3 to
354d7fa
Compare
MattKercher
force-pushed
the
feature/jellyfin-api-fixes
branch
2 times, most recently
from
September 4, 2026 21:17
f18f1e5 to
772079e
Compare
MattKercher
force-pushed
the
feature/jellyfin-api-fixes
branch
from
September 5, 2026 01:53
772079e to
6c1364e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The goal of this PR is to further refine the Jellyfin integration, as well as fix some outstanding bugs.
This started as a way to optimize for #259 but even with that closed, the changes ended up being useful for a lot of Jellyfin efficiency gains. This PR gets rid of any network requests made to the server while the models are being processed in bulk so the initial page loading is faster. Although I prefer to avoid changing the
base.pyAPI, I added a minimal flag to the verify functions so rows/buttons can instruct the integration to load a leaner API call since they don't require as much data. From there, the verify functions now work to layer on new data as it's retrieved, instead of an all-or-nothing approach where it used to check simply if the model existed.Notable Fixes
systemSearchfunction so it will now check the album model for cover art when the song doesn't have it.pingfunction timing out too quickly.Detailed Changes
COVER_SIZEdict toconstants.pyto keep track of the two sizes for the covers, which can be called withCOVER_SIZE["big"]forgdkPaintableBigandCOVER_SIZE["small"]forgdkPaintableMediaTypeStrEnumto Jellyfin to hold onto the names of the different media types instead of passing around raw strings, which can be called withMediaType.ALBUM,MediaType.ARTIST,MediaType.SONG, andMediaType.PLAYLISTgetCachedCoverArtfunction to bypass network calls so__bulk_compilecan simply grab from the image cache and write the album art to the model if the cover art has already been cached without making a network call if it's not cached. (This also fixes an issue withFavorite Songswhich used to slam my Jellyfin server because of the code I wrote where it'd try to fetch the cover art for every favorite song I had. At the same time. 馃珷)updateCoverArtto only fetch the 750 pixel cover art and compresses it using PIL on-device to 240 instead of making two API calls to the server for different sized cover art.minimalargument to the verify functions to instruct them to make leaner API calls when less data is necessary. This variable is set toTrueon all buttons and rows that call the verify functions. Note: I addedminimalto the function headers in Navidrome and Local but they don't utilize it.fetch_allfunction to handle the logic. Note: Some functions usethreading.Threadto callfetch_allto prevent theself.threadsThreadPoolExecutor from locking up waiting for a child thread to finish that wasn't able to execute because the pool executor queue ran out of workers.self.ongoing_requeststo track which requests are currently running to prevent duplicate calls to the same verify function. It's a dict that holds onto whether the current verify call is a minimal call so it can do a full API call if you load an album/artist/playlist page even if a minimal request is ongoing. Previously the functions would checkmodel_id in self.loaded_modelsbut since the verify functions can layer on more data as it's brought in, it needed a separate variable to track currently ongoing requests.__bulk_verifyto__bulk_compileas the prefetch code no longer uses the verify functions and instead processes the artist/album/song/playlist lists directly with a new__compile_response_jsonfunction.__write_to_modelfunction that takes a dict and writes it to the corresponding model_id. It only writes on the main thread usingGLib.idle_add(). As multiple threads can write to the model simultaneously, PyGObject was throwing C reference counter assertion errors due to GObject not being memory safe. UsingGLib.idle_add()has the dual benefit of making it so callbacks on the model variables that modify UI elements are now called from the main thread to reduce flickering and crashes.__compile_response_jsonsystemSearchfunction so it will now check the album model for cover art when the song doesn't have it.albumArtCheckvariable to the Song model so it knows if it fetched the albumArt from the album object. This prevents theverifySongfunction from repeatedly trying to fetch the album art if the album object doesn't have cover art either.pingcan run for longer when the server is being slow.Additional Thoughts/Questions
force_update
As of right now, the verify functions in Jellyfin ignore the
force_updateargument. Every time you'd navigate to the artist, album, or playlist pages it'd force the model to dump all of its information and redownload it. How come this is the default behavior? I imagine the Navidrome or Local integrations rely on it for something. I wanted to ask before messing with it, so I had the Jellyfin integration ignore it for now (it'd be trivial to re-add to thefetch_allfunction).Anyway, sorry for the giant PR description 馃檭 Thanks again for the awesome app!