Method: Wait#until
- Defined in:
- lib/wait.rb
#until(&block) ⇒ Object
Description
Wait#until executes a block until there’s a valid (by default, truthy) result. Useful for blocking script execution until:
-
an HTTP request was successful
-
a port has opened
-
a process has started
-
etc.
Examples
wait = Wait.new
# => #<Wait>
wait.until { Time.now.sec.even? }
# [Counter] attempt 1/5
# [Tester] result: false
# [Rescuer] rescued: Wait::ResultInvalid
# [Raiser] not raising: Wait::ResultInvalid
# [Delayer] delaying for 1s
# [Counter] attempt 2/5
# [Tester] result: true
# => true
If you wish to handle an exception by attempting the block again, pass one or an array of exceptions with the :rescue
option.
wait = Wait.new(:rescue => RuntimeError)
# => #<Wait>
wait.until do |attempt|
case attempt
when 1 then nil
when 2 then raise RuntimeError
when 3 then "foo"
end
end
# [Counter] attempt 1/5
# [Tester] result: nil
# [Rescuer] rescued: Wait::ResultInvalid
# [Raiser] not raising: Wait::ResultInvalid
# [Delayer] delaying for 1s
# [Counter] attempt 2/5
# [Rescuer] rescued: RuntimeError
# [Raiser] not raising: RuntimeError
# [Delayer] delaying for 1s
# [Counter] attempt 3/5
# [Tester] result: "foo"
# => "foo"
Returns
The result of the block if valid (by default, truthy).
Raises
If no results are valid, the exception from the last attempt made.
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/wait.rb', line 124 def until(&block) # Reset the attempt counter. @counter.reset begin # Increment the attempt counter. @counter.increment # Wrap the given block in a timeout. result = Timeout.timeout(@timeout, TimeoutError) do # Execute the block and pass the attempt count (an +Integer+) to it. yield(@counter.attempt) end # Raise an exception unless the result is valid. @tester.valid?(result) ? result : raise(ResultInvalid) rescue TimeoutError, ResultInvalid, *@rescuer.exceptions => exception # Log the exception. @rescuer.log(exception) # Raise the exception if it ought to be. raise(exception) if @raiser.raise?(exception) # Raise the exception if this was the last attempt. raise(exception) if @counter.last_attempt? # Sleep before the next attempt. @delayer.sleep # Try the block again. retry end end |