Skip to content

Commit 6478f30

Browse files
authored
feat: should retry based on business code (#197)
1 parent 365c1d2 commit 6478f30

File tree

2 files changed

+56
-6
lines changed

2 files changed

+56
-6
lines changed

src/main/java/io/github/doocs/im/ClientConfiguration.java

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ public class ClientConfiguration {
3131
* 默认自动更新签名
3232
*/
3333
public static final boolean DEFAULT_RENEW_SIG = true;
34+
35+
/**
36+
* 默认业务错误码重试开关关闭
37+
*/
38+
public static final boolean DEFAULT_ENABLE_BUSINESS_RETRY = false;
3439
/**
3540
* 默认超时时间(毫秒)
3641
*/
@@ -57,14 +62,15 @@ public class ClientConfiguration {
5762
private long callTimeout = DEFAULT_CALL_TIMEOUT;
5863
private long expireTime = DEFAULT_EXPIRE_TIME;
5964
private boolean autoRenewSig = DEFAULT_RENEW_SIG;
65+
private boolean enableBusinessRetry = DEFAULT_ENABLE_BUSINESS_RETRY;
6066
private String userAgent = DEFAULT_USER_AGENT;
6167
private ConnectionPool connectionPool = DEFAULT_CONNECTION_POOL;
6268

6369
public ClientConfiguration() {
6470
}
6571

6672
public ClientConfiguration(int maxRetries, long retryIntervalMs, long connectTimeout, long readTimeout, long writeTimeout,
67-
long callTimeout, long expireTime, boolean autoRenewSig,
73+
long callTimeout, long expireTime, boolean autoRenewSig, boolean enableBusinessRetry,
6874
String userAgent, ConnectionPool connectionPool) {
6975
if (connectionPool == null) {
7076
connectionPool = DEFAULT_CONNECTION_POOL;
@@ -77,6 +83,7 @@ public ClientConfiguration(int maxRetries, long retryIntervalMs, long connectTim
7783
this.callTimeout = callTimeout;
7884
this.expireTime = expireTime;
7985
this.autoRenewSig = autoRenewSig;
86+
this.enableBusinessRetry = enableBusinessRetry;
8087
this.userAgent = userAgent;
8188
this.connectionPool = connectionPool;
8289
}
@@ -90,6 +97,7 @@ private ClientConfiguration(Builder builder) {
9097
this.callTimeout = builder.callTimeout;
9198
this.expireTime = builder.expireTime;
9299
this.autoRenewSig = builder.autoRenewSig;
100+
this.enableBusinessRetry = builder.enableBusinessRetry;
93101
this.userAgent = builder.userAgent;
94102
this.connectionPool = builder.connectionPool;
95103
}
@@ -162,6 +170,14 @@ public void setAutoRenewSig(boolean autoRenewSig) {
162170
this.autoRenewSig = autoRenewSig;
163171
}
164172

173+
public boolean isEnableBusinessRetry() {
174+
return enableBusinessRetry;
175+
}
176+
177+
public void setEnableBusinessRetry(boolean enableBusinessRetry) {
178+
this.enableBusinessRetry = enableBusinessRetry;
179+
}
180+
165181
public String getUserAgent() {
166182
return userAgent;
167183
}
@@ -215,6 +231,9 @@ public boolean equals(Object o) {
215231
if (autoRenewSig != that.autoRenewSig) {
216232
return false;
217233
}
234+
if (enableBusinessRetry != that.enableBusinessRetry) {
235+
return false;
236+
}
218237
if (!userAgent.equals(that.userAgent)) {
219238
return false;
220239
}
@@ -223,7 +242,7 @@ public boolean equals(Object o) {
223242

224243
@Override
225244
public int hashCode() {
226-
return Objects.hash(maxRetries, retryIntervalMs, connectTimeout, readTimeout, writeTimeout, callTimeout, expireTime, autoRenewSig, userAgent, connectionPool);
245+
return Objects.hash(maxRetries, retryIntervalMs, connectTimeout, readTimeout, writeTimeout, callTimeout, expireTime, autoRenewSig, enableBusinessRetry, userAgent, connectionPool);
227246
}
228247

229248
public static final class Builder {
@@ -235,6 +254,7 @@ public static final class Builder {
235254
private long callTimeout = DEFAULT_CALL_TIMEOUT;
236255
private long expireTime = DEFAULT_EXPIRE_TIME;
237256
private boolean autoRenewSig = DEFAULT_RENEW_SIG;
257+
private boolean enableBusinessRetry = DEFAULT_ENABLE_BUSINESS_RETRY;
238258
private String userAgent = DEFAULT_USER_AGENT;
239259
private ConnectionPool connectionPool = DEFAULT_CONNECTION_POOL;
240260

@@ -285,6 +305,11 @@ public Builder autoRenewSig(boolean autoRenewSig) {
285305
return this;
286306
}
287307

308+
public Builder enableBusinessRetry(boolean enableBusinessRetry) {
309+
this.enableBusinessRetry = enableBusinessRetry;
310+
return this;
311+
}
312+
288313
public Builder userAgent(String userAgent) {
289314
this.userAgent = userAgent;
290315
return this;

src/main/java/io/github/doocs/im/util/HttpUtil.java

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.github.doocs.im.util;
22

33
import io.github.doocs.im.ClientConfiguration;
4+
import io.github.doocs.im.model.response.GenericResult;
45
import okhttp3.*;
56

67
import java.io.IOException;
@@ -31,7 +32,7 @@ public class HttpUtil {
3132
.writeTimeout(DEFAULT_CONFIG.getWriteTimeout(), TimeUnit.MILLISECONDS)
3233
.callTimeout(DEFAULT_CONFIG.getCallTimeout(), TimeUnit.MILLISECONDS)
3334
.retryOnConnectionFailure(false)
34-
.addInterceptor(new RetryInterceptor(DEFAULT_CONFIG.getMaxRetries(), DEFAULT_CONFIG.getRetryIntervalMs()))
35+
.addInterceptor(new RetryInterceptor(DEFAULT_CONFIG.getMaxRetries(), DEFAULT_CONFIG.getRetryIntervalMs(), null, DEFAULT_CONFIG.isEnableBusinessRetry()))
3536
.build();
3637

3738
private HttpUtil() {
@@ -58,7 +59,7 @@ private static OkHttpClient getClient(ClientConfiguration config) {
5859
.writeTimeout(cfg.getWriteTimeout(), TimeUnit.MILLISECONDS)
5960
.callTimeout(cfg.getCallTimeout(), TimeUnit.MILLISECONDS)
6061
.retryOnConnectionFailure(false)
61-
.addInterceptor(new RetryInterceptor(cfg.getMaxRetries(), cfg.getRetryIntervalMs()))
62+
.addInterceptor(new RetryInterceptor(cfg.getMaxRetries(), cfg.getRetryIntervalMs(), null, DEFAULT_CONFIG.isEnableBusinessRetry()))
6263
.build());
6364
}
6465

@@ -104,10 +105,14 @@ class RetryInterceptor implements Interceptor {
104105
private static final int MAX_DELAY_MS = 10000;
105106
private final int maxRetries;
106107
private final long retryIntervalMs;
108+
private final Set<Integer> businessRetryCodes;
109+
private final boolean enableBusinessRetry;
107110

108-
public RetryInterceptor(int maxRetries, long retryIntervalMs) {
111+
public RetryInterceptor(int maxRetries, long retryIntervalMs, Set<Integer> businessRetryCodes, boolean enableBusinessRetry) {
109112
this.maxRetries = maxRetries;
110113
this.retryIntervalMs = retryIntervalMs;
114+
this.businessRetryCodes = businessRetryCodes;
115+
this.enableBusinessRetry = enableBusinessRetry;
111116
}
112117

113118
@Override
@@ -153,7 +158,13 @@ private boolean shouldRetry(Response response) {
153158
if (code >= 500 && code < 600) {
154159
return true;
155160
}
156-
return RETRYABLE_STATUS_CODES.contains(code);
161+
if (RETRYABLE_STATUS_CODES.contains(code)) {
162+
return true;
163+
}
164+
if (enableBusinessRetry) {
165+
return shouldRetryBasedOnBusinessCode(response);
166+
}
167+
return false;
157168
}
158169

159170
private void waitForRetry(int attempt) {
@@ -164,4 +175,18 @@ private void waitForRetry(int attempt) {
164175
Thread.currentThread().interrupt();
165176
}
166177
}
178+
179+
private boolean shouldRetryBasedOnBusinessCode(Response response) {
180+
try {
181+
if (businessRetryCodes == null || businessRetryCodes.isEmpty()) {
182+
return false;
183+
}
184+
String responseBody = Objects.requireNonNull(response.body()).string();
185+
GenericResult genericResult = JsonUtil.str2Obj(responseBody, GenericResult.class);
186+
int businessCode = genericResult.getErrorCode();
187+
return businessRetryCodes.contains(businessCode);
188+
} catch (IOException | IllegalStateException e) {
189+
return false;
190+
}
191+
}
167192
}

0 commit comments

Comments
 (0)