jellyfin-qbittorrent-monitor: handle qbittorrent going down state
This commit is contained in:
@@ -257,5 +257,127 @@ pkgs.testers.runNixOSTest {
|
||||
|
||||
local_playback["PositionTicks"] = 50000000
|
||||
server.succeed(f"curl -sf -X POST 'http://localhost:8096/Sessions/Playing/Stopped' -d '{json.dumps(local_playback)}' -H 'Content-Type:application/json' -H 'X-Emby-Authorization:{local_auth}, Token={local_token}'")
|
||||
|
||||
# === SERVICE RESTART TESTS ===
|
||||
|
||||
with subtest("qBittorrent restart during throttled state re-applies throttling"):
|
||||
# Start external playback to trigger throttling
|
||||
playback_start = {
|
||||
"ItemId": movie_id,
|
||||
"MediaSourceId": media_source_id,
|
||||
"PlaySessionId": "test-play-session-restart-1",
|
||||
"CanSeek": True,
|
||||
"IsPaused": False,
|
||||
}
|
||||
start_cmd = f"curl -sf -X POST 'http://{server_ip}:8096/Sessions/Playing' -d '{json.dumps(playback_start)}' -H 'Content-Type:application/json' -H 'X-Emby-Authorization:{client_auth}, Token={client_token}'"
|
||||
client.succeed(start_cmd)
|
||||
time.sleep(2)
|
||||
assert is_throttled(), "Should be throttled before qBittorrent restart"
|
||||
|
||||
# Restart mock-qbittorrent (this resets alt_speed to False)
|
||||
server.succeed("systemctl restart mock-qbittorrent.service")
|
||||
server.wait_for_unit("mock-qbittorrent.service")
|
||||
server.wait_for_open_port(8080)
|
||||
|
||||
# qBittorrent restarted - alt_speed is now False (default)
|
||||
# The monitor should detect this and re-apply throttling
|
||||
time.sleep(3) # Give monitor time to detect and re-apply
|
||||
assert is_throttled(), "Monitor should re-apply throttling after qBittorrent restart"
|
||||
|
||||
# Stop playback to clean up
|
||||
playback_stop = {
|
||||
"ItemId": movie_id,
|
||||
"MediaSourceId": media_source_id,
|
||||
"PlaySessionId": "test-play-session-restart-1",
|
||||
"PositionTicks": 50000000,
|
||||
}
|
||||
stop_cmd = f"curl -sf -X POST 'http://{server_ip}:8096/Sessions/Playing/Stopped' -d '{json.dumps(playback_stop)}' -H 'Content-Type:application/json' -H 'X-Emby-Authorization:{client_auth}, Token={client_token}'"
|
||||
client.succeed(stop_cmd)
|
||||
time.sleep(2)
|
||||
|
||||
with subtest("qBittorrent restart during unthrottled state stays unthrottled"):
|
||||
# Verify we're unthrottled (no active streams)
|
||||
assert not is_throttled(), "Should be unthrottled before test"
|
||||
|
||||
# Restart mock-qbittorrent
|
||||
server.succeed("systemctl restart mock-qbittorrent.service")
|
||||
server.wait_for_unit("mock-qbittorrent.service")
|
||||
server.wait_for_open_port(8080)
|
||||
|
||||
# Give monitor time to check state
|
||||
time.sleep(3)
|
||||
assert not is_throttled(), "Should remain unthrottled after qBittorrent restart with no streams"
|
||||
|
||||
with subtest("Jellyfin restart during throttled state maintains throttling"):
|
||||
# Start external playback to trigger throttling
|
||||
playback_start = {
|
||||
"ItemId": movie_id,
|
||||
"MediaSourceId": media_source_id,
|
||||
"PlaySessionId": "test-play-session-restart-2",
|
||||
"CanSeek": True,
|
||||
"IsPaused": False,
|
||||
}
|
||||
start_cmd = f"curl -sf -X POST 'http://{server_ip}:8096/Sessions/Playing' -d '{json.dumps(playback_start)}' -H 'Content-Type:application/json' -H 'X-Emby-Authorization:{client_auth}, Token={client_token}'"
|
||||
client.succeed(start_cmd)
|
||||
time.sleep(2)
|
||||
assert is_throttled(), "Should be throttled before Jellyfin restart"
|
||||
|
||||
# Restart Jellyfin
|
||||
server.succeed("systemctl restart jellyfin.service")
|
||||
server.wait_for_unit("jellyfin.service")
|
||||
server.wait_for_open_port(8096)
|
||||
server.wait_until_succeeds("curl -sf http://localhost:8096/health | grep -q Healthy", timeout=60)
|
||||
|
||||
# During Jellyfin restart, monitor can't reach Jellyfin
|
||||
# After restart, sessions are cleared - monitor should eventually unthrottle
|
||||
# But during the unavailability window, throttling should be maintained (fail-safe)
|
||||
time.sleep(3)
|
||||
|
||||
# Re-authenticate (old token invalid after restart)
|
||||
client_auth_result = json.loads(client.succeed(
|
||||
f"curl -sf -X POST 'http://{server_ip}:8096/Users/AuthenticateByName' -d '@${payloads.auth}' -H 'Content-Type:application/json' -H 'X-Emby-Authorization:{client_auth}'"
|
||||
))
|
||||
client_token = client_auth_result["AccessToken"]
|
||||
|
||||
# No active streams after Jellyfin restart, should eventually unthrottle
|
||||
time.sleep(3)
|
||||
assert not is_throttled(), "Should unthrottle after Jellyfin restart clears sessions"
|
||||
|
||||
with subtest("Monitor recovers after Jellyfin temporary unavailability"):
|
||||
# Re-authenticate with fresh token
|
||||
client_auth_result = json.loads(client.succeed(
|
||||
f"curl -sf -X POST 'http://{server_ip}:8096/Users/AuthenticateByName' -d '@${payloads.auth}' -H 'Content-Type:application/json' -H 'X-Emby-Authorization:{client_auth}'"
|
||||
))
|
||||
client_token = client_auth_result["AccessToken"]
|
||||
|
||||
# Start playback
|
||||
playback_start = {
|
||||
"ItemId": movie_id,
|
||||
"MediaSourceId": media_source_id,
|
||||
"PlaySessionId": "test-play-session-restart-3",
|
||||
"CanSeek": True,
|
||||
"IsPaused": False,
|
||||
}
|
||||
start_cmd = f"curl -sf -X POST 'http://{server_ip}:8096/Sessions/Playing' -d '{json.dumps(playback_start)}' -H 'Content-Type:application/json' -H 'X-Emby-Authorization:{client_auth}, Token={client_token}'"
|
||||
client.succeed(start_cmd)
|
||||
time.sleep(2)
|
||||
assert is_throttled(), "Should be throttled"
|
||||
|
||||
# Stop Jellyfin briefly (simulating temporary unavailability)
|
||||
server.succeed("systemctl stop jellyfin.service")
|
||||
time.sleep(2)
|
||||
|
||||
# During unavailability, throttle state should be maintained (fail-safe)
|
||||
assert is_throttled(), "Should maintain throttle during Jellyfin unavailability"
|
||||
|
||||
# Bring Jellyfin back
|
||||
server.succeed("systemctl start jellyfin.service")
|
||||
server.wait_for_unit("jellyfin.service")
|
||||
server.wait_for_open_port(8096)
|
||||
server.wait_until_succeeds("curl -sf http://localhost:8096/health | grep -q Healthy", timeout=60)
|
||||
|
||||
# After Jellyfin comes back, sessions are gone - should unthrottle
|
||||
time.sleep(3)
|
||||
assert not is_throttled(), "Should unthrottle after Jellyfin returns with no sessions"
|
||||
'';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user