What's wrong with my function for making async calls to an endpoint and collecting responses?

55 Views Asked by At

I have a use-case where I need to hit an endpoint to fetch some data. The endpoint takes start-date-time and end-date-time as params and has a limitation that the duration between them can only be <= 24hrs. So if I want to fetch data for a duration of more than 24hrs, I need to make individual api calls passing the divided intervals as params.

I have come-up with below code using @Async annotation and it is fetching the data as required. But I am suspecting this is not executing/making the calls concurrently as the response time is increasing hugely as the no. of intervals increase.

public List<Response> makeAsyncCalls(Collection<Pair<LocalDateTime, LocalDateTime>> intervals) {

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
    List<CompletableFuture<Response>> responses = new ArrayList<>();
    intervals.stream()
        .map((Pair<LocalDateTime, LocalDateTime> interval) -> Pair.of(interval.getLeft().format(formatter),
            interval.getRight().format(formatter))).forEach(timeInterval -> {
            try {
                responses.add(
                    fetchDataFromEndPoint(timeInterval));
            } catch (Exception e) {
                //throw some custom exception here
            }
        });
    CompletableFuture<Void> completedFuture = CompletableFuture.allOf(responses.toArray(new CompletableFuture[0]));
    if (completedFuture.isCompletedExceptionally()) {
        //throw exception
    }
    return responses.stream().map(CompletableFuture::join).collect(toList());
}

@Async
public CompletableFuture<Response> fetchDataFromEndPoint(Pair<String, String> interval)
            throws Exception {
            //Here service class has the webTarget that makes the call to the endpoint.
            Response response = service.getResponse(interval.getLeft(), interval.getRight());
            return CompletableFuture.completedFuture(response);
        }

Approx response times:

Interval size Response time
1 7~9 seconds
3 22~23 seconds
5 ~30 seconds
1

There are 1 best solutions below

2
Juliano Negri On

It seems that you are actually blocking on service.getResponse(interval.getLeft(), interval.getRight()). Therefore, you are not making concurrent calls to the endpoint.

Try changing @Async mechanism to Worker threads using CompletableFuture.supplyAsync()

public CompletableFuture<String> fetchDataFromEndPoint(Pair<String,String> interval){
    CompletableFuture<String> futureResponse =
            CompletableFuture.supplyAsync(() -> service.getResponse(interval.getLeft(), interval.getRight())); 

    return futureResponse;
}