Module: Retriable

Defined in:
lib/retriable.rb,
lib/retriable/config.rb,
lib/retriable/version.rb,
lib/retriable/validation.rb,
lib/retriable/exponential_backoff.rb

Defined Under Namespace

Modules: Validation Classes: Config, ExponentialBackoff

Constant Summary collapse

OVERRIDE_THREAD_KEY =

Thread-local storage key for the active #with_override block. We deliberately use Thread#thread_variable_set/get (true thread-local) rather than Thread.current[] (fiber-local) so that fibers within a thread share the same override. Changing this to Thread.current[] would silently break callers that use fiber-based concurrency.

:retriable_override
VERSION =
"3.7.0"

Class Method Summary collapse

Class Method Details

.configObject



25
26
27
# File 'lib/retriable.rb', line 25

def config
  @config ||= Config.new
end

.configure {|config| ... } ⇒ Object

Yields:



21
22
23
# File 'lib/retriable.rb', line 21

def configure
  yield(config)
end

.retriable(opts = {}, &block) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/retriable.rb', line 57

def retriable(opts = {}, &block)
  override_config = current_override
  local_config = if opts.empty? && !override_config
                   config
                 else
                   Config.new(apply_override_options(config.to_h.merge(opts), override_config))
                 end

  # Config is mutable through `configure`, so validate again immediately before use.
  local_config.validate!

  plan = retry_plan(local_config)
  timeout = local_config.timeout
  on = local_config.on
  retry_if = local_config.retry_if
  on_retry = local_config.on_retry
  sleep_disabled = local_config.sleep_disabled
  max_elapsed_time = local_config.max_elapsed_time

  exception_list = on.is_a?(Hash) ? on.keys : on
  exception_list = [*exception_list]
  start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  elapsed_time = -> { Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time }

  execute_tries(
    max_tries: plan.max_tries, interval_for: plan.interval_for, timeout: timeout,
    exception_list: exception_list, on: on, retry_if: retry_if, on_retry: on_retry,
    elapsed_time: elapsed_time, max_elapsed_time: max_elapsed_time,
    sleep_disabled: sleep_disabled, &block
  )
end

.with_context(context_key, options = {}, &block) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/retriable.rb', line 44

def with_context(context_key, options = {}, &block)
  contexts = available_contexts

  if !contexts.key?(context_key)
    raise ArgumentError,
          "#{context_key} not found in Retriable contexts (including overrides). Available contexts: #{contexts.keys}"
  end

  return unless block_given?

  retriable(context_options_for(context_key, options), &block)
end

.with_override(opts = {}) ⇒ Object

Raises:

  • (ArgumentError)


29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/retriable.rb', line 29

def with_override(opts = {})
  raise ArgumentError, "empty override options are not allowed" if opts.empty?
  raise ArgumentError, "with_override requires a block" unless block_given?

  validate_override_options(opts)

  previous = Thread.current.thread_variable_get(OVERRIDE_THREAD_KEY)
  Thread.current.thread_variable_set(OVERRIDE_THREAD_KEY, opts)
  begin
    yield
  ensure
    Thread.current.thread_variable_set(OVERRIDE_THREAD_KEY, previous)
  end
end