fix(jellyfin): off-media instant registration + native-webhook multi-version#272
Merged
Merged
Conversation
…ook multi-version
Two remaining multi-version/off-media gaps, both Jellyfin-specific.
1) Off-media instant registration was silently broken (HTTP 404 -> slow
fallback) for ALL off-media items. The app POSTed
/MediaPreviewBridge/Trickplay/{id} without `saveWithMedia`, so the plugin
defaulted to true and looked in the media-adjacent tile dir an off-media
publish never wrote -> 404 -> registration deferred to the next scheduled
scan instead of appearing immediately. Fix: `_trigger_item_refresh` sends
`saveWithMedia` matching the adapter's mode. Verified live: alternate
version POST returns 404 without the param, 204 with it; the real trigger
path now logs "Registered trickplay via Media Preview Bridge plugin".
App-only; no plugin release needed.
2) A native Jellyfin webhook resolving an item id previewed only the primary
version of a merged multi-version item. Added
`resolve_item_to_remote_paths(item_id) -> [(version_id, path)]` (base:
single; Jellyfin/Emby: every MediaSource, Emby yields one since versions are
separate item ids; Plex: every media[*].parts[*].file by bare ratingKey).
webhook_router resolves to a LIST and fans out one Job per version.
Single-version (and all Sonarr/Radarr path webhooks) keep the byte-identical
one-job response; multi-version returns {"status":"queued",
"version_count":N,"jobs":[...]}. server_id_filter is threaded into every
version's Job. Verified live against Jellyfin 10.11.11.
Tests: saveWithMedia param matrix; per-version resolvers + failure->[]; router
fan-out (Plex + Jellyfin) with per-version hints; per-server URL pins every
version; Emby item-id does not fan out.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YC1Z1JFBVJ5xKi5YAqYKfc
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## dev #272 +/- ##
==========================================
+ Coverage 83.97% 84.00% +0.03%
==========================================
Files 89 89
Lines 19599 19632 +33
==========================================
+ Hits 16458 16492 +34
+ Misses 3141 3140 -1
🚀 New features to boost your workflow:
|
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.
Closes the two remaining multi-version / off-media edges flagged after #269/#271. Both Jellyfin-specific; live-verified on Jellyfin 10.11.11.
1. Off-media instant trickplay registration (was silently 404'ing)
The app POSTed
/MediaPreviewBridge/Trickplay/{id}withoutsaveWithMedia, so the plugin defaulted totrueand asked Jellyfin for the media-adjacent tile dir — which an off-media publish never writes — and returned 404. Registration then fell back to the next scheduled metadata refresh instead of appearing immediately. This affected all off-media items (single- and multi-version).Fix:
_trigger_item_refreshnow sendssaveWithMediamatching the adapter's mode. App-only — no plugin release needed.Live A/B (alternate version, off-media): POST without the param →
404; withsaveWithMedia=false→204 registered. The real trigger path now logsRegistered trickplay via Media Preview Bridge pluginfor every version.2. Native Jellyfin webhook → every version
A native Jellyfin webhook resolving an item id previewed only the primary version of a merged item (alternates live in
MediaSources). Addedresolve_item_to_remote_paths(item_id) -> [(version_id, path)]:resolve_item_to_remote_pathresult.MediaSource(each tagged with its per-version GUID for off-media); Emby yields one (versions are separate item ids → no fan-out, matches the scan).media[*].parts[*].fileby bare ratingKey — brings the universal/incomingrouter to parity with/webhook, which already fanned out.webhook_routerresolves to a list and fans out one Job per version. Single-version and all Sonarr/Radarr path webhooks return the byte-identical one-job response; multi-version returns{"status":"queued","version_count":N,"jobs":[...]}.server_id_filteris threaded into every version's Job.Live:
resolve_item_to_remote_pathsreturns both versions with distinct GUIDs against real Jellyfin.Tests
saveWithMediamatrix (media-adjacent / off-media / default); per-version resolvers (Plex parts, Jellyfin MediaSources, failure →[]); router fan-out (Plex + Jellyfin) with per-version hint assertions; per-server URL pins every version; Emby item-id does not fan out. Full suite green (the only failures are the known flaky xdist worker-crash pollution — all pass in isolation). Architecture Review run; no HIGH, the MED + 2 LOW (test-matrix gaps) closed before commit.🤖 Generated with Claude Code