I am using completable future to invoke multiple service calls.
CompletableFuture<Response1> future1 = CompletableFuture.supplyAsync(() -> webServiceCall1());
CompletableFuture<Response2> future2 = CompletableFuture.supplyAsync(() -> webServiceCall2());
CompletableFuture<Response3> future3 = CompletableFuture.supplyAsync(() -> webServiceCall3());
And then I am using :
Response1 response1 = future1.get();
Response2 response2 = future2.get();
Response3 response3 = future3.get();
// do further processing on the response
Well why am i using this kind of code ??? by doing that I am able to improve performance. If service1 succeeds with 200 & takes 3 sec of time , service2 succeeds with 200 & takes 3 sec of time , service3 succeeds with 200 & takes 3 sec of time , so calling them one after other will take overall 9 secs of time. But if I use what I have written above, all of them will be executing parallel & will finish around in 3 secs of time.
now issue is that if webservice1 fails, then hit to webservice2 & webservice3 will not be needed. but in my scenario, since the code is written in such a way that it calls webservice2 & webservice3, even if webservice1 fails.
How we can avoid this & still keep webservice calls parallel & still fail safe at the same time ??
Let me rephrase myself -- How we can keep the overall performance of this code high (considering benchmark of somewhere around 3 secs) & still fail safe at the same time ??
CodePudding user response:
You could use the thenApplyAsync
function:
ResponseHolder holder = CompletableFuture.supplyAsync(ResponseHolder::new)
.thenApplyAsync(h -> h.setResponse1(webServiceCall1()))
.thenApplyAsync(h -> h.setResponse2(webServiceCall2()))
.thenApplyAsync(h -> h.setResponse3(webServiceCall3()))
.get() // may fail
;
And the ResponseHolder
class:
public class ResponseHolder {
private Response1 response1;
private Response2 response2;
private Response3 response3;
// for each responseX:
public ResponseHolder setResponse1(Response1 response1) {
this.response1 = response1;
return this;
}
}
CodePudding user response:
How we can avoid this & still keep webservice calls parallel & still fail safe at the same time ??
You can't.
You've already started the processing of web service calls 2 and 3 by the time that you hear of the failure of service call 1 (for example). It's too late to not call them.
If you must call service 2 only after service call 1 succeeds, then you have to wait until you know that service call 1 has succeeded.
You're otherwise asking for a fortune-teller: call services 2 and 3 now, if service 1 will succeed at some future time.
The best you can do is to provide a way to cancel the service calls while they're in progress (i.e., tell them to quit at the next convenient point) but that might be more trouble than it's worth to get right.