class Resque::Failure::MultipleWithRetrySuppression
A multiple failure backend, with retry suppression
For example: if you had a job that could retry 5 times, your failure backends are not notified unless the final retry attempt also fails.
Example:
require 'resque-retry' require 'resque/failure/redis' Resque::Failure::MultipleWithRetrySuppression.classes = [Resque::Failure::Redis] Resque::Failure.backend = Resque::Failure::MultipleWithRetrySuppression
Public Class Methods
failure_key(retry_key)
click to toggle source
Expose this for the hook’s use
@api public
# File lib/resque/failure/multiple_with_retry_suppression.rb, line 96 def self.failure_key(retry_key) 'failure-' + retry_key end
Public Instance Methods
save()
click to toggle source
Called when the job fails
If the job will retry, suppress the failure from the other backends. Store the lastest failure information in redis, used by the web interface.
@api private
Calls superclass method
# File lib/resque/failure/multiple_with_retry_suppression.rb, line 29 def save args = args_from(payload) log_message 'failure backend save', args, exception retryable = retryable? job_being_retried = retryable && retrying? if !job_being_retried log_message( "#{retryable ? '' : 'non-'}retryable job is not being retried - sending failure to superclass", args, exception ) cleanup_retry_failure_log! return super end # some plugins define retry_delay and have it take no arguments, so rather than break those, # we'll just check here to see whether it takes the additional exception class argument or not # we also allow all job args to be passed to a custom `retry_delay` method retry_delay_arity = klass.method(:retry_delay).arity calculated_retry_delay = if [-2, 2].include?(retry_delay_arity) klass.retry_delay(exception.class, *args) elsif [-1, 1].include?(retry_delay_arity) klass.retry_delay(exception.class) else klass.retry_delay end if calculated_retry_delay > 0 log_message( "retry_delay: #{calculated_retry_delay} > 0 - saving details in Redis", args, exception ) data = { :failed_at => Time.now.strftime("%Y/%m/%d %H:%M:%S"), :payload => payload, :exception => exception.class.to_s, :error => exception.to_s, :backtrace => Array(exception.backtrace), :worker => worker.to_s, :queue => queue } data = Resque.encode(data) Resque.redis.setex( failure_key, 2 * calculated_retry_delay, data ) else log_message( "retry_delay: #{calculated_retry_delay} <= 0 - ignoring", args, exception ) end end
Protected Instance Methods
args_from(payload)
click to toggle source
# File lib/resque/failure/multiple_with_retry_suppression.rb, line 119 def args_from(payload) (payload || {})['args'].dup end
cleanup_retry_failure_log!()
click to toggle source
# File lib/resque/failure/multiple_with_retry_suppression.rb, line 123 def cleanup_retry_failure_log! Resque.redis.del(failure_key) if retryable? end
failure_key()
click to toggle source
# File lib/resque/failure/multiple_with_retry_suppression.rb, line 127 def failure_key self.class.failure_key(retry_key) end
klass()
click to toggle source
# File lib/resque/failure/multiple_with_retry_suppression.rb, line 131 def klass Resque::Job.new(nil, nil).constantize(payload['class']) end
retry_key()
click to toggle source
# File lib/resque/failure/multiple_with_retry_suppression.rb, line 135 def retry_key klass.redis_retry_key(*payload['args']) end
retryable?()
click to toggle source
# File lib/resque/failure/multiple_with_retry_suppression.rb, line 139 def retryable? klass.respond_to?(:redis_retry_key) rescue NameError false end
retrying?()
click to toggle source
# File lib/resque/failure/multiple_with_retry_suppression.rb, line 145 def retrying? redis_key_exists?(retry_key) end
Private Instance Methods
redis_key_exists?(key)
click to toggle source
# File lib/resque/failure/multiple_with_retry_suppression.rb, line 151 def redis_key_exists?(key) ![false, 0].include?(Resque.redis.exists(key) || false) end