Skip to content

Commit 6c64de6

Browse files
authored
Keep package publish lock fresh (#11)
* Keep package publish lock fresh * Isolate publish lock heartbeat cleanup
1 parent 879d9d1 commit 6c64de6

1 file changed

Lines changed: 69 additions & 0 deletions

File tree

scripts/publish-package-repo.sh

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,13 @@ MERGED_DIST_DIR="$(mktemp -d)"
3535
PACKAGE_REPO_ASSET_DIR="$(mktemp -d)"
3636
LOCK_TIMEOUT_SECONDS="${LOCK_TIMEOUT_SECONDS:-600}"
3737
LOCK_POLL_SECONDS="${LOCK_POLL_SECONDS:-5}"
38+
LOCK_HEARTBEAT_SECONDS="${LOCK_HEARTBEAT_SECONDS:-60}"
3839
LOCK_OWNER="${LOCK_OWNER:-$(hostname)-$$-$(date -u +%s)}"
3940
current_step="initializing"
4041
private_key_file=""
4142
passphrase_file_secret=""
4243
lock_error_file=""
44+
lock_heartbeat_pid=""
4345

4446
log_step() {
4547
current_step="$1"
@@ -54,6 +56,7 @@ on_error() {
5456
}
5557

5658
cleanup() {
59+
stop_lock_heartbeat
5760
release_lock
5861
if [ -n "${private_key_file:-}" ]; then
5962
rm -f "$private_key_file"
@@ -110,6 +113,71 @@ release_lock() {
110113
fi
111114
}
112115

116+
refresh_lock() {
117+
local generation details new_generation
118+
119+
if [ ! -f "$lock_generation_file" ]; then
120+
return 0
121+
fi
122+
123+
generation="$(cat "$lock_generation_file" 2>/dev/null || true)"
124+
if [ -z "$generation" ]; then
125+
return 0
126+
fi
127+
128+
: >"$lock_error_file"
129+
if printf '%s\n' "$LOCK_OWNER" | gcloud storage cp - "$lock_path" --if-generation-match="$generation" >/dev/null 2>"$lock_error_file"; then
130+
details="$(describe_lock)"
131+
new_generation="$(printf '%s\n' "$details" | awk '{print $1}')"
132+
if [ -z "$new_generation" ]; then
133+
printf 'Refreshed publish lock at %s, but could not resolve its generation\n' "$lock_path" >&2
134+
return 1
135+
fi
136+
printf '%s' "$new_generation" >"$lock_generation_file"
137+
printf 'Refreshed publish lock generation %s\n' "$new_generation"
138+
return 0
139+
fi
140+
141+
printf 'Unable to refresh publish lock at %s\n' "$lock_path" >&2
142+
if [ -s "$lock_error_file" ]; then
143+
cat "$lock_error_file" >&2
144+
fi
145+
return 1
146+
}
147+
148+
lock_heartbeat_loop() {
149+
local parent_pid="$1"
150+
151+
trap - EXIT ERR
152+
153+
while true; do
154+
sleep "$LOCK_HEARTBEAT_SECONDS"
155+
if ! refresh_lock; then
156+
printf 'Publish lock heartbeat failed; stopping publisher to avoid concurrent repository writes\n' >&2
157+
kill -TERM "$parent_pid" >/dev/null 2>&1 || true
158+
exit 1
159+
fi
160+
done
161+
}
162+
163+
start_lock_heartbeat() {
164+
if [ "${LOCK_HEARTBEAT_SECONDS:-0}" -le 0 ]; then
165+
return 0
166+
fi
167+
168+
lock_heartbeat_loop "$$" &
169+
lock_heartbeat_pid="$!"
170+
printf 'Started publish lock heartbeat every %ss\n' "$LOCK_HEARTBEAT_SECONDS"
171+
}
172+
173+
stop_lock_heartbeat() {
174+
if [ -n "${lock_heartbeat_pid:-}" ]; then
175+
kill "$lock_heartbeat_pid" >/dev/null 2>&1 || true
176+
wait "$lock_heartbeat_pid" 2>/dev/null || true
177+
lock_heartbeat_pid=""
178+
fi
179+
}
180+
113181
acquire_lock() {
114182
local details generation update_time age now
115183
log_step "Acquiring publish lock at $lock_path"
@@ -124,6 +192,7 @@ acquire_lock() {
124192
fi
125193
printf '%s' "$generation" >"$lock_generation_file"
126194
printf 'Acquired publish lock generation %s\n' "$generation"
195+
start_lock_heartbeat
127196
return 0
128197
fi
129198

0 commit comments

Comments
 (0)