summaryrefslogtreecommitdiff
path: root/src/lib/job-pool.source.sh
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/job-pool.source.sh')
-rw-r--r--src/lib/job-pool.source.sh137
1 files changed, 137 insertions, 0 deletions
diff --git a/src/lib/job-pool.source.sh b/src/lib/job-pool.source.sh
new file mode 100644
index 0000000..5c629aa
--- /dev/null
+++ b/src/lib/job-pool.source.sh
@@ -0,0 +1,137 @@
+wait_for_parallel_job_pid() {
+ local -r pid="$1"; shift
+ local -i status=0
+
+ set +e
+ wait "$pid"
+ status=$?
+ set -e
+
+ return "$status"
+}
+
+parallel_job_pid_is_running() {
+ local -r pid="$1"; shift
+ local running_pid
+
+ for running_pid in "$@"; do
+ if [ "$running_pid" = "$pid" ]; then
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+reap_finished_parallel_jobs() {
+ local -r job_pids_name="$1"; shift
+ # shellcheck disable=SC2178
+ local -n job_pids_ref="$job_pids_name"
+ local -n failed_ref="$1"; shift
+ local -i reaped_status="$1"; shift
+ local -i has_reaped_status=1
+ local -i status=0
+ local -a remaining_pids=()
+ local -a running_pids=()
+ local pid
+
+ mapfile -t running_pids < <(jobs -rp)
+
+ for pid in "${job_pids_ref[@]}"; do
+ if parallel_job_pid_is_running "$pid" "${running_pids[@]}"; then
+ remaining_pids+=("$pid")
+ continue
+ fi
+
+ if wait_for_parallel_job_pid "$pid"; then
+ status=0
+ else
+ status=$?
+ fi
+ if (( status == 127 && has_reaped_status != 0 )); then
+ status=$reaped_status
+ has_reaped_status=0
+ fi
+
+ if (( status != 0 )); then
+ failed_ref=1
+ fi
+ done
+
+ job_pids_ref=("${remaining_pids[@]}")
+}
+
+wait_for_next_parallel_job() {
+ local -r job_pids_name="$1"; shift
+ local -r failed_name="$1"; shift
+ # shellcheck disable=SC2178
+ local -n job_pids_ref="$job_pids_name"
+ local -i status=0
+
+ set +e
+ wait -n "${job_pids_ref[@]}"
+ status=$?
+ set -e
+
+ reap_finished_parallel_jobs "$job_pids_name" "$failed_name" "$status"
+}
+
+wait_for_parallel_job_slot() {
+ local -r job_pids_name="$1"; shift
+ local -r failed_name="$1"; shift
+ local -r max_jobs="$1"; shift
+ # shellcheck disable=SC2178
+ local -n job_pids_ref="$job_pids_name"
+
+ while (( ${#job_pids_ref[@]} >= max_jobs )); do
+ wait_for_next_parallel_job "$job_pids_name" "$failed_name"
+ done
+}
+
+wait_for_parallel_jobs() {
+ # shellcheck disable=SC2178
+ local -n job_pids_ref="$1"; shift
+ local -n failed_ref="$1"; shift
+
+ : "$failed_ref"
+ while (( ${#job_pids_ref[@]} > 0 )); do
+ if ! wait_for_parallel_job_pid "${job_pids_ref[0]}"; then
+ failed_ref=1
+ fi
+ job_pids_ref=("${job_pids_ref[@]:1}")
+ done
+}
+
+wait_for_image_job_slot() {
+ local -r image_job_pids_name="$1"; shift
+ local -r failed_name="$1"; shift
+
+ wait_for_parallel_job_slot \
+ "$image_job_pids_name" \
+ "$failed_name" \
+ "$IMAGE_JOBS"
+}
+
+wait_for_image_jobs() {
+ local -r image_job_pids_name="$1"; shift
+ local -r failed_name="$1"; shift
+
+ wait_for_parallel_jobs "$image_job_pids_name" "$failed_name"
+}
+
+wait_for_template_render_job_slot() {
+ local -r render_job_pids_name="$1"; shift
+ local -r failed_name="$1"; shift
+
+ wait_for_parallel_job_slot \
+ "$render_job_pids_name" \
+ "$failed_name" \
+ "$IMAGE_JOBS"
+}
+
+wait_for_template_render_jobs() {
+ local -r render_job_pids_name="$1"; shift
+ local -r failed_name="$1"; shift
+
+ wait_for_parallel_jobs "$render_job_pids_name" "$failed_name"
+}