Class: BlockRepeater::Repeater
- Inherits:
-
Object
- Object
- BlockRepeater::Repeater
- Includes:
- RepeaterMethods
- Defined in:
- lib/block_repeater/repeater.rb
Overview
The class which governs when to stop repeating based on condition or timeout
Constant Summary collapse
- @@default_exceptions =
[]
Constants included from RepeaterMethods
RepeaterMethods::UNTIL_METHOD_REGEX
Class Method Summary collapse
-
.default_catch(exceptions: [], behaviour: :defer, &block) ⇒ Object
Same as #catch but defines default behaviours shared by all BlockRepeater instances except that there is no default exception type, it must be defined.
Instance Method Summary collapse
-
#backoff(timeout: 10, initial_wait: 0.1, multiplier: 2) ⇒ Object
Retry a call whilst exponentially increasing the wait time between each iteration until a timeout is reached.
-
#catch(exceptions: [StandardError], behaviour: :defer, &block) ⇒ Object
Determine how to respond to exceptions raised while repeating, must be called before #until.
-
#initialize(manual_repeat: true, **kwargs, &block) ⇒ Repeater
constructor
Prepare the Repeater to take the initial block to be repeated.
-
#repeat(times: 25, delay: 0.2, **_) ⇒ Object
Repeat a block until either the defined timeout is met or the condition block returns true.
-
#until(&block) ⇒ Object
Set the block which determines if the main block should stop being executed.
Methods included from RepeaterMethods
#call_if_method_responsive, #method_missing, #respond_to_missing?
Constructor Details
#initialize(manual_repeat: true, **kwargs, &block) ⇒ Repeater
Prepare the Repeater to take the initial block to be repeated
21 22 23 24 25 26 |
# File 'lib/block_repeater/repeater.rb', line 21 def initialize(manual_repeat: true, **kwargs, &block) @manual_repeat = manual_repeat @repeater_arguments = kwargs @repeat_block = block @anticipated_exceptions = [] end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class RepeaterMethods
Class Method Details
.default_catch(exceptions: [], behaviour: :defer, &block) ⇒ Object
Same as #catch but defines default behaviours shared by all BlockRepeater instances except that there is no default exception type, it must be defined
125 126 127 |
# File 'lib/block_repeater/repeater.rb', line 125 def self.default_catch(exceptions: [], behaviour: :defer, &block) @@default_exceptions << ExceptionResponse.new(types: exceptions, behaviour: behaviour, &block) end |
Instance Method Details
#backoff(timeout: 10, initial_wait: 0.1, multiplier: 2) ⇒ Object
Retry a call whilst exponentially increasing the wait time between each iteration until a timeout is reached
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/block_repeater/repeater.rb', line 79 def backoff(timeout: 10, initial_wait: 0.1, multiplier: 2) raise StandardError, 'Multiplier cannot be less than 1.1' if multiplier < 1.1 condition_met = nil result = nil current_sleep_seconds = initial_wait start_time = Time.now until current_sleep_seconds >= timeout result = @repeat_block.call condition_met = @condition_block.call(result) if @condition_block duration = Time.now - start_time break if condition_met || duration > timeout # calculating exponential increase current_sleep_seconds *= multiplier # how long the total duration will be after the next sleep projected_duration = current_sleep_seconds + duration # if projected duration exceeds the timeout, reduce time for next sleep to allow one final call current_sleep_seconds = (timeout - duration) if projected_duration > timeout sleep(current_sleep_seconds) end result end |
#catch(exceptions: [StandardError], behaviour: :defer, &block) ⇒ Object
Determine how to respond to exceptions raised while repeating, must be called before #until
117 118 119 120 |
# File 'lib/block_repeater/repeater.rb', line 117 def catch(exceptions: [StandardError], behaviour: :defer, &block) @anticipated_exceptions << ExceptionResponse.new(types: exceptions, behaviour: behaviour, &block) self end |
#repeat(times: 25, delay: 0.2, **_) ⇒ Object
Repeat a block until either the defined timeout is met or the condition block returns true
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/block_repeater/repeater.rb', line 35 def repeat(times: 25, delay: 0.2, **_) result, @condition_met, deferred_exception = nil anticipated_exception_types = @anticipated_exceptions.map(&:types).flatten default_exception_types = @@default_exceptions.map(&:types).flatten exception_types = anticipated_exception_types + default_exception_types times.times do begin result = @repeat_block.call @condition_met = @condition_block.call(result) if @condition_block deferred_exception = nil rescue *exception_types => e exceptions = if anticipated_exception_types.any? do |ex| e.class <= ex end @anticipated_exceptions else @@default_exceptions end matched_response = exceptions.detect { |expected| expected.types.any? { |ex| e.class <= ex } } if matched_response.behaviour == :defer deferred_exception = matched_response deferred_exception.actual = e else matched_response.execute(e) end break if matched_response.behaviour == :stop end break if @condition_met sleep delay end deferred_exception&.execute result end |
#until(&block) ⇒ Object
Set the block which determines if the main block should stop being executed
135 136 137 138 139 140 141 142 |
# File 'lib/block_repeater/repeater.rb', line 135 def until(&block) @condition_block = block if @manual_repeat self else repeat(**@repeater_arguments) end end |