A declarative busy wait.
Use this library to assert on liveness properties of a system. A typical use case is waiting for some asynchronous process to finish in the background before the assertion can be checked.
An example of this might be writing data to an eventually consistent store and then waiting for a read operation to return the same data.
assert eventually(fn -> {:ok, "expected_result"} == SUT.read() end)
You can also use this library to set up a synchronization point in your code.
The wrapped expression will be re-run multiple times, either until the
condition succeeds or the maximum number of retries is reached (which causes an
exception to be raised). This way you can be certain that the specified
condition holds after eventually
returns.
An example of this might be calling an external resource that we expect to fail intermittently (sigh).
credentials = XYZ.fresh_credentials()
user_id = eventually(fn -> FlakyUserService.register_user!(credentials) end)
proceed_with(user_id)
The call to eventually
will succeed if the passed function returns some value
other than false
within the provided number of retries. Otherwise, it will
either raise a Liveness
exception or reraise the last exception raised by the
function.
By default, eventually
will attempt to execute the function 250 times, every
20 milliseconds. Both parameters can be altered by passing them to
eventually
.
So, this:
eventually(fn -> ... end)
Is equivalent to this:
eventually(fn -> ... end, 250, 20)
The library is available on hex.pm. You can use it in your project by adding it to dependencies:
defp deps() do
[
{:liveness, "~> 1.0.0"}
]
end
This library is licensed under the MIT License.