Skip to content

Commit 9d6ffc3

Browse files
committed
feat(healthcheck): use ExecStartPost
1 parent 2216913 commit 9d6ffc3

File tree

1 file changed

+22
-55
lines changed

1 file changed

+22
-55
lines changed

modules/healthcheck/default.nix

Lines changed: 22 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,6 @@
7575
) config.mcl.services;
7676
in
7777
{
78-
assertions = lib.mapAttrsToList (
79-
serviceName: serviceConfig:
80-
let
81-
cfg = serviceConfig.healthcheck;
82-
in
83-
lib.mkIf (cfg != null && cfg.readiness-probe.enable) {
84-
assertion = cfg.exec != null;
85-
message = "When healthcheck.readiness-probe is enabled, you must define `healthcheck.exec` with the service command. (${serviceName})";
86-
}
87-
) servicesWithHealthcheck;
8878
systemd = {
8979
timers = lib.mapAttrs' (
9080
mainServiceName: serviceConfig:
@@ -120,8 +110,8 @@
120110
# If the TimeoutStartSec is not infinity, it can cause the service to fail, because the readiness probe is considered part of the startup.
121111
serviceConfig.TimeoutStartSec = lib.mkForce "infinity";
122112

123-
# We replace the ExecStart with a script that runs the readiness probe in the background, and the original service command in the foreground.
124-
serviceConfig.ExecStart =
113+
# We add a ExecStartPost with a script that runs the readiness probe
114+
serviceConfig.ExecStartPost =
125115
let
126116
scriptPath = lib.makeBinPath (
127117
[
@@ -133,46 +123,33 @@
133123
++ (serviceConfig.path or [ ])
134124
);
135125
in
136-
lib.mkForce (
137126
pkgs.writeShellScript "${mainServiceName}-readiness-check" ''
138127
#!${pkgs.runtimeShell}
139128
set -o nounset
140129
export PATH="${scriptPath}:$PATH"
141130
142-
check() {
143-
echo "Health check: starting background readiness probe for ${mainServiceName}."
144-
sleep ${toString probeCfg.initialDelay}
145-
retryCount=${toString probeCfg.retryCount}
146-
while true; do
147-
if (timeout ${toString probeCfg.timeout}s ${probeCfg.command} &> /dev/null); then
148-
echo "Health check: probe successful. Notifying systemd that the service is ready."
149-
systemd-notify --ready --status="${probeCfg.statusReadyMessage}"
150-
return 0
151-
else
152-
echo "Health check: probe not successful. Notifying systemd that the service is still waiting. Retrying in ${toString probeCfg.interval} seconds..."
153-
systemd-notify --status="${probeCfg.statusWaitingMessage}"
154-
if [[ ''${retryCount} -ne -1 ]]; then
155-
retryCount=$((retryCount - 1))
156-
if [[ ''${retryCount} -le 0 ]]; then
157-
echo "Health check: probe failed after maximum retries. Exiting."
158-
exit 1
159-
fi
131+
echo "Health check: starting background readiness probe for ${mainServiceName}."
132+
sleep ${toString probeCfg.initialDelay}
133+
retryCount=${toString probeCfg.retryCount}
134+
while true; do
135+
if (timeout ${toString probeCfg.timeout}s ${probeCfg.command} &> /dev/null); then
136+
echo "Health check: probe successful. Notifying systemd that the service is ready."
137+
systemd-notify --ready --status="${probeCfg.statusReadyMessage}"
138+
exit 0
139+
else
140+
echo "Health check: probe not successful. Notifying systemd that the service is still waiting. Retrying in ${toString probeCfg.interval} seconds..."
141+
systemd-notify --status="${probeCfg.statusWaitingMessage}"
142+
if [[ ''${retryCount} -ne -1 ]]; then
143+
retryCount=$((retryCount - 1))
144+
if [[ ''${retryCount} -le 0 ]]; then
145+
echo "Health check: probe failed after maximum retries. Exiting."
146+
exit 1
160147
fi
161148
fi
162-
sleep ${toString probeCfg.interval}
163-
done
164-
}
165-
166-
if [[ -n "''${NOTIFY_SOCKET:-}" ]]; then
167-
check &
168-
else
169-
echo "Health check: NOTIFY_SOCKET not set. Cannot run readiness probe." >&2
170-
exit 1
171-
fi
172-
173-
${cfg.exec}
174-
''
175-
);
149+
fi
150+
sleep ${toString probeCfg.interval}
151+
done
152+
'';
176153
}
177154
))
178155
) servicesWithHealthcheck;
@@ -246,16 +223,6 @@
246223
description = "Additional programs to add to the PATH for health checks.";
247224
};
248225

249-
# The main command for the service, required when readiness-probe is on.
250-
exec = lib.mkOption {
251-
type = lib.types.str;
252-
description = ''
253-
The actual command to run for the service.
254-
This MUST be used instead of `script` or `serviceConfig.ExecStart`
255-
when `readiness-probe.enable` is true.
256-
'';
257-
};
258-
259226
# The new readiness probe that uses the notify pattern.
260227
readiness-probe = lib.mkOption {
261228
type = lib.types.submodule readinessProbeOptions;

0 commit comments

Comments
 (0)