Class: Fractor::Workflow::RetryOrchestrator
- Inherits:
-
Object
- Object
- Fractor::Workflow::RetryOrchestrator
- Defined in:
- lib/fractor/workflow/retry_orchestrator.rb
Overview
Orchestrates retry logic for workflow job execution. Handles retry strategies, backoff calculations, and attempt tracking.
Instance Attribute Summary collapse
-
#attempts ⇒ Object
readonly
Returns the value of attribute attempts.
-
#debug ⇒ Object
readonly
Returns the value of attribute debug.
-
#retry_config ⇒ Object
readonly
Returns the value of attribute retry_config.
Instance Method Summary collapse
-
#calculate_delay(attempt) ⇒ Numeric
Calculate the delay before the next retry attempt.
-
#execute_with_retry(job) {|Job| ... } ⇒ Object
Execute a job with retry logic.
-
#exhausted?(max_attempts) ⇒ Boolean
Check if all retry attempts are exhausted.
-
#initialize(retry_config, debug: false) ⇒ RetryOrchestrator
constructor
Initialize a new retry orchestrator.
-
#last_error ⇒ Exception?
Get the last error that occurred during retry.
-
#reset! ⇒ Object
Reset the attempt counter and state.
-
#should_retry?(_attempt, error) ⇒ Boolean
Check if a retry should be attempted.
-
#state ⇒ Hash
Get the current retry state information.
Constructor Details
#initialize(retry_config, debug: false) ⇒ RetryOrchestrator
Initialize a new retry orchestrator.
21 22 23 24 25 26 27 28 |
# File 'lib/fractor/workflow/retry_orchestrator.rb', line 21 def initialize(retry_config, debug: false) @retry_config = retry_config @debug = debug @attempts = 0 @last_error = nil @all_errors = [] @started_at = nil end |
Instance Attribute Details
#attempts ⇒ Object (readonly)
Returns the value of attribute attempts.
15 16 17 |
# File 'lib/fractor/workflow/retry_orchestrator.rb', line 15 def attempts @attempts end |
#debug ⇒ Object (readonly)
Returns the value of attribute debug.
15 16 17 |
# File 'lib/fractor/workflow/retry_orchestrator.rb', line 15 def debug @debug end |
#retry_config ⇒ Object (readonly)
Returns the value of attribute retry_config.
15 16 17 |
# File 'lib/fractor/workflow/retry_orchestrator.rb', line 15 def retry_config @retry_config end |
Instance Method Details
#calculate_delay(attempt) ⇒ Numeric
Calculate the delay before the next retry attempt.
100 101 102 |
# File 'lib/fractor/workflow/retry_orchestrator.rb', line 100 def calculate_delay(attempt) @retry_config.delay_for(attempt) end |
#execute_with_retry(job) {|Job| ... } ⇒ Object
Execute a job with retry logic. Retries the job execution according to the retry strategy configuration.
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/fractor/workflow/retry_orchestrator.rb', line 37 def execute_with_retry(job) reset! @started_at = Time.now loop do @attempts += 1 log_debug "Executing job '#{job.name}', attempt #{@attempts}" result = yield job # If we got here without error, execution succeeded log_retry_success(job) if @attempts > 1 return result rescue StandardError => e @last_error = e # Track all errors for DLQ entry @all_errors << { attempt: @attempts, error: e, timestamp: Time.now, } # Check if error is retryable unless @retry_config.retryable?(e) log_debug "Error #{e.class} is not retryable, failing immediately" raise e end # Record the failure and check if we've exhausted retries if exhausted?(@retry_config.max_attempts) log_retry_exhausted(job) raise e end # Calculate delay for this attempt delay = calculate_delay(@attempts) # Log retry attempt log_retry_attempt(job, delay) # Wait before retrying sleep(delay) if delay.positive? end end |
#exhausted?(max_attempts) ⇒ Boolean
Check if all retry attempts are exhausted.
115 116 117 |
# File 'lib/fractor/workflow/retry_orchestrator.rb', line 115 def exhausted?(max_attempts) @attempts >= max_attempts end |
#last_error ⇒ Exception?
Get the last error that occurred during retry.
107 108 109 |
# File 'lib/fractor/workflow/retry_orchestrator.rb', line 107 def last_error @last_error end |
#reset! ⇒ Object
Reset the attempt counter and state.
120 121 122 123 124 125 |
# File 'lib/fractor/workflow/retry_orchestrator.rb', line 120 def reset! @attempts = 0 @last_error = nil @all_errors = [] @started_at = nil end |
#should_retry?(_attempt, error) ⇒ Boolean
Check if a retry should be attempted.
90 91 92 93 94 |
# File 'lib/fractor/workflow/retry_orchestrator.rb', line 90 def should_retry?(_attempt, error) return false if exhausted?(@retry_config.max_attempts) @retry_config.retryable?(error) end |
#state ⇒ Hash
Get the current retry state information.
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/fractor/workflow/retry_orchestrator.rb', line 130 def state { attempts: @attempts, max_attempts: @retry_config.max_attempts, last_error: @last_error&.class&.name, exhausted: exhausted?(@retry_config.max_attempts), all_errors: @all_errors.map do |err| { attempt: err[:attempt], error_class: err[:error].class.name, error_message: err[:error]., timestamp: err[:timestamp], } end, total_time: @started_at ? Time.now - @started_at : 0, } end |