Total Pageviews

2017/04/05

[Failsafe] Retry with Fallback

Scenario
If we cannot get connection, then we will retry 5 times with 2 seconds delay.
If we fail to retry with 5 times, then we will pause X minutes then retry again.
How to implement it?


How-to
You can make good use of failsafe to fulfill this implement.
In this exampe, it will demonstrate:
1. create a retry policy with 5 max retries and have 2 seconds delay among retries
2. If you got failed execution, it will retry again after 5 seconds.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package albert.practice.retry;

import java.sql.Connection;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import lombok.extern.slf4j.Slf4j;
import net.jodah.failsafe.Failsafe;
import net.jodah.failsafe.RetryPolicy;

@Slf4j
public class RetryTest {

    private int count = 0;

    public static void main(String[] args) throws ConnectionException {
        new RetryTest().connectWithRetry();
    }

    public Connection connectWithRetry() {
        // create a retry policy with 5 max retries and have 2 seconds delay among retries 
        RetryPolicy retryPolicy = new RetryPolicy();
        retryPolicy.retryOn(ConnectionException.class).withDelay(2, TimeUnit.SECONDS)
                .withMaxRetries(5);

        // Using Fallbacks allow you to provide an alternative result for a failed execution. 
        // In this example, it will retry again after 5 seconds.
        Connection conn = Failsafe.with(retryPolicy).withFallback(() -> retryIfFail())
                .get(() -> connect());

        return conn;
    }

    public void retryIfFail() throws InterruptedException {
        log.debug("GG at " + getCurrentTime());
        Thread.sleep(5000);

        log.debug("retry....." + getCurrentTime());
        connectWithRetry();
    }

    public Connection connect() throws ConnectionException {
        log.debug(" time = " + getCurrentTime());
        Connection conn = null;
        if (count < 9) {
            count++;
            throw new ConnectionException("connection fail!");
        } else {
            log.debug("get connection successfuly...");
        }
        return conn;
    }

    private String getCurrentTime() {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
        return dateFormat.format(new Date());
    }
}


Console log:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
DEBUG albert.practice.retry.RetryTest -  time = 2016/11/05 11:42:13.832
DEBUG albert.practice.retry.RetryTest -  time = 2016/11/05 11:42:15.837
DEBUG albert.practice.retry.RetryTest -  time = 2016/11/05 11:42:17.837
DEBUG albert.practice.retry.RetryTest -  time = 2016/11/05 11:42:19.837
DEBUG albert.practice.retry.RetryTest -  time = 2016/11/05 11:42:21.838
DEBUG albert.practice.retry.RetryTest -  time = 2016/11/05 11:42:23.839
DEBUG albert.practice.retry.RetryTest - GG at 2016/11/05 11:42:23.839
DEBUG albert.practice.retry.RetryTest - retry.....2016/11/05 11:42:28.839
DEBUG albert.practice.retry.RetryTest -  time = 2016/11/05 11:42:28.839
DEBUG albert.practice.retry.RetryTest -  time = 2016/11/05 11:42:30.839
DEBUG albert.practice.retry.RetryTest -  time = 2016/11/05 11:42:32.839
DEBUG albert.practice.retry.RetryTest -  time = 2016/11/05 11:42:34.840
DEBUG albert.practice.retry.RetryTest - get connection successfuly...

Reference
[1] https://github.com/jhalterman/failsafe#fallbacks

No comments: