Anticipate is a fluent interface for retrying blocks of code:
sleeping(0.1).seconds.between_tries.failing_after(20).tries do # Calls block every 0.1 seconds until it stops raising errors end
Including the Anticipate module into your class gives you:
failing_after(3).tries {} sleeping(0.1).seconds.between_tries {} sleeping(123).seconds.between_tries.failing_after(456).tries {}
Blocks should contain an assertion, i.e. raise a descriptive error if some condition is unsatisfied. On the last iteration, any error will be wrapped in an Anticipate::TimeoutError and re-raised.
The first try is attempted immediately, there is no sleep before the first yield.
If lots of your code needs to wait for things to happen, you might consider defining your own timing module, e.g:
module Timing include Anticipate def very_soon sleeping(0.1).seconds.between_tries.failing_after(10).tries do yield end end def eventually sleeping(2).seconds.between_tries.failing_after(5).tries do yield end end end
…that way you can adjust timing details in one place as the system grows.
I’m aware of a couple of gems performing the begin-rescue-sleep-retry dance, namely ‘retry’ and ‘attempt’. The aim of this library is to offer more expressive syntax.