Commit Graph

447 Commits

Author SHA1 Message Date
unkin-agent 1c59e6afcb perf(nextup): batch the user data reads the next episode selection makes
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
Next Up walked every series in an unpaginated loop and read user data one
episode at a time, so the Home screen row cost two queries per series once the
cache was gone.

- read the played state of every candidate episode in one query
- read the versions the resume check and the last played date need in one query each
- default PrefetchedUserData on IUserBaseItemComparer so plugin comparers still compile
- cover the bounded query count and the plugin comparer with tests
- share one database across the replica tests
2026-09-21 00:36:39 +10:00
unkin-agent a7919b9bac fix(userdata): read user data through to the database
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
The user data cache and the item's in-memory rows were both filled once per
replica and never invalidated, so a pod serving a playback tick read its own
stale resume position and wrote it back over the position another pod had just
saved, silently losing resume points, played state, favourites and ratings.

- drop the user item data cache
- read single and batched user data from the database on every query
- prefetch user data for in-memory sorts and filters so each stays one query
- cover the lost update against real PostgreSQL with two manager instances
2026-09-20 23:51:29 +10:00
unkin-agent 95220e2ed6 fix(ha): read transcode store config from the variable form deployments set
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
The startup configuration only reads JELLYFIN_ prefixed environment
variables, so the bare Jellyfin__TranscodeStore__* form used by the chart,
the manifests and the README is dropped and the Redis store is never
registered. Nothing logs the selected store, so the fallback is invisible.

- Read bare Jellyfin__* variables into the Jellyfin:* configuration root
- Keep an explicit JELLYFIN_ variable winning over the bare form
- Log the selected transcode session store at startup
- Ping Redis once at startup and log an unreachable store at Error
- Log endpoints only, never the connection string
2026-09-13 13:10:52 +10:00
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 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
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
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 fd016cfb13 Share played state across alternate versions 2026-09-06 17:20:18 +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
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
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
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 ccdc69e3b0 Treat an item deleted mid-save as a no-op when saving its images 2026-09-01 21:42:07 +02:00
Shadowghost c5f8a93513 Close a change batch on its own window so a library scan cannot grow it without bound 2026-09-01 21:42:06 +02:00
Shadowghost 50f08d41a4 Find dead people and artists by id, not by name 2026-09-01 19:49:25 +02:00
Felix Förtsch 145258865a avoid correlated legacy item value filter queries
The legacy filter queries projected ItemValue before grouping tags and genres. EF Core translated that shape into duplicated correlated aggregates, causing multi-minute requests for libraries with many distinct values and blocking unrelated SQLite-backed API calls.

Join ItemValuesMap directly to ItemValues before grouping. This preserves type and item filtering, clean-value grouping, minimum-value selection and ordering while producing one aggregate query. Add an in-memory SQLite regression test for result semantics and both SQL shapes.
2026-09-01 14:37:44 +02:00
Shadowghost 7ccce8e0e7 Fix recursive handling for LinkedChildren 2026-08-31 17:56:56 +02:00
Cody Robibero 420d44f638 Merge commit from fork
Fix broken access control in session management
2026-08-30 14:40:25 -04:00
Shadowghost 27d898e59e Count a season's episodes by the season they belong to 2026-08-29 21:39:14 +02:00
Shadowghost ea5f83328d Support anime provider ids on season folders 2026-08-28 15:48:17 +02:00
Shadowghost 2aad6047c8 Fix children count on virtual items 2026-08-26 18:57:50 +02:00
Cody Robibero f682c22b08 Merge pull request #17715 from Shadowghost/fix-people-cleanup
Delete credits nothing maps to and bound item-by-name folder names
2026-08-25 18:28:52 -04:00
Cody Robibero e79e2cba27 Merge pull request #17714 from Shadowghost/fix-localized-view-ids
Stop deriving user view ids from their localized name
2026-08-25 18:26:09 -04:00
Shadowghost a81b90f570 Fix tests 2026-08-25 21:03:51 +02:00
Shadowghost 6978dfc294 Delete a credit once no item maps to it any more 2026-08-25 20:31:30 +02:00
Piotr Niełacny 5e621d0e3f Order IsPlayed and IsUnplayed by the played state the filter reports
Ordering mapped both keys to the item's own stored UserData row. Folders do not
have one: a series, season or box set counts as played when no descendant is
left unplayed, which is what the isPlayed filter and the DTO both report. A
mixed library therefore sorted every series and box set into the unplayed group,
and a query could filter and sort by two different notions of "played".

Extract the filter's predicate into BuildIsPlayedFilter and route both sort keys
through it so the two cannot drift apart again.
2026-08-25 15:19:38 +02:00
Shadowghost e1af8dce05 Merge remote-tracking branch 'upstream/master' into fix-series-merging 2026-08-22 17:18:01 +02:00
Shadowghost 587f06dccc Multiple fixes and improvements
Co-Authored-By: Cody Robibero <cody@robibe.ro>
2026-08-22 07:42:56 +02:00
Shadowghost 7ad5ff6aa7 Merge remote-tracking branch 'upstream/master' into optimize-db-helper-memory
# Conflicts:
#	src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/JellyfinDbModelSnapshot.cs
2026-08-22 07:01:58 +02:00
Shadowghost 8e80677bdd Fix series merging leaking across libraries and under-counting merged children 2026-08-21 22:48:47 +02:00
Tim Eisele fb50b4df8b Stop user updates from orphaning permission and preference rows (#17645)
* Stop user updates from orphaning permission and preference rows

* Make UserId non-nullable

* Remove unnecessary ToList

* Update Jellyfin.Server.Implementations/Users/UserManager.cs

Co-authored-by: Claus Vium <cvium@users.noreply.github.com>

---------

Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2026-08-20 18:35:26 +02:00
Cody Robibero 4a659fb30c Merge pull request #17631 from itsb/fix/confirmed-resume-position-master
Use client-reported position for idle playback cleanup
2026-08-18 17:12:00 -04:00
m0g3r 46be43ad24 Prevent orphaned user permissions and preferences (#17643)
Prevent orphaned user permissions and preferences
2026-08-18 18:16:48 +02:00
martin-77 c539ee7e81 Fix SQLite variable limit in child count batches 2026-08-17 01:43:10 +02:00
itsb f0c5370e27 Preserve unknown idle playback position 2026-08-16 09:09:18 -05:00
itsb 499e64b1c3 Use client-reported position for idle playback cleanup 2026-08-14 23:31:39 -05:00
Shadowghost 4de43d36dd Require session ownership for additional users, capabilities and viewing reports 2026-08-14 14:50:07 +02:00