In my previous post about Retry with Spring I - Number of Retries I covered how we can retry an operation n
number of times in case the operation causes an exception.
In this post I am going to cover the simplest retry policy - TimeoutRetryPolicy
. This policy keep retrying an operation until the timeout occurs. A sample use case for it might be: we just restarted the database and the database takes a few seconds to come up. So keep retrying for configured amount of seconds.
Easier to show with an example:
import com.rackspace.monitoring.BaseLoggingThing
import org.springframework.retry.RetryCallback
import org.springframework.retry.RetryContext
import org.springframework.retry.policy.TimeoutRetryPolicy
import org.springframework.retry.support.RetryTemplate
class TimeoutRetryExample extends BaseLoggingThing {
RetryTemplate retryTemplate = new RetryTemplate()
CarRepository carRepository
TimeoutRetryExample(com.rackspace.monitoring.atomhopper.CarRepository carRepository, int timeoutInSecs) {
this.carRepository = carRepository
TimeoutRetryPolicy timeoutRetryPolicy = new TimeoutRetryPolicy()
timeoutRetryPolicy.timeout = timeoutInSecs * 1000L
retryTemplate.retryPolicy = timeoutRetryPolicy
}
String getCar(final String make) {
return retryTemplate.execute(new RetryCallback() {
@Override
String doWithRetry(RetryContext retryContext) throws Exception {
// A long operation is simulated here.
sleep(1000)
return carRepository.findCarNameByMake(make)
}
})
}
}
And corresponding test:
import spock.lang.Specification
import spock.lang.Timeout
import spock.lang.Unroll
class TimeoutRetryExampleTest extends Specification {
CarRepository carRepository = Mock()
@Timeout(2)
@Unroll
def 'retries 1 times'() {
given:
// Retry for 1 seconds
TimeoutRetryExample retryExample = new TimeoutRetryExample(carRepository, 1)
when:
retryExample.getCar('Toyota')
then:
thrown(IllegalStateException)
1 * carRepository.findCarNameByMake(_) >> { throw new IllegalStateException('foo') }
}
@Timeout(2)
@Unroll
def 'does not retry if no exception is thrown'() {
given:
// Retry for 1 seconds
TimeoutRetryExample retryExample = new TimeoutRetryExample(carRepository, 5)
when:
def car = retryExample.getCar('Toyota')
then:
car == 'Family Car'
1 * carRepository.findCarNameByMake(_) >> 'Family Car'
}
@Timeout(6)
@Unroll
def 'retries 5 times'() {
given:
// Retry for 5 seconds
TimeoutRetryExample retryExample = new TimeoutRetryExample(carRepository, 5)
when:
def car = retryExample.getCar('Toyota')
then:
car == 'Camry'
5 * carRepository.findCarNameByMake(_) >>
{ throw new IllegalStateException('foo') } >>
{ throw new IllegalStateException('foo') } >>
{ throw new IllegalStateException('foo') } >>
{ throw new IllegalStateException('foo') } >>
'Camry'
}
}