expbackoff() {
# Exponential backoff: retries a command upon failure, scaling up the delay between retries.
# Example: "expbackoff my_command --with --some --args --maybe"
local MAX_RETRIES=${EXPBACKOFF_MAX_RETRIES:-8} # Max number of retries
local BASE=${EXPBACKOFF_BASE:-1} # Base value for backoff calculation
local MAX=${EXPBACKOFF_MAX:-300} # Max value for backoff calculation
local FAILURES=0
while ! "$@"; do
FAILURES=$(( $FAILURES + 1 ))
if (( $FAILURES > $MAX_RETRIES )); then
echo "$@" >&2
echo " * Failed, max retries exceeded" >&2
return 1
else
local SECONDS=$(( $BASE * 2 ** ($FAILURES - 1) ))
if (( $SECONDS > $MAX )); then
SECONDS=$MAX
fi
echo "$@" >&2
echo " * $FAILURES failure(s), retrying in $SECONDS second(s)" >&2
sleep $SECONDS
echo
fi
done
}
something_that_succeeds() { echo "I'm a winner!"; }
something_that_fails() { echo "I'm a loser :("; return 1; }
EXPBACKOFF_MAX_RETRIES=3 # Override default value - speeds up testing
expbackoff something_that_succeeds --calling it with -args
echo # Clear up the display
expbackoff something_that_fails --calling it with -args
echo
echo $? # Should be 1, indicating overall failure of `something_that_fails`