Class: AttemptThis::AttemptObject
- Inherits:
-
Object
- Object
- AttemptThis::AttemptObject
- Defined in:
- lib/attempt_this/attempt_object.rb
Overview
Retry policy implementation. This class is internal and is not supposed to be used outside of the module.
Constant Summary collapse
- @@scenarios =
All registered scenarios
{}
Class Method Summary collapse
- .get_object(id_or_enumerator) ⇒ Object
-
.reset ⇒ Object
Resets all static data.
Instance Method Summary collapse
-
#and_default_to(default_method, &block) ⇒ Object
Specifies default method that should be called after all attempts have failed.
-
#attempt(block) ⇒ Object
Executes the code block.
-
#initialize(enumerator) ⇒ AttemptObject
constructor
Initializes object with enumerator.
-
#scenario(id) ⇒ Object
Creates a scenario with the given id.
-
#with_binary_backoff(initial_delay, &block) ⇒ Object
Specifies delay which doubles between failed attempts.
-
#with_delay(delay, &block) ⇒ Object
Specifies delay in seconds between failed attempts.
-
#with_filter(*exceptions, &block) ⇒ Object
Specifies exceptions.
-
#with_reset(reset_method, &block) ⇒ Object
Specifies reset method that will be called after each failed attempt.
Constructor Details
#initialize(enumerator) ⇒ AttemptObject
Initializes object with enumerator.
22 23 24 |
# File 'lib/attempt_this/attempt_object.rb', line 22 def initialize(enumerator) @enumerator = enumerator end |
Class Method Details
.get_object(id_or_enumerator) ⇒ Object
15 16 17 18 19 |
# File 'lib/attempt_this/attempt_object.rb', line 15 def self.get_object(id_or_enumerator) impl = @@scenarios[id_or_enumerator] impl ||= AttemptObject.new(id_or_enumerator) impl end |
.reset ⇒ Object
Resets all static data.
11 12 13 |
# File 'lib/attempt_this/attempt_object.rb', line 11 def self.reset @@scenarios = {} end |
Instance Method Details
#and_default_to(default_method, &block) ⇒ Object
Specifies default method that should be called after all attempts have failed.
75 76 77 78 79 80 81 |
# File 'lib/attempt_this/attempt_object.rb', line 75 def and_default_to(default_method, &block) raise(ArgumentError, 'Default method is nil!') unless default_method raise(ArgumentError, 'Default method has already been specified!') if @default_method @default_method = default_method attempt(block) end |
#attempt(block) ⇒ Object
Executes the code block.
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/attempt_this/attempt_object.rb', line 27 def attempt(block) # Returning self will allow chaining calls return self unless block return block.call unless AttemptThis.enabled? apply_defaults # Retriable attempts require special error handling result = each_retriable_attempt do return attempt_with_reset(&block) end # Final attempt if (result != :empty) @delay_policy.call unless result == :skipped final_attempt(&block) end end |
#scenario(id) ⇒ Object
Creates a scenario with the given id.
108 109 110 111 112 113 |
# File 'lib/attempt_this/attempt_object.rb', line 108 def scenario(id) raise(ArgumentError, 'Nil id!') if id.nil? raise(ArgumentError, "There is already a scenario with id #{id}") if @@scenarios.has_key?(id) @@scenarios[id] = self end |
#with_binary_backoff(initial_delay, &block) ⇒ Object
Specifies delay which doubles between failed attempts.
84 85 86 87 88 89 90 91 |
# File 'lib/attempt_this/attempt_object.rb', line 84 def with_binary_backoff(initial_delay, &block) raise(ArgumentError, "Delay should be a number; got ${initial_delay}!") unless initial_delay.is_a?(Numeric) raise(ArgumentError, "Delay should be a positive number; got #{initial_delay}!") unless initial_delay > 0 raise(ArgumentError, "Delay policy has already been specified!") if @delay_policy @delay_policy = BinaryBackoffPolicy.new(initial_delay) attempt(block) end |
#with_delay(delay, &block) ⇒ Object
Specifies delay in seconds between failed attempts.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/attempt_this/attempt_object.rb', line 47 def with_delay(delay, &block) # Delay should be either an integer or a range of integers. if (delay.is_a?(Numeric)) raise(ArgumentError, "Delay should be a non-negative number; got #{delay}!") unless delay >= 0 delay = delay..delay elsif delay.is_a?(Range) raise(ArgumentError, "Range members should be numbers; got #{delay}!") unless delay.first.is_a?(Numeric) && delay.last.is_a?(Numeric) raise(ArgumentError, "Range members should be non-negative; got #{delay}!") unless delay.first >= 0 && delay.last >= 0 raise(ArgumentError, "Range's end should be greater than or equal to range's start; got #{delay}!") unless delay.first <= delay.last else raise(ArgumentError, "Delay should be either an number or a range of numbers; got #{delay}!") end raise(ArgumentError, 'Delay policy has already been specified!') if @delay_policy @delay_policy = lambda{Kernel.sleep(delay.first + rand(delay.count))} attempt(block) end |
#with_filter(*exceptions, &block) ⇒ Object
Specifies exceptions
94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/attempt_this/attempt_object.rb', line 94 def with_filter(*exceptions, &block) raise(ArgumentError, "Empty exceptions list!") unless exceptions.size > 0 # Everything must be an exception. exceptions.each do |e| raise(ArgumentError, "Not an exception: #{e}!") unless e <= Exception end raise(ArgumentError, "Exception filter has already been specified!") if @exception_filter @exception_filter = ExceptionTypeFilter.new(exceptions) attempt(block) end |
#with_reset(reset_method, &block) ⇒ Object
Specifies reset method that will be called after each failed attempt.
66 67 68 69 70 71 72 |
# File 'lib/attempt_this/attempt_object.rb', line 66 def with_reset(reset_method, &block) raise(ArgumentError, 'Reset method is nil!') unless reset_method raise(ArgumentError, 'Reset method has already been speicifed!') if @reset_method @reset_method = reset_method attempt(block) end |