feat(circuit-breaker): add auto-recovery from OPEN state (#160)
The OPEN state was terminal — once triggered, it persisted across restarts with no automatic recovery. This adds two recovery mechanisms: 1. Cooldown timer (default): OPEN → HALF_OPEN after CB_COOLDOWN_MINUTES (default 30). The existing HALF_OPEN logic handles recovery or re-trip. 2. Auto-reset option: CB_AUTO_RESET=true bypasses cooldown, resets to CLOSED on startup for fully unattended operation. Changes: - Add parse_iso_to_epoch() to lib/date_utils.sh (cross-platform) - Add cooldown + auto-reset logic to init_circuit_breaker() - Add opened_at field to state file when entering/staying OPEN - Add --auto-reset-circuit CLI flag and .ralphrc config vars - Add 19 tests in test_circuit_breaker_recovery.bats - Update CLAUDE.md and README.md documentation
This commit is contained in:
parent
abcfa8b695
commit
b4b9db6b76
7 changed files with 626 additions and 6 deletions
|
|
@ -46,8 +46,59 @@ get_epoch_seconds() {
|
|||
date +%s
|
||||
}
|
||||
|
||||
# Convert ISO 8601 timestamp to Unix epoch seconds
|
||||
# Input: ISO timestamp (e.g., "2025-01-15T10:30:00+00:00")
|
||||
# Returns: Unix epoch seconds on stdout
|
||||
# Falls back to current epoch on parse failure (safe default)
|
||||
parse_iso_to_epoch() {
|
||||
local iso_timestamp=$1
|
||||
|
||||
if [[ -z "$iso_timestamp" || "$iso_timestamp" == "null" ]]; then
|
||||
date +%s
|
||||
return
|
||||
fi
|
||||
|
||||
# Try GNU date -d (Linux, macOS with Homebrew coreutils)
|
||||
local result
|
||||
if result=$(date -d "$iso_timestamp" +%s 2>/dev/null) && [[ "$result" =~ ^[0-9]+$ ]]; then
|
||||
echo "$result"
|
||||
return
|
||||
fi
|
||||
|
||||
# Try BSD date -j (native macOS)
|
||||
# Strip timezone suffix for BSD compatibility
|
||||
local stripped="${iso_timestamp%%+*}"
|
||||
stripped="${stripped%%Z*}"
|
||||
if result=$(date -j -f "%Y-%m-%dT%H:%M:%S" "$stripped" +%s 2>/dev/null) && [[ "$result" =~ ^[0-9]+$ ]]; then
|
||||
echo "$result"
|
||||
return
|
||||
fi
|
||||
|
||||
# Fallback: manual epoch arithmetic from ISO components
|
||||
# Parse: YYYY-MM-DDTHH:MM:SS (ignore timezone, assume UTC)
|
||||
local year month day hour minute second
|
||||
if [[ "$iso_timestamp" =~ ^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2}) ]]; then
|
||||
year="${BASH_REMATCH[1]}"
|
||||
month="${BASH_REMATCH[2]}"
|
||||
day="${BASH_REMATCH[3]}"
|
||||
hour="${BASH_REMATCH[4]}"
|
||||
minute="${BASH_REMATCH[5]}"
|
||||
second="${BASH_REMATCH[6]}"
|
||||
|
||||
# Use date with explicit components if available
|
||||
if result=$(date -u -d "${year}-${month}-${day} ${hour}:${minute}:${second}" +%s 2>/dev/null) && [[ "$result" =~ ^[0-9]+$ ]]; then
|
||||
echo "$result"
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
# Ultimate fallback: return current epoch (safe default)
|
||||
date +%s
|
||||
}
|
||||
|
||||
# Export functions for use in other scripts
|
||||
export -f get_iso_timestamp
|
||||
export -f get_next_hour_time
|
||||
export -f get_basic_timestamp
|
||||
export -f get_epoch_seconds
|
||||
export -f parse_iso_to_epoch
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue