Skip to content

Commit

Permalink
Add retrier implementation based on Spring Retry
Browse files Browse the repository at this point in the history
  • Loading branch information
chenzhiguo committed May 7, 2024
1 parent 4449972 commit 34b36cb
Show file tree
Hide file tree
Showing 10 changed files with 244 additions and 2 deletions.
5 changes: 5 additions & 0 deletions joylive-bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@
<artifactId>joylive-flowcontrol-resilience4j</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.jd.live</groupId>
<artifactId>joylive-flowcontrol-spring</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.jd.live</groupId>
<artifactId>joylive-classloader-springboot2</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,8 @@ protected O process(R request) {
/**
* Create a retry supplier
*
* @param ctx The {@link MethodContext} containing information about the target
* method to be invoked, its arguments, and the expected result type.
* @param ctx The {@link MethodContext} containing information about the target
* method to be invoked, its arguments, and the expected result type.
* @return Returns a supplier for retry logic.
*/
protected Supplier<Response> createRetrySupplier(MethodContext ctx) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.jd.live</groupId>
<artifactId>joylive-flowcontrol</artifactId>
<version>${revision}</version>
</parent>

<artifactId>joylive-flowcontrol-spring</artifactId>

<properties>
<spring.version>4.3.16.RELEASE</spring.version>
<spring-retry.version>2.0.5</spring-retry.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>${spring-retry.version}</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<configuration>
<artifactSet>
<includes>
<include>org.springframework:*</include>
<include>org.springframework.retry:*</include>
</includes>
</artifactSet>
<transformers>
<!-- This transformer will merge the contents of META-INF/services -->
<transformer
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
<relocations>
<relocation>
<pattern>org.springframework</pattern>
<shadedPattern>com.jd.live.agent.shaded.org.springframework</shadedPattern>
</relocation>
<relocation>
<pattern>org.springframework.retry</pattern>
<shadedPattern>com.jd.live.agent.shaded.org.springframework.retry</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright © ${year} ${owner} (${email})
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jd.live.agent.implement.flowcontrol.spring.retry;

import com.jd.live.agent.governance.invoke.retry.Retrier;
import com.jd.live.agent.governance.policy.service.retry.RetryPolicy;
import com.jd.live.agent.governance.response.Response;
import org.springframework.retry.backoff.FixedBackOffPolicy;
import org.springframework.retry.support.RetryTemplate;

import java.util.function.Supplier;

/**
* SpringRetrier
*
* @since 1.0.0
*/
public class SpringRetrier implements Retrier {

private final RetryPolicy policy;

private final RetryTemplate retryTemplate;

public SpringRetrier(RetryPolicy policy) {
this.policy = policy;
this.retryTemplate = new RetryTemplate();
SpringRetryPolicy retryPolicy = new SpringRetryPolicy(policy);
retryPolicy.setMaxAttempts(policy.getRetry());
retryTemplate.setRetryPolicy(retryPolicy);
FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
fixedBackOffPolicy.setBackOffPeriod(policy.getWaitTimeInMilliseconds());
retryTemplate.setBackOffPolicy(fixedBackOffPolicy);
}

/**
* {@inheritDoc}
*/
@Override
public boolean isRetryable(Response response) {
return policy.isRetry(response.getCode()) || policy.isRetry(response.getThrowable());
}

/**
* {@inheritDoc}
*/
@Override
public <T extends Response> T execute(Supplier<T> supplier) {
// TODO retry timeout
return retryTemplate.execute(context -> {
T response = supplier.get();
context.setAttribute(SpringRetryPolicy.RESPONSE_KEY, response);
return response;
});
}

/**
* {@inheritDoc}
*/
@Override
public RetryPolicy getPolicy() {
return policy;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright © ${year} ${owner} (${email})
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jd.live.agent.implement.flowcontrol.spring.retry;

import com.jd.live.agent.core.extension.annotation.Extension;
import com.jd.live.agent.governance.invoke.retry.Retrier;
import com.jd.live.agent.governance.invoke.retry.RetrierFactory;
import com.jd.live.agent.governance.policy.service.retry.RetryPolicy;

/**
* SpringRetrierFactory
*
* @since 1.0.0
*/
@Extension(value = "Spring")
public class SpringRetrierFactory implements RetrierFactory {

@Override
public Retrier create(RetryPolicy retryPolicy) {
return new SpringRetrier(retryPolicy);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright © ${year} ${owner} (${email})
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jd.live.agent.implement.flowcontrol.spring.retry;

import com.jd.live.agent.governance.policy.service.retry.RetryPolicy;
import com.jd.live.agent.governance.response.Response;
import org.springframework.retry.RetryContext;
import org.springframework.retry.policy.SimpleRetryPolicy;

/**
* SpringRetryPolicy
*
* @since 1.0.0
*/
public class SpringRetryPolicy extends SimpleRetryPolicy {

public static final String RESPONSE_KEY = "response";

private final RetryPolicy retryPolicy;

public SpringRetryPolicy(RetryPolicy retryPolicy) {
this.retryPolicy = retryPolicy;
}

@Override
public boolean canRetry(RetryContext context) {
Throwable t = context.getLastThrowable();
boolean can = (t == null || retryPolicy.isRetry(t)) && context.getRetryCount() < this.getMaxAttempts();
if (!can && context.hasAttribute(RESPONSE_KEY)) {
Response response = (Response) context.getAttribute(RESPONSE_KEY);
can = retryPolicy.isRetry(response.getCode()) && context.getRetryCount() < this.getMaxAttempts();
}
if (!can) {
can = super.canRetry(context);
}
return can;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
com.jd.live.agent.implement.flowcontrol.spring.retry.SpringRetrierFactory
1 change: 1 addition & 0 deletions joylive-implement/joylive-flowcontrol/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<packaging>pom</packaging>
<modules>
<module>joylive-flowcontrol-resilience4j</module>
<module>joylive-flowcontrol-spring</module>
</modules>

<dependencies>
Expand Down
5 changes: 5 additions & 0 deletions joylive-package/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@
<artifactId>joylive-flowcontrol-resilience4j</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.jd.live</groupId>
<artifactId>joylive-flowcontrol-spring</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.jd.live</groupId>
<artifactId>joylive-classloader-springboot2</artifactId>
Expand Down
1 change: 1 addition & 0 deletions joylive-package/src/main/assembly/assembly.xml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
<include>com.jd.live:joylive-event-opentelemetry</include>
<include>com.jd.live:joylive-expression-jexl</include>
<include>com.jd.live:joylive-flowcontrol-resilience4j</include>
<include>com.jd.live:joylive-flowcontrol-spring</include>
</includes>
</dependencySet>

Expand Down

0 comments on commit 34b36cb

Please sign in to comment.