Customizing retry delays with Amazon SQS from Shoryuken (ruby)

2.2k Views Asked by At

I am migrating a background job processing service made with sidekiq to shoryuken, which is based on Amazon SQS. With sidekiq you can customize the retries pattern by using sidekiq_retry_in:

class WorkerWithCustomRetry
    include Sidekiq::Worker
    sidekiq_options :retry => 5

    sidekiq_retry_in do |count|
        retry_count(count)
    end

    def self.retry_count(count)
    ...
    end
end

where, in my case, retry_countreturns the delay for the next retry based on external configuration. With shoryuken retries are yielded to SQS which handle retries automatically as long as the message is not deleted by the consumer application. However with shoryuken you can change the delay by using retry_intervals but documentation only explains how to set fixed values:

class MyWorker
    include Shoryuken::Worker

    shoryuken_options queue: 'default', retry_intervals: [360, 1200, 3600] # 5.minutes, 20.minutes and 1.hour

end

I need to customize the delay for retries the same way as with sidekiq, using a retry_count method which returns different values depending on external data. Is this possible or does exist a workaround to do that with shoryuken?

1

There are 1 best solutions below

0
Pablo Cantero On BEST ANSWER

Currently Shoryuken only supports fixed values for exponential backoff, but you can submit a PR changing ExponentialBackoffRetry with:

# https://github.com/phstc/shoryuken/blob/290b1cb4c4c40f34881d7f7b7a3beda949099cf5/lib/shoryuken/middleware/server/exponential_backoff_retry.rb#L11

retry_intervals = worker.class.get_shoryuken_options['retry_intervals']

retry_intervals = if retry_intervals.respond_to? :call
                    retry_intervals.call(worker, queue, sqs_msg, body)
                  else
                    Array(retry_intervals)
                  end

So you will be able to use a proc or fixed values to set retry_intervals, i.e.:

class MyWorker
  include Shoryuken::Worker

  shoryuken_options queue: 'default', 
    retry_intervals: -> (worker, queue, sqs_msg, body) { worker.your_method(...) }
end

OR you can remove the default ExponentialBackoffRetry and add yours:

Shoryuken.configure_server do |config|
  config.server_middleware do |chain|
    chain.remove Middleware::Server::ExponentialBackoffRetry
    chain.add YourExponentialBackoffRetry
  end
end

But keep in mind that SQS does not officially support exponential backoff, it's something implemented in Shoryuken using the Visibility Timeout, which can extended to a maximum of 12 hours.

https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ChangeMessageVisibility.html

You can continue to call ChangeMessageVisibility to extend the visibility timeout to a maximum of 12 hours. If you try to extend beyond 12 hours, the request will be rejected.