Module: Qless::Middleware::RetryExceptions

Included in:
RetryExceptions
Defined in:
lib/qless/middleware/retry_exceptions.rb

Overview

Auto-retries particular errors using qless-core’s internal retry tracking mechanism. Supports a backoff strategy (typically exponential).

Note: this does not support varying the number of allowed retries by exception type. If you want that kind of flexibility, use the RequeueExceptions middleware instead.

Constant Summary collapse

NO_BACKOFF_STRATEGY =
->(_num, _error) { 0 }
DEFAULT_ON_RETRY_CALLBACK =
lambda { |error, job| }

Instance Method Summary collapse

Instance Method Details

#around_perform(job) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
# File 'lib/qless/middleware/retry_exceptions.rb', line 12

def around_perform(job)
  super
rescue *retryable_exception_classes => error
  raise if job.retries_left <= 0

  attempt_num = (job.original_retries - job.retries_left) + 1
  failure = Qless.failure_formatter.format(job, error)
  job.retry(backoff_strategy.call(attempt_num, error), *failure)

  on_retry_callback.call(error, job)
end

#backoff_strategyObject



38
39
40
# File 'lib/qless/middleware/retry_exceptions.rb', line 38

def backoff_strategy
  @backoff_strategy ||= NO_BACKOFF_STRATEGY
end

#exponential(delay_seconds, options = {}) ⇒ Object

If ‘factor` is omitted it is set to `delay_seconds` to reproduce legacy behavior.



53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/qless/middleware/retry_exceptions.rb', line 53

def exponential(delay_seconds, options={})
  factor = options.fetch(:factor, delay_seconds)
  fuzz_factor = options.fetch(:fuzz_factor, 0)

  lambda do |retry_no, error|
    unfuzzed = delay_seconds * factor**(retry_no - 1)
    return unfuzzed if fuzz_factor.zero?
    r = 2 * rand  - 1
    # r is uniformly distributed in range [-1, 1]
    unfuzzed * (1 + fuzz_factor * r)
  end
end

#on_retry_callbackObject



47
48
49
# File 'lib/qless/middleware/retry_exceptions.rb', line 47

def on_retry_callback
  @on_retry_callback ||= DEFAULT_ON_RETRY_CALLBACK
end

#retry_on(*exception_classes) ⇒ Object



28
29
30
# File 'lib/qless/middleware/retry_exceptions.rb', line 28

def retry_on(*exception_classes)
  retryable_exception_classes.push(*exception_classes)
end

#retryable_exception_classesObject



24
25
26
# File 'lib/qless/middleware/retry_exceptions.rb', line 24

def retryable_exception_classes
  @retryable_exception_classes ||= []
end

#use_backoff_strategy(strategy = nil, &block) ⇒ Object



34
35
36
# File 'lib/qless/middleware/retry_exceptions.rb', line 34

def use_backoff_strategy(strategy = nil, &block)
  @backoff_strategy = strategy || block
end

#use_on_retry_callback(&block) ⇒ Object



43
44
45
# File 'lib/qless/middleware/retry_exceptions.rb', line 43

def use_on_retry_callback(&block)
  @on_retry_callback = block if block
end