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
This commit is contained in:
2026-09-13 13:19:48 +10:00
parent 25269263ce
commit 91655fcb0a
5 changed files with 242 additions and 15 deletions
+12 -1
View File
@@ -60,7 +60,7 @@ return 1
| File | Purpose |
|------|---------|
| `MediaBrowser.Controller/ScheduledTasks/IScanLeaderLease.cs` | DI contract for the leader lease |
| `MediaBrowser.Controller/ScheduledTasks/ScanLeaderOptions.cs` | `Enabled`, `LeaseDurationSeconds`, `GatedTaskKeys` |
| `MediaBrowser.Controller/ScheduledTasks/ScanLeaderOptions.cs` | `Enabled` (defaults to on when Redis is configured), `LeaseDurationSeconds`, `GatedTaskKeys` |
| `MediaBrowser.Controller/ScheduledTasks/NullScanLeaderLease.cs` | Always-leader default, preserving single-instance behaviour |
| `Emby.Server.Implementations/ScheduledTasks/RedisScanLeaderLease.cs` | Redis TTL lease; an unreachable Redis is treated as holding the lease |
@@ -69,6 +69,17 @@ Gated by default: `RefreshLibrary`, `RefreshPeople`, `RefreshChapterImages`,
`CleanupUserDataTask`, `OptimizeDatabaseTask`. Only timer-driven runs are gated;
manual and API-triggered runs always execute locally.
Gating is on whenever `Jellyfin:TranscodeStore:RedisConnectionString` is set, because that is only
set for a multi-instance deployment. Set `Jellyfin:ScanLeader:Enabled=false` to opt out.
Startup logs which way it went:
```
Scan-leader gating is active: timer-driven library tasks run only on the instance holding the Redis scan-leader lease.
Scan-leader gating is off: timer-driven library tasks run on every instance.
```
`Enabled=true` with no Redis connection string logs a warning, because gating cannot run.
### PostgreSQL provider
`src/Jellyfin.Database/Jellyfin.Database.Providers.PostgreSQL/` is an EF Core