Non-fixed poll intervals in Awaitility

I just released Awaitility 1.7.0 and one of the big new features is the ability to use non-fixed poll intervals. A poll interval tells Awaitility how often it should evaluate the condition that is supplied to the until method. Previously you could only specify a poll interval at a fixed rate like this:

with().pollInterval(150, TimeUnit.MILLISECONDS).
       await().until(() -> someConditionIsFulfilled());

This means that `someConditionIsFulfilled` is evaluated (approximately) every 150th millisecond. I many situations this is just fine but imagine that `someConditionIsFulfilled` could take a while, perhaps it involves a network call or invokes a (slow) database. So Awaitility now also ships with other kinds of poll intervals, the FibonacciPollInterval and IterativePollInterval that allows for various back-off strategies.

Fibonacci

The FibonacciPollInterval generates a non-linear poll interval based on the fibonacci sequence. This is useful if it’s likely that the condition completes fast but if not we should back-off gracefully. To use this poll interval we can do like this:

with().pollInterval(fibonacci()).await().until(..);

where `fibonacci` is statically imported from `com.jayway.awaitility.pollinterval.FibonacciPollInterval`. This will generate a poll interval of `1, 1, 2, 3, 5, 8, 13, ..` milliseconds. To change the time unit to use, for example to seconds instead of milliseconds you can do:

with().pollInterval(fibonacci(TimeUnit.SECONDS)).await().until(..);

Or a bit more english-like:

with().pollInterval(fibonacci().with().timeUnit(SECONDS)).await().until(..);

Iterative

This poll interval creates a sequence generated by a function and a start duration. The function is free to do anything it wants with the duration, for example multiplying it by 2:

await().with().pollInterval(iterative(duration -> duration.multiply(2)), 
                            Duration.FIVE_HUNDRED_MILLISECONDS).until(..);

or a bit more english-like:

await().with().pollInterval(
                 iterative(duration -> duration.multiply(2)).with().startDuration(FIVE_HUNDRED_MILLISECONDS)
               ).until(..);

This generates a poll interval sequence that looks like this (ms): `500, 1000, 2000, 4000, 8000, 16000, …`

Custom

If fibonacci or iterative poll interval won’t do it for you it’s possible to roll your own implementation. We can do this by implementing the PollInterval interface that ships with Awaitility. This is a functional interface so in Java 8 we can for example do like this:

await().with().pollInterval((__, previous) -> previous.multiply(2).plus(1)).until(..);

In this example we create a `PollInterval` that is implemented as a (bi-) function that takes the previous poll interval duration and multiplies it by 2 and adds 1. `__` just signals that we don’t care about the poll count that is also provided by the `PollInterval` interface. Poll count is required when creating poll intervals that are not (only) interested in the previous duration but rather generates its duration based on the number of times it has been called. For example the `FibonacciPollInterval` uses only the poll count:

await().with().pollInterval((pollCount, __) -> new Duration(fib(pollCount), MILLISECONDS)).until(..);

With this approach you should be able to create all kinds of different poll interval sequences, for example sinus, parabolic and (true) exponential sequences if required.

Conclusion

Non-fixed poll intervals can be very useful in certain situations. Awaitility ships with some basic non-fixed poll intervals but it should be possible to create tailer made sequences that suits your unique use case if required.

One thought on “Non-fixed poll intervals in Awaitility

Leave a Reply to B. K. Oxley (binkley) Cancel reply

Your email address will not be published. Required fields are marked *