#!/bin/sh
# The updater's schedule: the procd instance `updater` of the init (WP A-5). It checks the feed twice a day (UPD-1: a banner within
# 24 h of a release) at a random minute, so a fleet does not call the feed at the same second, and it runs a retry that the updater
# itself scheduled after a network failure (UPD-2: tried again with growing waits, never given up for good). It never starts an
# update nobody asked for: automatic updates are WP A-5b (R1.1).
# One sleeping shell and nothing else; a check or an apply is a separate process (apply detaches, so the update that stops this
# service does not stop itself).
# Seams: FVPN_UPDATE_{RUN,LIBEXEC} as run; FVPN_UPDATE_TICK, _FIRST, _EVERY (seconds).
RUN=${FVPN_UPDATE_RUN:-/var/run/forestvpn}
LIBEXEC=${FVPN_UPDATE_LIBEXEC:-/usr/libexec/forestvpn}
TICK=${FVPN_UPDATE_TICK:-900}
rnd() { local n; n=$(od -An -N2 -tu2 /dev/urandom 2>/dev/null | tr -d ' '); echo $(( ${n:-0} % $1 )); }

next=$(( $(date +%s) + ${FVPN_UPDATE_FIRST:-$(( 120 + $(rnd 1680) ))} ))   # the first check 2 to 30 minutes after the service starts
while :; do
	t=$(date +%s)
	if [ "$t" -ge "$next" ]; then
		if "$LIBEXEC/update/run" check; then next=$(( t + ${FVPN_UPDATE_EVERY:-43200} + $(rnd 7200) ))
		else next=$(( t + 1800 + $(rnd 1800) )); fi   # the feed did not answer: sooner than twelve hours
	fi
	if [ -f "$RUN/update/retry" ]; then
		due=$(cut -d' ' -f2 "$RUN/update/retry" 2>/dev/null)
		[ -n "$due" ] && [ "$(date +%s)" -ge "$due" ] && "$LIBEXEC/update/run" apply >/dev/null
	fi
	sleep "$TICK"
done
