spring retry, guava retrying integration framework retries -sisyphus java

Sisyphus

Support procedural programming and java programming notes retry framework.

characteristic

  • Support fluent procedural programming

  • Agent-based retry bytecode

  • Based on annotation of a retry, allows custom annotations

  • Seamless access spring

  • Unified interface and annotation

  • To solve the shortcomings spring-retry and guava-retrying the

aim of design

A combination of spring-retry and gauva-retrying advantage.

Adjust some of the features to make it more conducive to practical use.

Similar ideas Netty interfaces ensure flexibility consistent interface, and replacement.

Learn Hibernate-Validator is designed to allow user-defined annotations.

The inadequacies of spring-retry and guava-retrying the

update record

update record

Open source address

sisyphus

Quick Start

Introduced

<plugin>
    <groupId>com.github.houbb</groupId>
    <artifactId>sisyphus-core</artifactId>
    <version>0.0.6</version>
</plugin>
复制代码

Access code

For details, see RetryerTest

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

Code Analysis

  • retry

Specifies the realization of a callable.

We print a log, and a simulation program exception.

Log information

Log information

called...
called...
called...
复制代码

And some other exception information.

Retry trigger condition, the default program is an abnormality has occurred

Here retry interval default is no time interval, a total of three attempts. (Including the first execution program itself)

Why sisyphus

Why sisyphus

As developers, we usually choose the more famous framework.

比如 guava-retrying spring-retry。

Or simply write one yourself.

Why not a guava-retrying / spring-retry

java retry this article I cited above as well as common implementation of the two frameworks, but also about the lack of them.

guava-retrying the advantages and disadvantages

advantage

  • Flexible

  • fluent and elegant wording

  • Provide more than enough to achieve

Shortcoming

  • There is no default annotation-based implementation

  • Retry strategy is not friendly design

spring-retry

advantage

  • Simple to use

Shortcoming

  • Retry single condition

  • Retry Wait a single strategy

  • You can not customize annotations

Why not write your own

Personal feelings

As a developer I usually tell the truth, to see and try again.

I would definitely lazy to write a for loop, retry several times over.

Since time does not permit.

If you're a little more diligent, you can choose spring-retry / guava-retrying. If you are familiar with their strengths and weaknesses, then.

If you want to create

All implementations sisyphus are based interfaces.

You can achieve their realization, all the basic things can be replaced.

Of course, some of the common strategy to achieve the basic framework of the project have detailed notes, as a reference can also have a little help.

sisyphus do more things

netty inspiration

Netty reference design, to ensure the consistency of the interface.

Sisyphus but also to do more, but also to ensure consistency between the interface and comments.

Use the boot class, to ensure convenience in use, late expansion flexibility.

hibernate-validator

Author hibernate-validator that I know one of the few applications for java annotations great developers. (Though poorly understood)

Custom annotation is from this framework to the school.

Associating with spring

The basic spring inseparable with our code, so you can simply combine spring.

As you use spring-retry the same.

sisyphus Module Introduction

Module division

sisyphus module division when taking into account the user's convenience, there are several modules:

sisyphus-api

Module interface definition, is the most basic part.

The default will be dependent sisyphus-core.

Generally do not need introduction, if you want to achieve according to its own retry the framework of a try.

sisyphus-core

For sisyphus-api module default implementation.

Fluent easy to use and adding boot class, can easily write code that retries declarative.

sisyphus-annotation

sisyphus comments implement the module.

(1) Based on Agent retry bytecode can not rely on spring. Usually use more flexible

(2) Its realization allows custom annotations. Users can write their own notes to retry.

sisyphus-spring

spring as a guide in java. Nature is to be supported.

You can use spring-retry and as easy to use sisyphus-spring.

Dependencies between modules

sisyphus-api
sisyphus-core
sisyphus-annotation
sisyphus-spring
sisyphus-test
复制代码

sisyphus-api is the basis of the maximum flexibility.

sisyphus-spring is the easiest-to-use, flexibility, relatively poor.

sisyphus-test as a test only, without external introduction.

sisyphus Configuration Overview

In order to meet more easily configured, Retryer class provides a lot of information that can be configured.

default allocation

/**
 * 默认配置测试
 */
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();
}
复制代码

And 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 trigger conditions, you can specify multiple criteria.

The default is thrown.

retryWaitContext

Retry strategy to wait, you can specify more.

The default is not any waiting.

maxAttempt

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

Default: 3 times.

listen

Specifies the Retry monitor implementation, the default is not listening.

recover

After the completion of the retry, retry still meet the conditions, you can specify the policy restored.

The default is not restored.

callable

The method of retries to be performed.

retryCall

Trigger retries.

Details Interface

Interface and its implementation

All interfaces are visible instance of a subclass corresponding directly.

Custom

Based on the flexibility of replacement, users can implement the interface defined to achieve more in line with their business.

sisyphus comment

Configuration with high flexibility, but for developers to use, there would be no comment as simple and flexible.

Therefore, the present frame is also achieved based annotation retry.

Design specifications

Both interfaces ensure uniformity and annotations.

maven introduced

<dependency>
    <groupId>${project.groupId}</groupId>
    <artifactId>sisyphus-annotation</artifactId>
    <version>${project.version}</version>
</dependency>
复制代码

annotation

There are two main core notes.

Retry

For the retry configuration.

/**
 * 重试注解
 * 1. 实际需要,只允许放在方法上。
 * 2. 如果放在接口上,是否所有的子类都生效?为了简单明确,不提供这种实现。
 * 3. 保持注解和接口的一致性。{@link com.github.houbb.sisyphus.api.core.Retry} 接口
 * @author binbin.hou
 * @since 0.0.3
 */
@Documented
@Inherited
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@RetryAble(DefaultRetryAbleHandler.class)
public @interface Retry {

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

    /**
     * 最大尝试次数
     * 1. 包含方法第一次正常执行的次数
     * @return 次数
     */
    int maxAttempt() default 3;

    /**
     * 重试触发的场景
     * @return 重试触发的场景
     */
    Class<? extends RetryCondition> condition() default ExceptionCauseRetryCondition.class;

    /**
     * 监听器
     * 1. 默认不进行监听
     * @return 监听器
     */
    Class<? extends RetryListen> listen() default NoRetryListen.class;

    /**
     * 恢复操作
     * 1. 默认不进行任何恢复操作
     * @return 恢复操作对应的类
     */
    Class<? extends Recover> recover() default NoRecover.class;

    /**
     * 等待策略
     * 1. 支持指定多个,如果不指定,则不进行任何等待,
     * @return 等待策略
     */
    RetryWait[] waits() default {};

}
复制代码

RetryWait

It is used to specify the retry wait strategy.

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.*;

/**
 * 重试等待策略
 * 1. 为了对应重试策略,所有的内置注解应该实现当前的注解。
 * 2. 是否允许自定义注解?
 *
 * 当注解+对象同时出现的时候,视为组合。
 *
 * @author binbin.hou
 * @since 0.0.3
 */
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Target(ElementType.ANNOTATION_TYPE)
@RetryWaitAble(DefaultRetryWaitAbleHandler.class)
public @interface RetryWait {

    /**
     * 默认值
     * 1. fixed 模式,则对应固定等待时间
     * 2. 递增
     * @return 默认值
     */
    long value() default RetryWaitConst.VALUE_MILLS;

    /**
     * 最小值
     * @return 最小值
     */
    long min() default RetryWaitConst.MIN_MILLS;

    /**
     * 最大值
     * @return 最大值
     */
    long max() default RetryWaitConst.MAX_MILLS;

    /**
     * 影响因数
     * 1. 递增重试,默认为 {@link RetryWaitConst#INCREASE_MILLS_FACTOR}
     * 2. 指数模式。默认为 {@link RetryWaitConst#MULTIPLY_FACTOR}
     * @return 影响因数
     */
    double factor() default Double.MIN_VALUE;

    /**
     * 指定重试的等待时间 class 信息
     * @return 重试等待时间 class
     */
    Class<? extends com.github.houbb.sisyphus.api.support.wait.RetryWait> retryWait() default NoRetryWait.class;

}
复制代码

Use annotations

Well-defined annotations, be sure to have annotations related use.

On the use of annotations, mainly in two ways.

Proxy+CGLIB

Agent-based enhancement mode and bytecode.

If the project is not used in spring, direct use of more convenient this way.

Spring-AOP

And spring can be integrated directly.

Use and spring-retry the same.

sisyphus agency template

purpose

In order to facilitate users to more easily use the annotation, while not dependent spring.

Code pattern-based manner bytecode + enhancement implementation.

Use Cases

maven introduced

The introduction of notes related modules.

<dependency>
    <groupId>${project.groupId}</groupId>
    <artifactId>sisyphus-annotation</artifactId>
    <version>${project.version}</version>
</dependency>
复制代码

Defined test methods

The following test code can refer spring-test module.

  • MenuServiceImpl.java
public class MenuServiceImpl {

    public void queryMenu(long id) {
        System.out.println("查询菜单...");
        throw new RuntimeException();
    }

    @Retry
    public void queryMenuRetry(long id) {
        System.out.println("查询菜单...");
        throw new RuntimeException();
    }

}
复制代码

test

Use RetryTemplate test

No retry annotated method

@Test(expected = RuntimeException.class)
public void templateTest() {
    MenuServiceImpl menuService = RetryTemplate.getProxyObject(new MenuServiceImpl());
    menuService.queryMenu(1);
}
复制代码
  • Log information
查询菜单...
复制代码

He requested only once.

Annotated method

@Test(expected = RuntimeException.class)
public void templateRetryTest() {
    MenuServiceImpl menuService = RetryTemplate.getProxyObject(new MenuServiceImpl());
    menuService.queryMenuRetry(1);
}
复制代码
  • Log information
查询菜单...
查询菜单...
查询菜单...
复制代码

other

Of course there are many more configuration, you can try yourself.

If you want to combine spring using annotations, please continue to read.

sisyphus spring Integration

purpose

Similar to the spring-retry framework, if you use spring framework, the integration of this project will be very simple.

Notes manner and process of programming, both to maintain consistency as much as possible, you want from a way into another relatively simple.

To switch from the present frame to the spring-retry is also very convenient.

Examples of Use

maven introduced

<dependency>
    <groupId>${project.groupId}</groupId>
    <artifactId>sisyphus-spring</artifactId>
    <version>${project.version}</version>
</dependency>
复制代码

The default will be the introduction of spring and AOP related jar.

Business code

You can refer to sisyphus-test module.

SIMULATED very common in some business methods.

Using the @Retryidentification method requires a retry.

  • SpringService.java
public interface SpringService {

    /**
     * 查询示例代码
     * @return 结果
     */
    String query();

}
复制代码
  • SpringServiceImpl.java
import com.github.houbb.sisyphus.annotation.annotation.Retry;
import com.github.houbb.sisyphus.test.service.SpringService;
import org.springframework.stereotype.Service;

/**
 * @author binbin.hou
 * @since 0.0.4
 */
@Service
public class SpringServiceImpl implements SpringService {

    @Override
    @Retry
    public String query() {
        System.out.println("spring service query...");
        throw new RuntimeException();
    }

}
复制代码

Open retry

Annotation-based configuration can be directly follows.

Using @EnableRetryidentification required to open and try again.

@Configurable
@ComponentScan(basePackages = "com.github.houbb.sisyphus.test.service")
@EnableRetry
public class SpringConfig {
}
复制代码

Test code

import com.github.houbb.sisyphus.test.config.SpringConfig;
import com.github.houbb.sisyphus.test.service.SpringService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * @author binbin.hou
 * @since 0.0.4
 */
@ContextConfiguration(classes = SpringConfig.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringServiceTest {

    @Autowired
    private SpringService springService;

    @Test(expected = RuntimeException.class)
    public void queryTest() {
        springService.query();
    }

}
复制代码
  • Log information
spring service query...
spring service query...
spring service query...
复制代码

New features scheduled

To the Senate

Retry context information added to the reference

Configuration optimization

Provide more excellent configuration experience

Reproduced in: https: //juejin.im/post/5d0ba0e051882559f63014c8

Guess you like

Origin blog.csdn.net/weixin_34085658/article/details/93175669