Last active
April 20, 2024 04:16
-
-
Save mrk21/617df3dbb59219148bb6bdb41e48cd4d to your computer and use it in GitHub Desktop.
Exponential Backoff And Jitter for Ruby
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Retryer | |
class RetryError < StandardError; end | |
class Backoff | |
def call(attempt) | |
raise NotImplementedError | |
end | |
end | |
class ExponentialBackoffAndEqualJitter < Backoff | |
def initialize(base:, cap:) | |
@base = base | |
@cap = cap | |
end | |
def call(attempt) | |
exp = [@cap, 2 ** attempt * @base].min | |
exp / 2.0 + random_between(0, exp / 2.0) | |
end | |
private | |
def random_between(min, max) | |
rand * (max - min) + min | |
end | |
end | |
def initialize( | |
*retryable_exceptions, | |
max_attempt: 10, | |
backoff: ExponentialBackoffAndEqualJitter.new(base: 0.1, cap: 10), | |
on_retry: ->(attempt, wait) {} | |
) | |
@retryable_exceptions = retryable_exceptions.empty? ? [RetryError] : retryable_exceptions | |
@max_attempt = max_attempt | |
@backoff = backoff | |
@on_retry = on_retry | |
end | |
def retryable(&block) | |
attempt = 0 | |
begin | |
return block.call | |
rescue *@retryable_exceptions | |
raise if attempt >= @max_attempt | |
attempt += 1 | |
wait = @backoff.call(attempt) | |
@on_retry.call(attempt, wait) | |
sleep wait | |
retry | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
See: AWS Solutions Architect ブログ: Exponential Backoff And Jitter