Module: DurableHuggingfaceHub::Utils::Retry
- Defined in:
- lib/durable_huggingface_hub/utils/retry.rb
Overview
Retry logic with exponential backoff for HTTP requests.
This module provides retry functionality for handling transient failures in HTTP requests, with configurable retry attempts and exponential backoff.
Constant Summary collapse
- DEFAULT_MAX_RETRIES =
Default maximum number of retry attempts
3- DEFAULT_INITIAL_DELAY =
Default initial delay in seconds
1- MAX_DELAY =
Maximum delay between retries (in seconds)
60- BACKOFF_MULTIPLIER =
Multiplier for exponential backoff
2- RETRYABLE_STATUS_CODES =
HTTP status codes that should trigger a retry
[ 408, # Request Timeout 429, # Too Many Requests 500, # Internal Server Error 502, # Bad Gateway 503, # Service Unavailable 504 # Gateway Timeout ].freeze
- RETRYABLE_ERRORS =
Errors that should trigger a retry
[ Faraday::TimeoutError, Faraday::ConnectionFailed, Faraday::SSLError ].freeze
Class Method Summary collapse
-
.calculate_delay(attempt, initial_delay) ⇒ Float
Calculates the delay for a retry attempt using exponential backoff.
-
.retryable_error?(error) ⇒ Boolean
Checks if an error should trigger a retry.
-
.with_retry(max_retries: DEFAULT_MAX_RETRIES, initial_delay: DEFAULT_INITIAL_DELAY, logger: nil) { ... } ⇒ Object
Executes a block with retry logic.
Class Method Details
.calculate_delay(attempt, initial_delay) ⇒ Float
Calculates the delay for a retry attempt using exponential backoff.
132 133 134 135 136 137 138 |
# File 'lib/durable_huggingface_hub/utils/retry.rb', line 132 def self.calculate_delay(attempt, initial_delay) # Exponential backoff: initial_delay * (2 ^ (attempt - 1)) delay = initial_delay * (BACKOFF_MULTIPLIER**(attempt - 1)) # Cap at maximum delay [delay, MAX_DELAY].min end |
.retryable_error?(error) ⇒ Boolean
Checks if an error should trigger a retry.
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/durable_huggingface_hub/utils/retry.rb', line 103 def self.retryable_error?(error) # Check if it's a known retryable error class return true if RETRYABLE_ERRORS.any? { |klass| error.is_a?(klass) } # Check if it's an HTTP error with retryable status if error.is_a?(HfHubHTTPError) && error.status_code return RETRYABLE_STATUS_CODES.include?(error.status_code) end # Check Faraday response errors if error.respond_to?(:response) && error.response status = error.response[:status] return RETRYABLE_STATUS_CODES.include?(status) if status end false end |
.with_retry(max_retries: DEFAULT_MAX_RETRIES, initial_delay: DEFAULT_INITIAL_DELAY, logger: nil) { ... } ⇒ Object
Executes a block with retry logic.
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/durable_huggingface_hub/utils/retry.rb', line 61 def self.with_retry(max_retries: DEFAULT_MAX_RETRIES, initial_delay: DEFAULT_INITIAL_DELAY, logger: nil) # Validate parameters validate_max_retries(max_retries) validate_initial_delay(initial_delay) attempt = 0 last_error = nil loop do begin return yield rescue => e attempt += 1 last_error = e # Check if error is retryable unless retryable_error?(e) raise e end # Check if we've exhausted retries if attempt > max_retries logger&.error("Max retries (#{max_retries}) exhausted for #{e.class}: #{e.}") raise e end # Calculate delay with exponential backoff delay = calculate_delay(attempt, initial_delay) # Log retry attempt logger&.warn("Retry attempt #{attempt}/#{max_retries} after #{delay}s due to #{e.class}: #{e.}") # Wait before retrying sleep(delay) end end end |