@@ -35,11 +35,13 @@ MERGED_DIST_DIR="$(mktemp -d)"
3535PACKAGE_REPO_ASSET_DIR=" $( mktemp -d) "
3636LOCK_TIMEOUT_SECONDS=" ${LOCK_TIMEOUT_SECONDS:- 600} "
3737LOCK_POLL_SECONDS=" ${LOCK_POLL_SECONDS:- 5} "
38+ LOCK_HEARTBEAT_SECONDS=" ${LOCK_HEARTBEAT_SECONDS:- 60} "
3839LOCK_OWNER=" ${LOCK_OWNER:- $(hostname)-$$ -$(date -u +% s)} "
3940current_step=" initializing"
4041private_key_file=" "
4142passphrase_file_secret=" "
4243lock_error_file=" "
44+ lock_heartbeat_pid=" "
4345
4446log_step () {
4547 current_step=" $1 "
@@ -54,6 +56,7 @@ on_error() {
5456}
5557
5658cleanup () {
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+
113181acquire_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