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.
update record
Open source address
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 @Retry
identification 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 @EnableRetry
identification 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