Class: Tasker::Orchestration::ResponseProcessor
- Inherits:
-
Object
- Object
- Tasker::Orchestration::ResponseProcessor
- Includes:
- Concerns::EventPublisher
- Defined in:
- lib/tasker/orchestration/response_processor.rb
Overview
ResponseProcessor handles API response validation and error detection
This component provides focused responsibility for processing API responses, determining if they indicate errors that require backoff handling, and preparing context for error handling.
Constant Summary collapse
- BACKOFF_ERROR_CODES =
HTTP status codes that should trigger backoff behavior (temporary failures)
[429, 503].freeze
- PERMANENT_ERROR_CODES =
HTTP status codes that indicate permanent failures (don't retry)
[400, 401, 403, 404, 422].freeze
- SUCCESS_CODES =
HTTP status codes that indicate a successful request
(200..226)
Instance Method Summary collapse
-
#process_response(step, response) ⇒ Hash?
Process an API response and determine if it requires error handling.
Methods included from Concerns::EventPublisher
#infer_step_event_type_from_state, #publish_custom_event, #publish_no_viable_steps, #publish_step_backoff, #publish_step_before_handle, #publish_step_cancelled, #publish_step_completed, #publish_step_event_for_context, #publish_step_failed, #publish_step_retry_requested, #publish_step_started, #publish_steps_execution_completed, #publish_steps_execution_started, #publish_task_completed, #publish_task_enqueue, #publish_task_failed, #publish_task_finalization_completed, #publish_task_finalization_started, #publish_task_pending_transition, #publish_task_reenqueue_delayed, #publish_task_reenqueue_failed, #publish_task_reenqueue_requested, #publish_task_reenqueue_started, #publish_task_retry_requested, #publish_task_started, #publish_viable_steps_discovered, #publish_workflow_state_unclear, #publish_workflow_step_completed, #publish_workflow_task_started
Instance Method Details
#process_response(step, response) ⇒ Hash?
Process an API response and determine if it requires error handling
31 32 33 34 35 36 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 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/tasker/orchestration/response_processor.rb', line 31 def process_response(step, response) status = extract_status(response) # Successful responses don't need special handling return nil if SUCCESS_CODES.include?(status) # Categorize error type and raise appropriate Tasker error if BACKOFF_ERROR_CODES.include?(status) # Temporary failures that should be retried with backoff context = build_error_context(step, response, status) retry_after = extract_retry_after(response) Rails.logger.warn( 'ResponseProcessor: API response requires backoff handling - ' \ "Status: #{status}, Step: #{step.name} (#{step.workflow_step_id})" ) # Parse retry_after immediately to avoid timing issues with date formats parsed_retry_after = if retry_after&.match?(/^\d+$/) retry_after.to_i elsif retry_after # Parse HTTP date format with error handling begin retry_time = Time.zone.parse(retry_after) [(retry_time - Time.zone.now).to_i, 1].max rescue ArgumentError => e Rails.logger.warn("Invalid Retry-After date format: #{retry_after}, error: #{e.}") nil # Let exponential backoff handle it end end raise Tasker::RetryableError.new( "API call failed with retryable status #{status}", retry_after: parsed_retry_after, context: context ) elsif PERMANENT_ERROR_CODES.include?(status) # Permanent failures that should not be retried body = extract_body(response) context = build_error_context(step, response, status) Rails.logger.error( 'ResponseProcessor: API response indicates permanent error - ' \ "Status: #{status}, Step: #{step.name} (#{step.workflow_step_id})" ) raise Tasker::PermanentError.new( "API call failed with permanent status #{status}: #{body}", error_code: "HTTP_#{status}", context: context ) else # Other server errors (5xx) - treat as retryable but without forced backoff body = extract_body(response) context = build_error_context(step, response, status) Rails.logger.error( 'ResponseProcessor: API response indicates server error - ' \ "Status: #{status}, Step: #{step.name} (#{step.workflow_step_id})" ) # Create a special RetryableError that doesn't apply backoff error = Tasker::RetryableError.new( "API call failed with server error #{status}: #{body}", context: context ) # Mark this error as not requiring backoff error.define_singleton_method(:skip_backoff?) { true } raise error end end |