#!/usr/bin/env bash # Retry functions with exponential backoff # Usage: source "$SCRIPT_DIR/lib/common/retry.sh" # Source logging if not already sourced [ -z "$(type -t log_info)" ] && source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/logging.sh" # Retry a command with exponential backoff # Usage: retry_command [args...] retry_command() { local max_attempts="$1" local base_delay="$2" shift 2 local command=("$@") local attempt=1 local delay="$base_delay" while [ $attempt -le $max_attempts ]; do log_info "Attempt $attempt/$max_attempts: ${command[*]}" if "${command[@]}"; then return 0 fi if [ $attempt -lt $max_attempts ]; then log_warn "Command failed, retrying in ${delay}s..." sleep "$delay" delay=$((delay * 2)) # Exponential backoff fi ((attempt++)) || true done log_error "Command failed after $max_attempts attempts: ${command[*]}" return 1 } # Retry a function with exponential backoff # Usage: retry_function [args...] retry_function() { local max_attempts="$1" local base_delay="$2" local func_name="$3" shift 3 local args=("$@") local attempt=1 local delay="$base_delay" while [ $attempt -le $max_attempts ]; do log_info "Attempt $attempt/$max_attempts: $func_name" if "$func_name" "${args[@]}"; then return 0 fi if [ $attempt -lt $max_attempts ]; then log_warn "Function failed, retrying in ${delay}s..." sleep "$delay" delay=$((delay * 2)) # Exponential backoff fi ((attempt++)) || true done log_error "Function failed after $max_attempts attempts: $func_name" return 1 } # Wait for a condition to be true # Usage: wait_for_condition wait_for_condition() { local timeout="$1" local interval="$2" shift 2 local condition=("$@") local elapsed=0 while [ $elapsed -lt $timeout ]; do if "${condition[@]}"; then return 0 fi sleep "$interval" elapsed=$((elapsed + interval)) done log_error "Condition not met within ${timeout}s: ${condition[*]}" return 1 } # Wait for a service to be ready # Usage: wait_for_service wait_for_service() { local url="$1" local timeout="${2:-60}" local interval="${3:-5}" wait_for_condition "$timeout" "$interval" curl -sf "$url" >/dev/null } # Wait for a file to exist # Usage: wait_for_file wait_for_file() { local file_path="$1" local timeout="${2:-60}" local interval="${3:-5}" wait_for_condition "$timeout" "$interval" test -f "$file_path" }