Watch
0
0
Fork
You've already forked hyperhive
0
hyperhive/nix/host-modules/lib/retry-in-job.nix

38 lines
1.4 KiB
Nix

# Shared shell step for a oneshot that fetches over the network and that other
# units `Requires=`. `retry_in_job` repeats the fetch inside the unit's own
# start job, so a unit ordered `After=` it waits for the fetch to succeed. A
# unit that exits non-zero ends its job as `failed` and fails every `Requires=`
# dependent with `dependency`; a dependent whose start job failed is not
# started again when the retry succeeds, so ./store-retry.nix cannot cover
# this case.
#
# The retry stops at the budget and returns non-zero, so the unit still fails
# closed. Set the unit's `TimeoutStartSec` above the budget, or systemd kills
# the job before the helper gives up.
#
# Pure function — NOT a NixOS module. Call it from a unit's `script`:
#
# retryInJob = import ../host-modules/lib/retry-in-job.nix { };
# script = ''
# ${retryInJob}
# if ! retry_in_job 840 fetch; then exit 1; fi
# '';
{ }:
''
# retry_in_job <budget-seconds> <command…>: run the command until it
# succeeds, waiting 2s, doubling to at most 60s between attempts. Returns 1
# once another wait would pass the budget.
retry_in_job() {
local rc delay=2 deadline=$((SECONDS + $1))
shift
until "$@"; do
rc=$?
if [ $((SECONDS + delay)) -gt "$deadline" ]; then
return 1
fi
echo "the attempt failed with exit status $rc; retrying in $delay seconds." >&2
sleep "$delay"
delay=$((delay * 2 > 60 ? 60 : delay * 2))
done
}
''