Groovy Programmer : How to use Groovy default parameter values to implement retry functionality

Lets say you have a class which depends on another component. The component ( for example a remote call ) sometimes fails. You want to execute a method with a number of retries. Groovy supports parameters with default values and we are going to leverage that capability and recursion to achieve a retry functionality.

package groovycalamari

class WithRetryService {

    def remoteService

    String name(int retryAttempts = 2, int waitingMillisecondsBetweenAttempts = 5_000) {
        String result = remoteService?.name()
        if ( !result && retryAttempts > 0 ) {
            sleep(waitingMillisecondsBetweenAttempts)
            return name( (retryAttempts - 1), waitingMillisecondsBetweenAttempts )
        }
        result

    }
}

I have a collaborator which always fails.

package groovycalamari

class AlwaysFailsRemoteService {
    int numberOfTimesCalled = 0

    String name() {
        numberOfTimesCalled++
        return null
    }
}

I’ve a collaborator which fails the first two times, but works the third time is invoked.

package groovycalamari

class FailsTwiceWorksThridTimeRemoteService {

    int numberOfTimesCalled = 0

    String name() {
        if (numberOfTimesCalled < 2) {
            numberOfTimesCalled++
            return null

        }
        'Sergio del Amo'
    }
}

And here the Spock test to verify it works:

package groovycalamari

import spock.lang.Specification

class WithRetryServiceSpec extends Specification {

    def "test retry with a failing service will eventually fail"() {

        given:
        def service = new WithRetryService()
        service.remoteService = new AlwaysFailsRemoteService()

        when:
        String result = service.name()

        then:
        !result
        service.remoteService.numberOfTimesCalled == 3
    }

    def "test retry with a service which fails initially will eventually pass"() {

        given:
        def service = new WithRetryService()
        service.remoteService = new FailsTwiceWorksThridTimeRemoteService()

        when:
        String result = service.name()

        then:
        result
        service.remoteService.numberOfTimesCalled == 2
    }

}

Leave a Reply

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