Commit Graph

1738 Commits

Author SHA1 Message Date
unkin-agent baa16b6586 fix: make transcode leases ownership-checked and cleanup-aware
Cleanup never matched a live session because the controller registered empty
manifest and segment paths, renewal was a read-modify-write that could revert a
takeover, and the takeover script compared an ISO date to a number, so it errored.

- populate the session record's manifest and segment paths from the playlist path
- renew the lease via a Lua compare-and-set on the owning pod
- store the lease expiry as unix milliseconds so the scripts can compare it
- retain the session record past its lease so an orphan can still be taken over
- test the Redis store against a real Redis, including the renew-vs-takeover race
- drop the live stream record nothing ever read back
2026-09-12 10:19:29 +10:00
unkin-agent 3b416c7fb2 feat: gate periodic library tasks behind a scan-leader lease
Timer-driven library tasks fire on every replica, so a library refresh or a
database optimise runs once per pod against the same shared library.

- add IScanLeaderLease with a Redis TTL implementation and a no-op default
- skip timer-driven runs of the gated tasks on instances without the lease
- treat an unreachable Redis as holding the lease so tasks never stop running
- leave manual and API-triggered runs ungated
2026-09-11 23:56:51 +10:00
unkin-agent e3571eb2a4 feat(session): record open live streams in the session store
Live stream ownership is only tracked in process memory, so no replica can tell
which pod holds a stream open once that pod is gone.

- persist a LiveStreamSession record when the live stream mappings change
- delete the record when the stream is closed
- keep closing the stream when the store is unreachable
2026-09-11 23:56:35 +10:00
unkin-agent 6ccabd4c72 feat(hls): register transcode sessions and renew their lease
A transcode that is not in the store is invisible to the other replicas, so the
HLS entry points have to publish and hold the lease themselves.

- register the play session in the store when ffmpeg starts
- renew the lease on a background loop and delete the session when it ends
- shorten segments and bound the playlist window when resuming a stored session
- add RecoverySegmentLengthSeconds and RecoverySegmentBufferCount encoding options
2026-09-11 23:56:35 +10:00
unkin-agent c43992630e feat: skip transcode files held by an active session
Every replica runs the transcode cleanup task against the same shared transcode
directory, so one pod deletes segments another pod is still streaming.

- read the active sessions from ITranscodeSessionStore before deleting
- keep files matching an active session manifest path or segment prefix
- abort the sweep when the store cannot be reached
2026-09-11 23:56:35 +10:00
unkin-agent e23d1a23be feat: add a durable transcode session store
Transcode state lives only in the process that started ffmpeg, so a pod restart
drops every in-flight HLS stream with no way for a peer to pick it up.

- add ITranscodeSessionStore plus the TranscodeSession and LiveStreamSession records
- add RedisTranscodeSessionStore with TTL leases and an atomic Lua takeover script
- add NullTranscodeSessionStore for single-instance deployments
- pick the store from Jellyfin:TranscodeStore:RedisConnectionString at startup
2026-09-11 23:56:19 +10:00
unkin-agent e68455f0ed feat(db): add opt-in PostgreSQL database provider
Multi-replica deployments cannot share a SQLite file, so the database has to
move to a server engine before the rest of the HA work is usable.

- add Jellyfin.Database.Providers.PostgreSQL with an EF Core Npgsql provider
- register the provider and a pooled NpgsqlDataSource when DatabaseType is Jellyfin-PostgreSQL
- accept postgresql:// URIs and POSTGRES_CONNECTION_STRING alongside CustomProviderOptions
- add container-backed provider, CRUD, concurrency and migration tests
2026-09-11 23:56:04 +10:00
Cody Robibero 85ebd83bdd Merge pull request #17821 from Shadowghost/more-counts
Expose optimized ItemCounts for byName items
2026-09-07 17:53:31 -04:00
Cody Robibero 42f7a6e720 Merge pull request #17820 from Shadowghost/only-download-missing-plugin-images
Only download missing plugin images
2026-09-07 17:43:57 -04:00
Cody Robibero 96f81b0c1b Merge pull request #17775 from slevin-7/fix-skia-sharpen-perf
Apply the resize sharpening kernel directly instead of via SKImageFilter
2026-09-07 17:43:48 -04:00
Cody Robibero 7d9bd1d3e4 Merge pull request #17816 from Shadowghost/version-aware-played-state
Share played state across alternate versions
2026-09-07 17:43:10 -04:00
Shadowghost 2644163f57 Count distinct items for byName ItemCounts and batch every kind 2026-09-07 18:39:59 +02:00
Shadowghost e1e319cb5c Only download missing plugin images 2026-09-07 10:43:36 +02:00
Shadowghost 59cd5f983b Expose optimized ItemCounts for byName items 2026-09-07 10:30:01 +02:00
Shadowghost 04a7568902 Fix TMDb search result ranking 2026-09-07 08:23:31 +02:00
Shadowghost fd016cfb13 Share played state across alternate versions 2026-09-06 17:20:18 +02:00
Cody Robibero f898c35b96 Merge pull request #17791 from Shadowghost/fix-code-migration
Don't dispose application singletons after running a code migration
2026-09-06 07:45:43 -04:00
Cody Robibero 34feb3c04a Merge pull request #17763 from Shadowghost/fix-refresh-queue-and-directory-cache
Fix items being lost from the refresh queue and bound the directory service caches
2026-09-06 07:36:13 -04:00
Cody Robibero 8d108d2870 Merge pull request #17806 from jellyfin/fix/dovi-color-validation
Enforce dolby vision transfer check
2026-09-06 07:35:32 -04:00
Cody Robibero 2555ab7539 Merge pull request #17805 from Shadowghost/fix-unordered-multiepisode-nfo
Fix handling of unordered multi-episode NFOs
2026-09-06 07:34:45 -04:00
Cody Robibero edb6cd11da Merge branch 'master' into fix-code-migration 2026-09-06 07:34:30 -04:00
Shadowghost 7b638a22bb Add test 2026-09-06 09:07:22 +02:00
Shadowghost 79a6ac6d82 Don't read episode markers in episode titles as a multi-episode range 2026-09-06 08:04:34 +02:00
Shadowghost ca90347dc2 Resolve migration routine loggers from the application container 2026-09-06 07:54:11 +02:00
Cody Robibero 66d038c403 Merge pull request #17762 from Shadowghost/fix-scan-memory-leak
Bound change batches during a scan; keep ffprobe and image saves from failing
2026-09-06 01:28:02 -04:00
gnattu a1910a7b2e Enforce dolby vision transfer check
Dolby vision files having unexpected transfers now also marked as invalid, and it will now get its base video range from its base layer color transfer, as not all invalid dolby vision files are HDR now.
2026-09-06 02:53:52 +08:00
Shadowghost 006809f02a Fix handling of unordered multi-episode NFOs 2026-09-05 19:32:56 +02:00
Cody Robibero 84589380e5 Merge pull request #17746 from kfarnung/fix/vobsub-idx-subtitle-language
Probe .idx instead of .sub for external VobSub subtitle language detection
2026-09-05 11:09:46 -04:00
Cody Robibero 441a05ac88 Merge pull request #17768 from Shadowghost/fix-livetv-hls-audio-codec-and-manifest-direct-play
Fix Live TV HLS playback: bogus audio encoder and unplayable direct played manifests
2026-09-05 11:00:31 -04:00
Cody Robibero 44ecc909ff Merge pull request #17796 from fmarcac/fix/syncplay-shuffle-mode-crash
Fix crash when SyncPlay shuffle mode is set to sorted twice
2026-09-05 10:58:31 -04:00
Cody Robibero 2b0ccf2a30 Merge pull request #17800 from fmarcac/fix/syncplay-active-session-counter
Fix SyncPlay active session counter leaking on rejoin
2026-09-05 10:57:55 -04:00
fmarcac 7ce911a401 Clamp client reported ping in SyncPlay groups 2026-09-05 15:06:37 +02:00
fmarcac 0c05d9d1a9 Apply the SyncPlay resume delay floor in the correct unit 2026-09-05 14:24:49 +02:00
fmarcac e5bfe562bc Fix crash when SyncPlay shuffle mode is set to sorted twice 2026-09-05 14:24:48 +02:00
fmarcac 51a7d5d08a Fix SyncPlay active session counter leaking on rejoin 2026-09-05 14:24:48 +02:00
Shadowghost f8470630be Retire runners that are cancelled before they start 2026-09-05 09:59:12 +02:00
Shadowghost c622a16261 Don't dispose application singletons after running a code migration 2026-09-05 07:37:09 +02:00
Shadowghost e5cd3381ac Limit cache size again
Co-Authored-By: Cody Robibero <cody@robibe.ro>
2026-09-05 07:09:29 +02:00
Shadowghost 46dd7d8e99 Invalidate the singleton DirectoryService cache on filesystem changes 2026-09-04 19:28:59 +02:00
Shadowghost 0d9c9c9ecc Fix the library scheduler never retiring its runners 2026-09-04 19:23:29 +02:00
Shadowghost fc37151fc4 Use platform separators in the DirectoryService path tests 2026-09-04 06:57:18 +02:00
Cody Robibero c96ff18e5b Merge pull request #17757 from felixfoertsch/fix/legacy-filter-tag-query
Fix UI stalls caused by large tag and genre sets
2026-09-03 18:36:37 -04:00
Shadowghost b724e57458 Reduce comments 2026-09-03 11:51:02 +02:00
Albert 064de2172e Apply the resize sharpening kernel directly instead of via SKImageFilter
Since the SkiaSharp 3 update the MatrixConvolution image filter used in
SkiaEncoder.ResizeImage no longer has a fast CPU path: on the software
rasterizer it takes about 4.5 seconds per megapixel-sized image, which
turns every cold image request into a multi-second operation and makes
first-time loads of a library view take minutes.

Draw the resize without the paint filter and apply the identical 3x3
kernel (same weights, clamped edges, alpha included) directly on the
resized pixels instead. This drops a cold 1000x1500 -> 663x995 poster
render from ~4.6s to well under a second; the convolution pass itself
takes ~86ms. Output is visually unchanged.
2026-09-02 21:41:36 +02:00
Felix Förtsch c3a7de54f3 avoid correlated item value name queries 2026-09-02 11:33:54 +02:00
Felix Förtsch 5adafb446f test legacy item value filter semantics 2026-09-02 11:29:24 +02:00
Felix Förtsch 3df58ab775 Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-09-02 11:05:36 +02:00
Shadowghost 8eb4964599 Never treat a manifest container as an audio codec or a direct play target 2026-09-02 09:29:48 +02:00
Shadowghost d73e3d964e Optimize Caches
Co-Authored-By: Cody Robibero <cody@robibe.ro>
2026-09-02 07:06:08 +02:00
Shadowghost e5dc3b8a54 Bound the directory caches a singleton would otherwise hold for the process lifetime 2026-09-01 22:04:06 +02:00