Module: Qless::Middleware::RequeueExceptions

Defined in:
lib/qless/middleware/requeue_exceptions.rb

Overview

This middleware is like RetryExceptions, but it doesn’t use qless-core’s internal retry/retry-tracking mechanism. Instead, it re-queues the job when it fails with a matched error, and increments a counter in the job’s data.

This is useful for exceptions for which you want a different backoff/retry strategy. The internal retry mechanism doesn’t allow for separate tracking by exception type, and thus doesn’t allow you to retry different exceptions a different number of times.

This is particularly useful for handling resource throttling errors, where you may not want exponential backoff, and you may want the error to be retried many times, w/o having other transient errors retried so many times.

Defined Under Namespace

Classes: RequeueableException

Constant Summary collapse

DEFAULT_ON_REQUEUE_CALLBACK =
lambda { |error, job| }

Instance Method Summary collapse

Instance Method Details

#around_perform(job) ⇒ Object



71
72
73
74
75
# File 'lib/qless/middleware/requeue_exceptions.rb', line 71

def around_perform(job)
  super
rescue *requeueable_exceptions.keys => e
  handle_exception(job, e)
end

#handle_exception(job, error) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/qless/middleware/requeue_exceptions.rb', line 56

def handle_exception(job, error)
  config = requeuable_exception_for(error)

  requeues_by_exception = (job.data['requeues_by_exception'] ||= {})
  requeues_by_exception[config.klass.name] ||= 0

  config.raise_if_exhausted_requeues(
    error, requeues_by_exception[config.klass.name])

  requeues_by_exception[config.klass.name] += 1
  job.requeue(job.queue_name, delay: config.delay, data: job.data)

  on_requeue_callback.call(error, job)
end

#on_requeue_callbackObject



52
53
54
# File 'lib/qless/middleware/requeue_exceptions.rb', line 52

def on_requeue_callback
  @on_requeue_callback ||= DEFAULT_ON_REQUEUE_CALLBACK
end

#requeuable_exception_for(e) ⇒ Object



85
86
87
88
89
90
91
# File 'lib/qless/middleware/requeue_exceptions.rb', line 85

def requeuable_exception_for(e)
  requeueable_exceptions.fetch(e.class) do
    requeueable_exceptions.each do |klass, exc|
      break exc if klass === e
    end
  end
end

#requeue_on(*exceptions, options) ⇒ Object



40
41
42
43
44
45
# File 'lib/qless/middleware/requeue_exceptions.rb', line 40

def requeue_on(*exceptions, options)
  RequeueableException.from_splat_and_options(
    *exceptions, options).each do |exc|
    requeueable_exceptions[exc.klass] = exc
  end
end

#requeueable?(exception) ⇒ Boolean

Returns:

  • (Boolean)


77
78
79
# File 'lib/qless/middleware/requeue_exceptions.rb', line 77

def requeueable?(exception)
  requeueable_exceptions.member?(exception)
end

#requeueable_exceptionsObject



81
82
83
# File 'lib/qless/middleware/requeue_exceptions.rb', line 81

def requeueable_exceptions
  @requeueable_exceptions ||= {}
end

#use_on_requeue_callback(&block) ⇒ Object



48
49
50
# File 'lib/qless/middleware/requeue_exceptions.rb', line 48

def use_on_requeue_callback(&block)
  @on_requeue_callback = block if block
end