1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.hc.client5.http.impl.classic;
29
30 import java.io.IOException;
31
32 import org.apache.hc.client5.http.HttpRoute;
33 import org.apache.hc.client5.http.classic.BackoffManager;
34 import org.apache.hc.client5.http.classic.ConnectionBackoffStrategy;
35 import org.apache.hc.client5.http.classic.ExecChain;
36 import org.apache.hc.client5.http.classic.ExecChainHandler;
37 import org.apache.hc.core5.annotation.Contract;
38 import org.apache.hc.core5.annotation.ThreadingBehavior;
39 import org.apache.hc.core5.http.ClassicHttpRequest;
40 import org.apache.hc.core5.http.ClassicHttpResponse;
41 import org.apache.hc.core5.http.HttpException;
42 import org.apache.hc.core5.util.Args;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46
47
48
49
50
51
52
53
54
55
56
57 @Contract(threading = ThreadingBehavior.STATELESS)
58 public final class BackoffStrategyExec implements ExecChainHandler {
59
60 private static final Logger LOG = LoggerFactory.getLogger(BackoffStrategyExec.class);
61
62 private final ConnectionBackoffStrategy connectionBackoffStrategy;
63 private final BackoffManager backoffManager;
64
65
66
67
68
69
70
71
72
73
74 public BackoffStrategyExec(
75 final ConnectionBackoffStrategy connectionBackoffStrategy,
76 final BackoffManager backoffManager) {
77 super();
78 Args.notNull(connectionBackoffStrategy, "Connection backoff strategy");
79 Args.notNull(backoffManager, "Backoff manager");
80 this.connectionBackoffStrategy = connectionBackoffStrategy;
81 this.backoffManager = backoffManager;
82 }
83
84 @Override
85 public ClassicHttpResponse execute(
86 final ClassicHttpRequest request,
87 final ExecChain.Scope scope,
88 final ExecChain chain) throws IOException, HttpException {
89 Args.notNull(request, "HTTP request");
90 Args.notNull(scope, "Scope");
91 final HttpRoute route = scope.route;
92
93 final ClassicHttpResponse response;
94 try {
95 response = chain.proceed(request, scope);
96 } catch (final IOException | HttpException ex) {
97 if (this.connectionBackoffStrategy.shouldBackoff(ex)) {
98 if (LOG.isDebugEnabled()) {
99 LOG.debug("Backing off route {} due to exception: {}", route, ex.getMessage());
100 }
101 this.backoffManager.backOff(route);
102 }
103 throw ex;
104 }
105 if (this.connectionBackoffStrategy.shouldBackoff(response)) {
106 if (LOG.isDebugEnabled()) {
107 LOG.debug("Backing off route {} due to response status: {}", route, response.getCode());
108 }
109 this.backoffManager.backOff(route);
110 } else {
111 if (LOG.isDebugEnabled()) {
112 LOG.debug("Probing route: {}", route);
113 }
114 this.backoffManager.probe(route);
115 }
116 return response;
117 }
118
119 }