wait on qbt service before init

This commit is contained in:
2026-03-15 13:45:07 -04:00
parent 7c0a617640
commit ef0da7582c
2 changed files with 36 additions and 19 deletions

View File

@@ -51,6 +51,17 @@ let
tvCategory = "tvshows";
};
};
serviceName = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
Name of the systemd service for this download client.
When set, the init service will depend on (After + Requires) this service,
ensuring the download client is running before health checks execute.
'';
example = "qbittorrent";
};
};
};
@@ -424,6 +435,13 @@ let
# Get list of service names that syncedApps depend on
getSyncedAppDeps = inst: map (app: "${app.serviceName}.service") inst.syncedApps;
# Get list of service names that download clients depend on
getDownloadClientDeps =
inst:
lib.concatMap (
dc: lib.optional (dc.serviceName != null) "${dc.serviceName}.service"
) inst.downloadClients;
enabledInstances = lib.filterAttrs (_: inst: inst.enable) cfg;
mkBazarrProviderSection =
@@ -525,8 +543,9 @@ in
"${inst.serviceName}.service"
]
++ (getSyncedAppDeps inst)
++ (getDownloadClientDeps inst)
++ (lib.optional (inst.networkNamespacePath != null) "wg.service");
requires = [ "${inst.serviceName}.service" ];
requires = [ "${inst.serviceName}.service" ] ++ (getDownloadClientDeps inst);
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";

View File

@@ -88,10 +88,6 @@ pkgs.testers.runNixOSTest {
{
description = "Mock qBittorrent API";
wantedBy = [ "multi-user.target" ];
before = [
"sonarr-init.service"
"radarr-init.service"
];
serviceConfig = {
ExecStart = "${pkgs.python3}/bin/python3 ${mockQbitScript}";
Type = "simple";
@@ -131,6 +127,7 @@ pkgs.testers.runNixOSTest {
implementation = "QBittorrent";
configContract = "QBittorrentSettings";
protocol = "torrent";
serviceName = "mock-qbittorrent";
fields = {
host = "127.0.0.1";
port = 6011;
@@ -154,6 +151,7 @@ pkgs.testers.runNixOSTest {
implementation = "QBittorrent";
configContract = "QBittorrentSettings";
protocol = "torrent";
serviceName = "mock-qbittorrent";
fields = {
host = "127.0.0.1";
port = 6011;
@@ -272,27 +270,27 @@ pkgs.testers.runNixOSTest {
assert "health check" in prowlarr_journal.lower() or "testing" in prowlarr_journal.lower(), \
"Expected health check log messages in prowlarr-init journal"
with subtest("Health check fails when download client is unreachable"):
# Stop mock qBittorrent to simulate failure
with subtest("Init service stops when download client service stops (Requires dependency)"):
# With serviceName set, sonarr-init has Requires=mock-qbittorrent.service.
# When mock-qbittorrent stops, sonarr-init should also be pulled down
# no spurious restart loops or alert spam.
machine.succeed("systemctl stop mock-qbittorrent.service")
# Restart sonarr-init - it should FAIL because download client test will fail
machine.execute("systemctl restart sonarr-init.service")
# Wait for the service to settle into failed state (it has Restart=on-failure)
# sonarr-init should be inactive (pulled down by dependency)
machine.wait_until_succeeds(
"systemctl show sonarr-init.service --property=Result | grep -q 'exit-code'",
timeout=60,
"systemctl show sonarr-init.service --property=ActiveState | grep -q 'inactive'",
timeout=30,
)
# Check journal for health check failure message
journal = machine.succeed("journalctl -u sonarr-init.service --no-pager")
assert "health check failed" in journal.lower(), \
"Expected health check failure message in sonarr-init journal, got: " + journal[-500:]
# radarr-init should also be inactive (same Requires dependency)
machine.wait_until_succeeds(
"systemctl show radarr-init.service --property=ActiveState | grep -q 'inactive'",
timeout=30,
)
with subtest("Health check fails when Prowlarr synced app is unreachable"):
# Sonarr is already stopped from previous subtest
# Also stop radarr to ensure both synced apps are unreachable
# Stop radarr to ensure synced apps are unreachable
# (sonarr is already stopped since sonarr-init was pulled down above)
machine.succeed("systemctl stop radarr.service")
# Restart prowlarr-init - it should FAIL because synced app connectivity test fails