Class: Shoryuken::Middleware::Server::ExponentialBackoffRetry

Inherits:
Object
  • Object
show all
Includes:
Util
Defined in:
lib/shoryuken/middleware/server/exponential_backoff_retry.rb

Overview

Middleware that implements exponential backoff retry for failed messages. When a job fails, the message visibility timeout is adjusted based on configured retry intervals.

Instance Method Summary collapse

Methods included from Util

#elapsed, #fire_event, #logger, #unparse_queues, #worker_name

Instance Method Details

#call(worker, _queue, sqs_msg, _body) { ... } ⇒ void

This method returns an undefined value.

Processes a message with exponential backoff retry on failure

Parameters:

  • worker (Object)

    the worker instance

  • _queue (String)

    the queue name (unused)

  • sqs_msg (Shoryuken::Message, Array<Shoryuken::Message>)

    the message or batch

  • _body (Object)

    the parsed message body (unused)

Yields:

  • continues to the next middleware in the chain

Raises:

  • (StandardError)

    re-raises the original exception if retry intervals are not configured, if retry limit is exceeded, or if the exception is classified as non-retryable



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/shoryuken/middleware/server/exponential_backoff_retry.rb', line 22

def call(worker, _queue, sqs_msg, _body)
  return yield unless worker.class.exponential_backoff?

  if sqs_msg.is_a?(Array)
    logger.warn { "Exponential backoff isn't supported for batch workers" }
    return yield
  end

  started_at = Time.now
  yield
rescue => e
  worker_options = worker.class.get_shoryuken_options
  retry_intervals = worker_options['retry_intervals']

  # Non-retryable exceptions must not be backoff retried; re-raise so the
  # NonRetryableException middleware can delete the message immediately.
  raise if NonRetryableException.non_retryable?(e, worker_options['non_retryable_exceptions'])

  if retry_intervals.nil? || !handle_failure(sqs_msg, started_at, retry_intervals)
    # Re-raise the exception if the job is not going to be exponential backoff retried.
    # This allows custom middleware (like exception notifiers) to be aware of the unhandled failure.
    raise
  end

  logger.warn { "Message #{sqs_msg.message_id} will attempt retry due to error: #{e.message}" }
  # since we didn't raise, lets log the backtrace for debugging purposes.
  logger.debug { e.backtrace.join("\n") } unless e.backtrace.nil?
end