Skip to content

Instantly share code, notes, and snippets.

@mrk21
Last active April 20, 2024 04:16
Show Gist options
  • Save mrk21/617df3dbb59219148bb6bdb41e48cd4d to your computer and use it in GitHub Desktop.
Save mrk21/617df3dbb59219148bb6bdb41e48cd4d to your computer and use it in GitHub Desktop.
Exponential Backoff And Jitter for Ruby
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
@mrk21
Copy link
Author

mrk21 commented Apr 19, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment