How to implement CompletableFuture with a priority execution? - java

I have an issue where I am not sure if the completable future api is able to solve my problem, but would like to open it to the stack overflow community.
I have a case, where I want to call 2 methods. One of these methods (method A) will return some data from DynamoDB. Another method (method B) will return some data from a SQL database. I would like to do these methods in parallel. However, the twist is the customer can ask for data in a certain priority.
For example, a user could pass in `["A" , "B"]. In this case, I would like both tasks to start being done in parallel, but if A finishes and returns useful data to stop execution on task B. If A returns null/not found, then return the result of B.
When reading about completable future's I have not found any methods that seem to be able to do this. The methods anyOf(CompletableFuture<?>... cfs) or allOf(CompletableFuture<?>... cfs) seem to apply to these situations. It seems like there is no way to give a preference to a specific CompletableFuture.
I would love to know how to solve this problem in Java!

Related

Java slack sdk client how to make the call async

I'm trying to make a call by using slack's sdk client in java in order to get user's id by using the email name. The slack client returns CompletableFuture object. I can get the user_name if i use get() method but as far as i understand, it's a synchronous function and it will make the application slower. Is there another way to make this call asynchronous?
public static String lookUpUserId(String email) throws ExecutionException, InterruptedException {
CompletableFuture<UsersLookupByEmailResponse> response = slackClient.usersLookupByEmail(r -> r
.email(email));
UsersLookupByEmailResponse data = response.get();
return data.getUser().getId();
}
I tried using supplyFunc and thenApply like this but it gives an error saying 'missing return statement' although i return a value. I'm just concerned about the performance and curious if there's a a better way to handle this. Thanks
response.thenApply(r->r.getUser().getId());
Since the call returns CompletableFuture, it is alredy asynchronous. Yes, get() method is a synchronous function. Using it will NOT make the application slower, it will make application consume more memory. Asynchronous access like
response.thenApply(r->r.getUser().getId());
looks correct.
The reason of error message is that the method lookUpUserId is declared as returning String and so must have a return staement. If you want to make it asynchronous, then declare it as returning CompletableFuture<String> and add return statement
return response.thenApply(r->r.getUser().getId());
I don't know much specifically about the slack api but some information can be found in this answer with regards to housing your function in a class that implements Runnable.
Make your `CompletableFuture` in the constructor and run your gets in `run()`.
In my opinion it is a best practice to process all of your api requests off of the main thread but you should know that running some single thing in a separate thread on one line and joining that thread back on the next is only going to add a little overhead without any performance advantages. If you are processing a batch of requests you should start each on independent threads with a for loop and join them all together after.
I'm also noticing that my referenced answer doesn't really cover thread joins for retrieving your results sooo you will probably also find this informative. And if you havn't learned about object oriented programming yet that's ok! you'll be writing your own classes in no time.
Edit: Ask for code if you need it, It's better if you write it yourself.

Monitor job status in the loop in Spring

I need to know if exists some pattern for following scenario:
I need call via REST API some long durable job which return me response containing job instance id a current status of job(STARTED, PROCESSING, SUCCESS FAILED, CANCELLED and so on)
After this I need to call another endpoint with job instance id from previous call to check if my job finnished or not.
The second step will be executed many time in the loop with some delay and of course with defined max count of checks.
Such routine will be always called from current thread and method will be blocked until some final status achieved or max check count or some exception during monitoring.
My idea is something like that developer will implemented some interface ExecutableMonitoredJob with two methods where first one will execute some operation and another one will determine if we are finnished or not. I would like to have it very abstract because operation might not be only REST call but for example also some db stored procedure or file creation. So second method to monitor status can have different implementation. Further, I would like to have possibility to access return value from first operation in the form of some context.
I looked at some tutorials in spring batch but I think that would be a little big overkill for now.
Does exist some suitable solution for my problem?
thanks

Execute the method after previous method finishes

I am making an android app in which I am fetching data from internet and storing it in a ArrayList with custom adapter. Fetching data takes time and in that time next function runs on its own. I only want the next function to run when data is completely fetched. What can I do? I think it has to do something with threads kindly explain what threads are and how can we use them?
Let's say there are 2 functions
Function A
Function B
I only want the function B to run when function A has completed its task. is there anyway to do that?
There are lots of resources available online where you can obtain information on Threads in Java.
I highly recommend the official Java Documentation.
This Introduction isn't half bad either.
As for obtaining information in one method and then waiting until it is done to run the next, as #cHao said, just call the methods sequentially like this
A();
B();
Unless you already have multiple threads set up in your code, this should work just fine.

What is the purpose of java.util.concurrent.CompletableFuture#allOf?

If I have Collection<CompletableFuture<MyResult>>, I expect to convert this into CompletableFuture<Collection<MyResult>>. So after conversion I have only one future and can easyly write bussines logic on MyResult collection using methods from CompletableFuture like thenApply, thenAccept etc. But CompletableFuture#allOf have result type Void so after invoking it I get "no results". E.g. I can not retrieve (as I understand) any results from returned future that correspods to Collection<CompletableFuture<MyResult>>.
I have a doubt that CompletableFuture#allOf just return the Future wich is completed after all in collection. So I can invoke CompletableFuture#allOf(...).isDone and then manually (!) in cycle tranform Collection<CompletableFuture> to CompletableFuture<Collection>, Is my assumption right?
Yes, the allOf method does not supply data, but does signal that all futures have been completed. This eliminates the need of using the more cumbersome countdown latch approach. The expectation is that you would then convert the completed futures back into a usable Collection to apply your business logic. See this question for implementation details. A great discussion of this topic is available at this blog post.
if you need CompletableFuture<Collection<MyResult>> as result you can get it by using allAsList method in https://github.com/spotify/completable-futures (spotify-completlablefutures library). CompletableFutures.allAsList(List<CompletableFuture<MyResult>>) will give you CompletableFuture<List<MyResult>>.

ability to get the progress on a Future<T> object

With reference to the java.util.concurrent package and the Future interface I notice (unless I am mistaken) that the ability to start a lengthy tasks and be able to query on the progress only comes with the SwingWorker implementing class.
This begs the following question:
Is there a way, in a non-GUI, non-Swing application (imaging a console application) to start a lengthy task in the background and allow the other threads to inspect the progress ? It seems to me that there is no reason why this capability should be limited to swing / GUI applications. Otherwise, the only available option, the way I see it, is to go through ExecutorService::submit which returns a Future object. However, the base Future interface does not allow monitoring the progress.
Obviously, the Future object would only be good for blocking and then receiving the result.
The Runnable or Callable object that you submit would either have to know how to provide this progress (percentage complete, count of attempts, status (enum?) etc) and provide that as an API call to the object itself, or posted in some lookup resource (in memory map or database if necessary). For simplicity I tend to like the object itself, especially since you're going to most likely need a handle (id) to lookup the object or a reference to the object itself.
This does mean that you have 3 threads operating. 1 for the actual work, 1 that is blocked while waiting for the result, and 1 that is a monitoring thread. The last one could be shared depending on your requirements.
In my case I passed a HashSet, with the Objects to process, as Parameter to the Method, wich was created as instance variable in the calling Class. When the asyncronous method removes the Objects after processing one can retrieve the size of the Map remaining in the calling Method. I thing in general passing Objects by Reference solves the Problem.
I was hoping that there was a standard concurrency framework way to stay updated on the progress of a long running task without requiring the client program to worry about orchestrating and synchronizing everything correctly. It seemed to me to that one could fathom an extended version of the Future<T> interface that would support:
public short progress(); in addition to the usual isDone() and get() methods.
Obviously the implementation of the progress() would then need to poll the object directly so maybe Future<T> would need to be specified as Future<T extends CanReportProgress> where CanReportProgress is the following interface:
public interface CanReportProgress {
public short progress();
}
This begs the question of why one would bother to go through the Future object as opposed to calling the object itself to get the progress. I don't know. I'll have to give it more thought. It could be argued that it is closer to the current contract / semantics whereby the Callable object is not, itself, accessed again by the client programmer after the call to ExecutorService::submit / execute.

Categories

Resources