Two ways to configure a better java retry framework sisyphus

Keywords: Java Back-end

review

We learned before

Introduction to better java retry framework sisyphus

The story behind the better java retry framework sisyphus

In this section, let's learn about sisyphus functional configuration and annotation configuration.

Functional configuration overview

In order to meet more convenient configuration, the Retryer class provides a lot of configurable information.

Default configuration

/**
 * Default configuration test
 */
public void defaultConfigTest() {
    Retryer.<String>newInstance()
            .condition(RetryConditions.hasExceptionCause())
            .retryWaitContext(RetryWaiter.<String>retryWait(NoRetryWait.class).context())
            .maxAttempt(3)
            .listen(RetryListens.noListen())
            .recover(Recovers.noRecover())
            .callable(new Callable<String>() {
                @Override
                public String call() throws Exception {
                    System.out.println("called...");
                    throw new RuntimeException();
                }
            }).retryCall();
}

It is equivalent to the following code:

public void helloTest() {
    Retryer.<String>newInstance()
            .callable(new Callable<String>() {
                @Override
                public String call() throws Exception {
                    System.out.println("called...");
                    throw new RuntimeException();
                }
            }).retryCall();
}

Method description

condition

Retry the triggered condition. You can specify multiple conditions.

The default is to throw an exception.

retryWaitContext

Retry waiting policy, multiple can be specified.

The default is no waiting.

maxAttempt

Specify the maximum number of retries, including the first execution.

Default: 3 times.

listen

Specify the listening implementation for retry. The default is no listening.

recover

When the retry conditions are still met after the retry is completed, you can specify the recovery policy.

Recovery is not performed by default.

callable

Method to retry execution.

retryCall

Trigger retry execution.

Interface details

Interface and its implementation

For all interfaces, you can directly view the corresponding subclass instances.

User defined

Based on the flexibility of substitution, users can implement interfaces and define implementations that are more in line with their own business.

sisyphus annotation

Configuration has high flexibility, but it is not as simple and flexible as annotation for developers.

Therefore, this framework also implements annotation based retry.

Design specification

Ensure the unity of interface and annotation.

maven introduction

<dependency>
    <groupId>${project.groupId}</groupId>
    <artifactId>sisyphus-annotation</artifactId>
    <version>${project.version}</version>
</dependency>

annotation

There are two main core annotations.

Retry

Used to specify the relevant configuration for retry.

/**
 * Retry annotation
 * 1. It is only allowed to put on the method according to the actual needs.
 * 2. If it is placed on the interface, does all subclasses take effect? For simplicity and clarity, this implementation is not provided.
 * 3. Maintain consistency between annotations and interfaces. {@ link com.github.houbb.sisyphus.api.core.Retry} interface
 * @author binbin.hou
 * @since 0.0.3
 */
@Documented
@Inherited
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@RetryAble(DefaultRetryAbleHandler.class)
public @interface Retry {

    /**
     * Retry class implementation
     * @return retry 
     * @since 0.0.5
     */
    Class<? extends com.github.houbb.sisyphus.api.core.Retry> retry() default DefaultRetry.class;

    /**
     * Maximum number of attempts
     * 1. Contains the number of times the method was executed normally for the first time
     * @return frequency
     */
    int maxAttempt() default 3;

    /**
     * Retry triggered scenario
     * @return Retry triggered scenario
     */
    Class<? extends RetryCondition> condition() default ExceptionCauseRetryCondition.class;

    /**
     * monitor
     * 1. No listening is performed by default
     * @return monitor
     */
    Class<? extends RetryListen> listen() default NoRetryListen.class;

    /**
     * Recovery operation
     * 1. No recovery operation is performed by default
     * @return Class corresponding to recovery operation
     */
    Class<? extends Recover> recover() default NoRecover.class;

    /**
     * Waiting strategy
     * 1. It supports specifying multiple. If not specified, no waiting will be performed,
     * @return Waiting strategy
     */
    RetryWait[] waits() default {};

}

RetryWait

Specifies the wait policy for retry.

package com.github.houbb.sisyphus.annotation.annotation;

import com.github.houbb.sisyphus.annotation.annotation.metadata.RetryWaitAble;
import com.github.houbb.sisyphus.annotation.handler.impl.DefaultRetryWaitAbleHandler;
import com.github.houbb.sisyphus.core.constant.RetryWaitConst;
import com.github.houbb.sisyphus.core.support.wait.NoRetryWait;

import java.lang.annotation.*;

/**
 * Retry wait policy
 * 1. In order to correspond to the retry policy, all built-in annotations should implement the current annotation.
 * 2. Allow custom annotations?
 *
 * When annotation + object appear at the same time, it is regarded as a combination.
 *
 * @author binbin.hou
 * @since 0.0.3
 */
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Target(ElementType.ANNOTATION_TYPE)
@RetryWaitAble(DefaultRetryWaitAbleHandler.class)
public @interface RetryWait {

    /**
     * Default value
     * 1. fixed Mode, corresponding to fixed waiting time
     * 2. Increasing
     * @return Default value
     */
    long value() default RetryWaitConst.VALUE_MILLS;

    /**
     * minimum value
     * @return minimum value
     */
    long min() default RetryWaitConst.MIN_MILLS;

    /**
     * Maximum
     * @return Maximum
     */
    long max() default RetryWaitConst.MAX_MILLS;

    /**
     * Influence factor
     * 1. Incremental retry. The default is {@ link RetryWaitConst#INCREASE_MILLS_FACTOR}
     * 2. Exponential model. The default is {@ link retrywaitconst #multiple_factor}
     * @return Influence factor
     */
    double factor() default Double.MIN_VALUE;

    /**
     * Specify the wait time class information for retry
     * @return Retry wait time class
     */
    Class<? extends com.github.houbb.sisyphus.api.support.wait.RetryWait> retryWait() default NoRetryWait.class;

}

Use of annotations

After defining annotations, there must be relevant use of annotations.

There are two main ways to use annotations.

Proxy+CGLIB

Based on proxy mode and bytecode enhancement.

If spring is not used in the project, it is more convenient to use this method directly.

Spring-AOP

It can be directly integrated with spring.

It is used in the same way as spring retry.

These contents will be explained in detail in the next section.

Summary

Flexible configuration can better meet various needs in actual production and use.

In general, it is recommended to use the annotation configuration method, which is very simple and convenient.

java retry framework sisyphus open source address

I hope this article is helpful to you. If you like it, you are welcome to like it and forward it.

I'm old ma. I look forward to seeing you again next time.

Posted by introvert on Thu, 21 Oct 2021 09:41:35 -0700