How to check status and cancel an asynchronous task? - java

Currently, I am working on a rest API through which client can submit a forever running task and it should return started confirmation if there is no error. The client should be able to submit any number of similar tasks. There should be a functionality to check the status and cancel any task. Currently, I am trying to do it in Java using Spring. How should I approach the problem?
I was able to create an asynchronous task in Spring each time I sent a post request. But till now unable to figure out how to check the status and cancel any task.

Threads you can use here.
Create a job executor class responsible for running the task.
Make a callable. So, you would be able to get the result in the Future.
Use BlockingQueue for the task to store and pick from it (you should because of processor i.e. dual/4 cores).
Use Runtime Class to get the Cores available and Run the thread in cores-1.
No. of thread = Available cores-1.
for cancellation, you can use a flag that mapped to respected stored Thread. Check that flag and return if thread started at any point of time

Related

Long running processes inside service invoked from actor

We are using Akka actors in our application. Actors are invoking services and in some cases those services are calling rest API exposed by third party. Now the third party APIs are taking a very long time to respond. Due to this during peak time , the system through put is getting impacted as threads are blocked as they wait for client API to respond.
Sometimes during peak time , because threads are waiting , messages just keep waiting in akka mail box for long time and are picked up, once blocked threads are made available.
I am looking for some solution where in i can improve the throughput of the system and can free up threads so that actor messages can start processing.
I am thinking to change the rest API call from blocking to non blocking call using Future and creating a dedicated actor for such kind of rest API invocations . Actor will periodically check if future is completed and then sends a completion message and then rest of process can continue.This way the number of blocking threads will reduce and they will be available for actor message processing.
Also would like to have separate execution context for actors which are doing blocking operations. As of now we have global execution context.
Need further inputs on this.
Firstly, you are correct that you should not block when processing a message, so you need to start an asynchronous process and return immediately from the message handler. The Actor can then send another message when the process completes.
You don't say what technology you are using for the REST API calls but libraries like Akka HTTP will return a Future when making an HTTP request so you shouldn't need to add your own Future around it. E.g:
def getStatus(): Future[Status] =
Http().singleRequest(HttpRequest(uri = "http://mysite/status")).flatMap {
res =>
Unmarshal(res).to[Status]
}
If for some reason you are using a synchronous library, wrap the call in Future(blocking{ ??? }) to notify the execution context that it needs to create a new thread. You don't need a separate execution context unless you need to control the scheduling of threads for this operation.
You also don't need to poll the Future, simply add an onComplete handler that sends an internal message back to your actor which then processes the result of the API call.

Should I create executor service for each request in spring controller?

I am trying to build a rest API controller which takes a list of hostnames as input and a command to be executed in each hostname
#RequestMapping("/tasks")
public Result execute(#RequestParam(value="hostList") List<HostName> hosts, String command) {
//1. Execute the command in each hostname asynchronously and get completable future.
//2. Get a list of completable future for each hostname command execution
//3. Wait for them to complete and then compose the result
}
The question is that, step 1 needs to happen asynchronously for each hostname.
I am planning to create a an executor service (with thread pool size of hosts.size()) for each request and then execute step 1 in that thread pool.
But I think it is a bad idea to create executor for each request, since that will consume a lot of memory.
Is this correct way forward or is there something in built in spring to take care of this scenario.
Please note that the list of hosts can vary from 1 to 20
No, there is no reason to create a new executor for each request. You should have one executor and when your request comes your code should create a number of runnable tasks and submit them to the executor. Also in your case, since you are talking about running some command on different hosts, it means that you don't run any command on your server. You somehow send a message to the relevant host with command to execute. (I assume through a queue). So your commands can NOT be executed synchronously even if you wanted to, since each command is executed on a different host. So, obviously they can not be running in the same process, let alone the same thread. So in your case, you probably don't need to have any Executor at all.
There is no reason to be making a new Thread for each request. You can either have a thread pool with fixed size N created by an Executor or submit your tasks on the Tomcat/any other provider threads that are used to fulfil your HTTP request. I gave two solutions below that may apply to one of your use cases
Below Solution is for when you want the client to wait for their commands to be submitted to their host
You should send a message to your hosts to execute the commands (maybe through a REST API or anything else), and wait for these tasks to either be executed or to be submitted: this all depends on your use case.
Below Solution is for when you want to be able to queue your commands
You can submit tasks to the created Thread Pool which will execute your tasks in an FI-FO order.
Depending on your use case, you can either use 1 or multiple (not too many Threads as this may only degrade your overall performance) threads in your Thread Pool. These tasks will then be executed when picked from the queue.

Polling for a job status java

I'm looking for a way to check a job status over a period of time:
If during the polling I get a result that the job was completed, I return it, otherwise I keep polling until the period I set is over and return a failure result.
I know how to do this using a timer and a while loop.
Is there a better way of doing it?
Thanks in advance
Better way to pool for the result should be using CompletionService.
Since you are already using asynchronous way of communication, make your thread implement Callable and implement call method similar to what you would do in a run method.
Now when you use completion service and to your executor service just say submit. With completion Service you get a blocking queue on which as and when you get the result completion service will put the result onto Queue and you can then do whatever you want with the result.

detect canceled requests on server when using gwt-rpc

In the gwt client I can cancel a request by letting the method in the Async interface return a Request object which contains a cancel() method I can call.
So far so good, but is there a way to detect this in the java code running on the server?
My use-case is that I have a rpc call which take a long time to complete on the server, and where the user has a "cancel" button to stop the request.
And If the user cancel the request, the server should stop processing, but there seems to be no way to detect that the client have closed the connection.
It is usually not a good idea to use server's request threads for long running tasks. You need to redesign them to be executed asynchronously (if you still have not done it). You can utilize java.util.concurent tools like FutureTask and Executors to achieve this. You will also need to use thread pools to make sure to control a max number of concurrent tasks.
When you submit a request for a long task from the client, you need to return a reference key (e.g. UUID or some unique string) to your FutureTask as soon as you schedule it for execution. Then to cancel the task, you need pass the key from the client and look up you task and cancel it:
See javadoc for more details:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/FutureTask.html

What's the effect on a second request of calling Thread.currentThread().sleep(2000) in a Spring MVC request handler?

I need to wait for a condition in a Spring MVC request handler while I call a third party service to update some entities for a user.
The wait averages about 2 seconds.
I'm calling Thread.sleep to allow the remote call to complete and for the entities to be updated in the database:
Thread.currentThread().sleep(2000);
After this, I retrieve the updated models from the database and display the view.
However, what will be the effect on parallel requests that arrive for processing at this controller/request handler?
Will parallel requests also experience a wait?
Or will they be spawned off into separate threads and so not be affected by the delay experienced by the current request?
What are doing may work sometimes, but it is not a reliable solution.
The Java Future interface, along with a configured ExecutorService allows you to begin some operation and have one or more threads wait until the result is ready (or optionally until a certain amount of time has passed).
You can find documentation for it here:
http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html

Categories

Resources