Skip to content

Commit b6db37e

Browse files
motinisvelo
andauthored
issue 361 - async feign variant supporting CompleteableFutures (OpenFeign#1174)
* issue 361 - async feign variant supporting CompleteableFutures * Update core/src/test/java/feign/AsyncFeignTest.java * remove duplication between synchronous and async cases * remove duplication between synchronous and async cases * support sync calls in async-feign * Add a synchronous "AsyncClient" * Added license header * Apply feign formatter * Add '@experimental' annotation to new async classes * "fix" formatting to try and appease build Co-authored-by: Marvin Froeder <velo@users.noreply.github.com>
1 parent 292b474 commit b6db37e

File tree

11 files changed

+3056
-68
lines changed

11 files changed

+3056
-68
lines changed
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/**
2+
* Copyright 2012-2020 The Feign Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+
* in compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License
10+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11+
* or implied. See the License for the specific language governing permissions and limitations under
12+
* the License.
13+
*/
14+
package feign;
15+
16+
import java.util.Optional;
17+
import java.util.concurrent.CompletableFuture;
18+
import java.util.concurrent.ExecutorService;
19+
import java.util.concurrent.Future;
20+
import feign.Request.Options;
21+
22+
/**
23+
* Submits HTTP {@link Request requests} asynchronously, with an optional context.
24+
*/
25+
@Experimental
26+
public interface AsyncClient<C> {
27+
28+
/**
29+
* Executes the request asynchronously. Calling {@link CompletableFuture#cancel(boolean)} on the
30+
* result may cause the execution to be cancelled / aborted, but this is not guaranteed.
31+
*
32+
* @param request safe to replay
33+
* @param options options to apply to this request
34+
* @param requestContext - the optional context, for example for storing session cookies. The
35+
* client should update this appropriately based on the received response before completing
36+
* the result.
37+
* @return a {@link CompletableFuture} to be completed with the response, or completed
38+
* exceptionally otherwise, for example with an {@link java.io.IOException} on a network
39+
* error connecting to {@link Request#url()}.
40+
*/
41+
CompletableFuture<Response> execute(Request request, Options options, Optional<C> requestContext);
42+
43+
class Default<C> implements AsyncClient<C> {
44+
45+
private final Client client;
46+
private final ExecutorService executorService;
47+
48+
public Default(Client client, ExecutorService executorService) {
49+
this.client = client;
50+
this.executorService = executorService;
51+
}
52+
53+
@Override
54+
public CompletableFuture<Response> execute(Request request,
55+
Options options,
56+
Optional<C> requestContext) {
57+
final CompletableFuture<Response> result = new CompletableFuture<>();
58+
final Future<?> future = executorService.submit(() -> {
59+
try {
60+
result.complete(client.execute(request, options));
61+
} catch (final Exception e) {
62+
result.completeExceptionally(e);
63+
}
64+
});
65+
result.whenComplete((response, throwable) -> {
66+
if (result.isCancelled()) {
67+
future.cancel(true);
68+
}
69+
});
70+
return result;
71+
}
72+
}
73+
74+
/**
75+
* A synchronous implementation of {@link AsyncClient}
76+
*
77+
* @param <C> - unused context; synchronous clients handle context internally
78+
*/
79+
class Pseudo<C> implements AsyncClient<C> {
80+
81+
private final Client client;
82+
83+
public Pseudo(Client client) {
84+
this.client = client;
85+
}
86+
87+
@Override
88+
public CompletableFuture<Response> execute(Request request,
89+
Options options,
90+
Optional<C> requestContext) {
91+
final CompletableFuture<Response> result = new CompletableFuture<>();
92+
try {
93+
result.complete(client.execute(request, options));
94+
} catch (final Exception e) {
95+
result.completeExceptionally(e);
96+
}
97+
98+
return result;
99+
}
100+
}
101+
}

0 commit comments

Comments
 (0)