Hi, I will describe in this post how can we write multiple parallel async calls and then combined their response in Vert-X. I will describe in Java but in other languages also it would be similar.
First of all I will describe the use case lets say if we want to make an API which internally depends on three other api calls/ DB calls which can be done parallel or which are independent of each other.
Then we can make all these three calls parallel as they are independent so the bottleneck of our APIs response time will be Max Time taken from one of these calls. If we do it sequentially then bottleneck will be the sum of time taken by all the apis.
One more thing whenever we make these type of api/DB call we don't want to block our thread as Vertx works on event loop (More info will be in another post). So we want to do it on background thread and get the callback whenever api call get the response.
For doing on the background thread and not blocking the main thread. There is a function in VertX executeblocking which executes our blocking code in the background and returns the callback when this apis returns the response.
A simple non blocking api call in VertX will look like this.
vertx.executeBlocking({ future ->
// Will call an API or a function which will consume a significant amount of time
Result result = someBlokcingAPI.blockingResponseMethod("I am blocking method");
future.complete(result);
}, { response ->
System.out.println("The result is : " + response.result());
});
So in the above function our blocking method is called on the background thread and it executes the response code block once our future.complete() is executed. Till then our event loop is not blocked. It can executes the other tasks.
We can use the same function to make more than one parallel async call and then combined the response
We will define multiple futures which will indicate the success or failure of our multiple api/DB or other blocking calls. Following is a simple example of doing async parallel call and then combining their response (It waits until all the future success or one of the future fails )
Future<ResultA> futureResultA = Future.future(); // ResultA is the type of reponse object you are expecting
Future<ResultB> future = Future.future();
vertx.executeBlocking({ future ->
// Will call an API or a function which will consume a significant amount of time
ResultA result = someBlockingAPI.blockingResponseMethod("I am blocking method");
futureResultA.complete(resultB);
future.complete(resultB);
});
Please see the second argument of executeBlocking function, If we don't pass false then it will be executed sequentially. False tells vertex that order of these functions doesn't matter so it can execute this in parallel.
vertx.executeBlocking({ future ->
// Will call an API or a function which will consume a significant amount of time
ResultB resultB = someBlockingAPI.blockingResponseMethod("I am blocking method");
futureResultB.complete(resultB);
future.complete(resultB);
}, false, { response ->
System.out.println("The result is : " + response.result());
});
So these two functions are executed asynchronously and parallel. Now for combining the response from these two call we write a function which will be called once both the future are successfully completed or one of them fails.
CompositeFuture.all( futureResultA, futureResultB).setHandler({ allResponse ->
if(allResponse.succeeded()){
// It will be called when both the future is completed successfully.
// you will have response of both the above function here you can combine the response // return
ResultC resultC = getResultCFromResultAAndResultB(futureResultA.result(), futureResultB.result());
// now you have the combined object from both the responses, you can return the response // or do whatever you want we the new combined object
} else {
// this will be called when any of the future is failed.
// return error message or log the error do whatever is needed here if call fails.
}
});
CompositeFuture.all is one function for composition there are some others also like CompositeFuture.any etc. I will write the difference in some other post.
If you like the post please share it. If you have any question please comment, I will try to answer. Till then Enjoy Programming :)
Source : http://vertx.io/docs/vertx-core/java/
First of all I will describe the use case lets say if we want to make an API which internally depends on three other api calls/ DB calls which can be done parallel or which are independent of each other.
Then we can make all these three calls parallel as they are independent so the bottleneck of our APIs response time will be Max Time taken from one of these calls. If we do it sequentially then bottleneck will be the sum of time taken by all the apis.
One more thing whenever we make these type of api/DB call we don't want to block our thread as Vertx works on event loop (More info will be in another post). So we want to do it on background thread and get the callback whenever api call get the response.
For doing on the background thread and not blocking the main thread. There is a function in VertX executeblocking which executes our blocking code in the background and returns the callback when this apis returns the response.
A simple non blocking api call in VertX will look like this.
vertx.executeBlocking({ future ->
// Will call an API or a function which will consume a significant amount of time
Result result = someBlokcingAPI.blockingResponseMethod("I am blocking method");
future.complete(result);
}, { response ->
System.out.println("The result is : " + response.result());
});
So in the above function our blocking method is called on the background thread and it executes the response code block once our future.complete() is executed. Till then our event loop is not blocked. It can executes the other tasks.
We can use the same function to make more than one parallel async call and then combined the response
We will define multiple futures which will indicate the success or failure of our multiple api/DB or other blocking calls. Following is a simple example of doing async parallel call and then combining their response (It waits until all the future success or one of the future fails )
Future<ResultA> futureResultA = Future.future(); // ResultA is the type of reponse object you are expecting
Future<ResultB> future = Future.future();
vertx.executeBlocking({ future ->
// Will call an API or a function which will consume a significant amount of time
ResultA result = someBlockingAPI.blockingResponseMethod("I am blocking method");
futureResultA.complete(resultB);
future.complete(resultB);
}, false, { response ->
System.out.println("The result is : " + response.result());});
Please see the second argument of executeBlocking function, If we don't pass false then it will be executed sequentially. False tells vertex that order of these functions doesn't matter so it can execute this in parallel.
vertx.executeBlocking({ future ->
// Will call an API or a function which will consume a significant amount of time
ResultB resultB = someBlockingAPI.blockingResponseMethod("I am blocking method");
futureResultB.complete(resultB);
future.complete(resultB);
}, false, { response ->
System.out.println("The result is : " + response.result());
});
So these two functions are executed asynchronously and parallel. Now for combining the response from these two call we write a function which will be called once both the future are successfully completed or one of them fails.
CompositeFuture.all( futureResultA, futureResultB).setHandler({ allResponse ->
if(allResponse.succeeded()){
// It will be called when both the future is completed successfully.
// you will have response of both the above function here you can combine the response // return
ResultC resultC = getResultCFromResultAAndResultB(futureResultA.result(), futureResultB.result());
// now you have the combined object from both the responses, you can return the response // or do whatever you want we the new combined object
} else {
// this will be called when any of the future is failed.
// return error message or log the error do whatever is needed here if call fails.
}
});
CompositeFuture.all is one function for composition there are some others also like CompositeFuture.any etc. I will write the difference in some other post.
If you like the post please share it. If you have any question please comment, I will try to answer. Till then Enjoy Programming :)
Source : http://vertx.io/docs/vertx-core/java/