-
Notifications
You must be signed in to change notification settings - Fork 25
/
Copy pathlib
125 lines (106 loc) · 3.36 KB
/
lib
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/bin/bash
: "${BASH_LIB_DIR:?BASH_LIB_DIR must be set. Please source bash-lib/init before other scripts from bash-lib.}"
function bl_die(){
bl_fatal "${@}"
exit 1
}
function bl_fail(){
bl_error "${@}"
return 1
}
#safe pushd
function bl_spushd(){
if ! pushd "${1}" >/dev/null; then
bl_die "pushd ${1} failed :("
fi
}
#safe popd
function bl_spopd(){
popd >/dev/null || bl_die "popd failed :("
}
# Test if a variable contains a number
function bl_is_num(){
[[ ${1:-invalid} =~ ^-?[0-9\.]*$ ]]
}
# Retry a command multiple times until it succeeds, with escalating
# delay between attempts.
# Delay is 2 * n + random up to 30s, then 30s + random after that.
# For large numbers of retries the max delay is effectively the retry
# count in minutes.
# Based on:
# https://gist.github.com/sj26/88e1c6584397bb7c13bd11108a579746
# but now quite heavily modified.
function bl_retry {
# Maxiumum amount of fixed delay between attempts
# a random value will still be added.
local -r MAX_BACKOFF=30
local rc
local count
local retries
local backoff
if [[ ${#} -lt 2 ]]; then
bl_die "retry usage: retry <retries> <command>"
fi
retries=$1
shift
if ! bl_is_num "${retries}"; then
bl_die "Invalid number of retries: ${retries} for command '${*}'".
fi
count=0
until eval "$@"; do
# Command failed, otherwise until would have skipped the loop
# Store return code so it can be reported to the user
rc=$?
count=$((count + 1))
if [ "${count}" -lt "${retries}" ]; then
# There are still retries left, calculate delay and notify user.
backoff=$((2 * count))
if [[ "${backoff}" -gt "${MAX_BACKOFF}" ]]; then
backoff=${MAX_BACKOFF}
fi;
# Add a random amount to the delay to prevent competing processes
# from re-colliding.
wait=$(( backoff + (RANDOM % count) ))
bl_info "'${*}' Retry $count/$retries exited $rc, retrying in $wait seconds..."
sleep $wait
else
# Out of retries :(
bl_error "Retry $count/$retries exited $rc, no more retries left."
return $rc
fi
done
return 0
}
# retry function that waits a constant number of seconds between attempts.
function bl_retry_constant {
if [[ ${#} -lt 3 ]]; then
bl_die "retry usage: retry <retries> <interval (seconds)> <command>"
fi
local retries=$1; shift
local interval=$1; shift
local count
local rc
local interval
if ! bl_is_num "${retries}"; then
bl_die "Invalid number of retries: ${retries} for command '${*}'"
fi
if ! bl_is_num "${interval}"; then
bl_die "Invalid interval in seconds: ${retries} for command '${*}'".
fi
count=0
until eval "$@"; do
# Command failed, otherwise until would have skipped the loop
# Store return code so it can be reported to the user
rc=$?
count=$((count + 1))
if [ "${count}" -lt "${retries}" ]; then
bl_info "'${*}' Retry $count/$retries exited $rc, retrying in $interval seconds..."
sleep "${interval}"
else
# Out of retries :(
bl_error "Retry $count/$retries exited $rc, no more retries left."
return $rc
fi
done
return 0
}