Commit Graph

30323 Commits

Author SHA1 Message Date
benvin 5177d6fb72 Merge pull request 'feat(session): share the session directory between instances' (#33) from benvin/session-directory into main
ci/woodpecker/push/ci Pipeline was successful
Reviewed-on: #33
2026-09-27 11:24:31 +10:00
benvin e3c1d9cb6b Merge pull request 'fix(ha): stop startup when the quick connect store is unreachable' (#37) from benvin/quickconnect-startup-fail-closed into main
ci/woodpecker/push/ci Pipeline was canceled
Reviewed-on: #37
2026-09-27 11:24:19 +10:00
unkin-agent 33a5fbce9b retry building the quick connect store in the startup probe, not just reading it
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-09-26 22:56:28 +10:00
unkin-agent 6c7f76fd26 retry the quick connect startup probe, and exit non-zero when a start fails
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
2026-09-26 22:14:14 +10:00
unkin-agent 9f4c857b23 test(session): cover the maintenance sweeps and capabilities routing
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
2026-09-26 22:11:03 +10:00
unkin-agent ce7e9f0c3d fix(session): bound a routed request and stop hiding a failed subscribe 2026-09-26 22:11:03 +10:00
unkin-agent bb26760011 fix(session): keep the maintenance sweeps and capabilities with the session owner 2026-09-26 22:11:03 +10:00
unkin-agent af4e44173f Merge remote-tracking branch 'origin/main' into benvin/session-directory
# Conflicts:
#	.woodpecker/ci.yaml
#	Jellyfin.Server/CoreAppHost.cs
#	tests/Jellyfin.Server.Tests/HighAvailability/RedisTestServer.cs
2026-09-26 20:43:52 +10:00
unkin-agent 624d528d28 install libfontconfig1 for the docker test step
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
The startup tests build a real app host, which probes the Skia encoder, and
loading libSkiaSharp needs fontconfig.
2026-09-26 19:30:43 +10:00
unkin-agent a99ca458bf fail startup when the quick connect store is unreachable
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
Read the configured quick connect store during InitializeServices and abort
startup, with a log line naming valkey, instead of coming up and failing on
the first request that needs the store.
2026-09-26 19:09:24 +10:00
benvin 2a09108d4f Merge pull request 'fix(ha): share quick connect state between instances' (#34) from benvin/quickconnect-shared-state into main
ci/woodpecker/push/ci Pipeline was successful
Reviewed-on: #34
2026-09-26 16:39:55 +10:00
unkin-agent 577d24d190 test(session): prove the directory and bus fall back together
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-09-26 15:12:04 +10:00
unkin-agent 611bcf2c4a fix(session): confirm routed delivery and keep playback state with the owner 2026-09-26 14:45:40 +10:00
unkin-agent e1ca272d6c fail quick connect closed on an unreachable valkey and restore the idempotent exchange
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
2026-09-26 14:28:45 +10:00
unkin-agent 086fdb8257 fix(session): parse the owner key without assuming the pod id
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
2026-09-25 00:04:54 +10:00
unkin-agent 51261b0128 test(session): sample ownership after each non-owner request
ci/woodpecker/push/ci Pipeline was canceled
ci/woodpecker/pr/ci Pipeline was canceled
2026-09-25 00:01:42 +10:00
unkin-agent 9e66708d87 fix(session): tie directory ownership to the live connection
Ownership is claimed with a Lua check-and-set keyed on the instance holding
the websocket, routing prefers a live controller over a local copy, the
session list deduplicates by owner, removal is ownership-checked, undelivered
routed messages surface, single-session lookups stop scanning the keyspace and
directory writes leave the request path bounded by a timeout.
2026-09-24 23:50:01 +10:00
unkin-agent 6c54a02240 make quick connect authorize atomic and stop the fallback shadowing redis
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-09-24 23:38:35 +10:00
unkin-agent 6f362c33c9 fix(session): satisfy StyleCop member ordering and indentation
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-09-24 23:08:52 +10:00
unkin-agent ba4d487c65 share quick connect state between instances
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
Move the pending requests and authorized secrets out of process so the
initiate, authorize and exchange legs can land on different replicas.
2026-09-24 23:02:56 +10:00
unkin-agent 00d0765152 feat(session): share the session directory between instances
ci/woodpecker/pr/ci Pipeline failed
ci/woodpecker/push/ci Pipeline failed
Publish every session to valkey with the instance holding it, and route a
command for a non-local session to its owner over a per-instance pub/sub
channel. Entries expire, so a dead instance leaves the directory.
2026-09-24 22:48:48 +10:00
benvin 6691b785c3 Merge pull request #32 from benvin/userdata-cache
ci/woodpecker/push/ci Pipeline was successful
fix(userdata): read user data through to the database
2026-09-21 23:13:37 +10:00
benvin 2adb13f50f Merge pull request #29 from benvin/config-propagation
ci/woodpecker/push/ci Pipeline was successful
fix(ha): propagate shared-config and library-visibility changes between replicas
2026-09-21 21:44:34 +10:00
benvin 1c98f4a074 Merge pull request #31 from benvin/pg-tests-in-ci
ci/woodpecker/push/ci Pipeline was successful
test(db): run the PostgreSQL provider tests in CI
2026-09-21 07:45:29 +10:00
benvin 393994a454 Merge pull request #30 from benvin/nextup-datetime-kind
ci/woodpecker/push/ci Pipeline was canceled
fix(api): normalise the Next Up cutoff to UTC
2026-09-21 07:42:33 +10:00
benvin ad50c4e433 Merge pull request #28 from benvin/gated-task-keys
ci/woodpecker/push/ci Pipeline was canceled
fix(ha): gate the remaining timer-driven scheduled tasks
2026-09-21 07:40:32 +10:00
unkin-agent 483c739fb1 report a peer's port change locally without rewriting it
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
Keep IConfigurationManager source-compatible for plugin implementers.
2026-09-21 00:46:16 +10:00
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 d39ec60e2c test(db): link PostgreSqlTestServer instead of referencing Jellyfin.Server.Tests
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-09-21 00:29:11 +10:00
unkin-agent a9d6c749fb keep an applied invalidation from inducing a write that publishes back
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
2026-09-21 00:24:01 +10:00
unkin-agent 44b62dcc64 test(ha): pin the default gated task key set
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-09-20 23:55:17 +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 a025655b4d test(db): run the PostgreSQL provider tests in CI
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
Point Jellyfin.Database.Tests.PostgreSQL at the server postgres-migration-chain
already runs, give every test its own database, and fix the two tests that only
ever failed against real PostgreSQL.
2026-09-20 23:48:43 +10:00
unkin-agent face8ac653 fix(api): normalise the Next Up cutoff to UTC
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
The query-string cutoff binds as DateTimeKind.Unspecified, which Npgsql
refuses to write to timestamp with time zone, so /Shows/NextUp 500s.
2026-09-20 23:47:23 +10:00
unkin-agent b662ffa48f propagate shared-config and library-option changes between instances
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
Add a Redis pub/sub invalidation bus, publish from the configuration and library-option write paths, and drop the matching local cache entry on the instances that did not write. No-op without a Redis connection string, and fails open when it is unreachable.
2026-09-20 23:47:21 +10:00
unkin-agent 1965c68a76 fix(ha): gate the remaining timer-driven scheduled tasks
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
Add the eight provider, live TV and plugin-update task keys to
ScanLeaderOptions.GatedTaskKeys and widen the test's task-key discovery to
every assembly that declares an IScheduledTask.
2026-09-20 23:36:34 +10:00
benvin ec581b5e5f Merge pull request 'fix(ha): gate library tasks on the scan leader by default' (#11) from benvin/scan-leader-default into main
ci/woodpecker/push/ci Pipeline was successful
Reviewed-on: #11
2026-09-13 15:04:38 +10:00
unkin-agent b77702c851 merge: resolve CoreAppHost conflict with main, drop dead redisConnectionString local
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
2026-09-13 14:48:26 +10:00
benvin 2370787471 Merge pull request 'fix(db): collapse presentation-key groups without min(uuid)' (#10) from benvin/fix-guid-aggregate-pg into main
ci/woodpecker/push/ci Pipeline was successful
Reviewed-on: #10
2026-09-13 14:25:19 +10:00
benvin a652d718ca Merge pull request 'fix(ha): read transcode store config from the variable form deployments set' (#9) from benvin/ha-config-wiring into main
ci/woodpecker/push/ci Pipeline was canceled
Reviewed-on: #9
2026-09-13 14:24:11 +10:00
benvin 0c707c7989 Merge pull request 'fix(devices): read devices and device options through to the database' (#8) from benvin/fix-device-cache into main
ci/woodpecker/push/ci Pipeline was canceled
Reviewed-on: #8
2026-09-13 14:23:17 +10:00
unkin-agent 91655fcb0a fix(ha): gate library tasks on the scan leader by default
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
Jellyfin:ScanLeader:Enabled defaults to false and nothing sets it, so
leader election never runs and every replica executes the timer-driven
library tasks concurrently - the exact behaviour the lease prevents.

- Enable gating by default when a Redis connection string is configured
- Honour an explicit Enabled setting either way
- Carry the effective decision onto the bound options the task worker reads
- Log at startup whether gating is active
- Warn when gating is enabled but no Redis connection string is configured
2026-09-13 13:19:48 +10:00
unkin-agent 6e405af1dc fix(db): collapse presentation-key groups without min(uuid)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
PostgreSQL has no min(uuid) aggregate, so every query that picked a group
representative with MIN over the item id failed with 42883: library browse,
search, Recently Added, the by-name endpoints and Upcoming.

- Pick the representative with an anti-join on (primary version, id)
- Cover the collapse with a repository test against a real PostgreSQL
2026-09-13 13:18:11 +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 56919b9565 fix(devices): read devices and device options through to the database
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
The device cache was filled once at construction, so a token minted by one
replica was unknown to every other replica already running and a token revoked
on one replica stayed valid on the others until they restarted.

- drop the eager device and device options dictionaries
- read devices and device options from the database on every query
- push the device query filters and ordering into SQL
- open the request's database context only for the api key fallback
- cover both directions against real PostgreSQL with two manager instances
2026-09-13 13:08:47 +10:00
benvin 25269263ce Merge pull request 'test(db): run the startup migration chain against PostgreSQL in CI' (#7) from benvin/ci-postgres-migration-chain into main
ci/woodpecker/push/ci Pipeline was successful
Reviewed-on: #7
2026-09-12 22:22:12 +10:00
benvin b183bec94b Merge pull request 'fix(db): materialise the rating list before updating' (#6) from benvin/fix-rating-levels-pg into main
ci/woodpecker/push/ci Pipeline was canceled
Reviewed-on: #6
2026-09-12 22:21:30 +10:00
unkin-agent bc42ff4b28 test(db): drop a leftover test database before recreating it
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
A server handed in through JELLYFIN_TEST_POSTGRES outlives the run, so a second
run finds the databases the first one created. Also name the failures in
Jellyfin.Database.Tests.PostgreSQL the CI step steps around.
2026-09-12 21:36:09 +10:00
unkin-agent b501ba9620 test(db): run the startup migration chain against PostgreSQL in CI
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
Every PostgreSQL test carries Category=RequiresDocker and the pipeline filters
that category out, so the provider production runs on was never exercised and
two upgrade-path bugs reached it in a row. Nothing covered the whole startup
sequence either - code and schema migrations interleaved the way the migration
service orders them.

- run both database stages through JellyfinMigrationService against a seeded
  library and against a fresh install
- take the server from JELLYFIN_TEST_POSTGRES when it is set, else start a
  container
- add a pipeline step that runs the PostgreSQL tests on every push and pull
  request, with the server inside the step: the kubernetes backend has no
  docker daemon, and a service container deadlocks on the workspace volume
2026-09-12 21:28:17 +10:00
unkin-agent acab85ada3 merge the rating levels fix so the chain test has it 2026-09-12 21:20:27 +10:00