java : execute a method over a maximum period of time - java

I am using the JavaMail API , and there is a method in the Folder class called "search" that sometimes take too long to execute. What i want is to execute this method over a maximum period of time( say for example 15 seconds in maximum) , that way i am sure that this method will not run up more than 15 seconds.
Pseudo Code
messages = maximumMethod(Folder.search(),15);
Do I have to create a thread just to execute this method and in the main thread use the wait method ?

The best way to do this is create a single threaded executor which you can submit callables with. The return value is a Future<?> which you can get the results from. You can also say wait this long to get the results. Here is sample code:
ExecutorService service = Executors.newSingleThreadExecutor();
Future<Message[]> future = service.submit(new Callable<Message[]>() {
#Override
public Message[] call() throws Exception {
return Folder.search(/*...*/);
}
});
try {
Message[] messages = future.get(15, TimeUnit.SECONDS);
}
catch(TimeoutException e) {
// timeout
}

You could
mark current time
launch a thread that will search in the folder
while you get the result (still in thread) don't do anything if current time exceeds time obtained in 1 plus 15 seconds. You won't be able to stop the connection if it is pending but you could just disgard a late result.
Also, if you have access to the socket used to search the folder, you could set its timeout but I fear it's gonna be fully encapsulated by javamail.
Regards,
Stéphane

This SO question shows how to send a timeout exception to the client code: How do I call some blocking method with a timeout in Java?
You might be able to interrupt the actual search using Thread.interrupt(), but that depends on the method's implementation. You may end up completing the action only to discard the results.

Related

Mono/Flux: how to suspend thread and wait for event or timeout

I would like to ask advice how to solve with Mono/Flux suspending and reactivating by delay or timeout.
The task is: application will receive HTTP request and should provide response.
When request is received using async sockets message should be sent. And we need to wait for specific answer, but no more than 30 seconds.
So I need to suspend thread until some Runnable will be called, or other option is each 0.2 sec query some variable and if it set to relevant value continue the process.
Could you please give me some suggestions?
Thank you
I think you need to use the timeout method from Mono/Flux, to set that behaviour. Example:
yourMonoOrFlux.timeout(Duration.ofSeconds(30))
.onErrorResume(yourFallbackMethod)
... //some other chained operations
It's also possible to set a fallback method when something goes wrong, using the onErrorResume method.
But if you need to really block the thread within those 30 secs, you should use block method rather than timeout. Example:
yourMonoOrFlux.block(Duration.ofSeconds(30))
... //other chained operations
Reference on the official reactor documentation
Finally I found the solution.
Maybe not most elegant but works, using recursion
This code querying variable state to get positive response, but not more than 10 seconds timeout.
val delayDuration = Duration.ofMillis(200)
val maximumAttempts = 50
fun createDelayedMono(counter : Int) : Mono<BigInteger> {
val mono = Mono.delay(delayDuration).flatMap {
it ->
if (counter < maximumAttempts && reactorHelper.isEventCompleted(rrn)) {
reactorHelper.removeEvent(rrn)
return#flatMap Mono.just(BigInteger.ZERO)
} else {
return#flatMap createDelayedMono(counter + 1)
}
}
return mono
}

How do I complete numerous jobs with a few threads giving each the same timeout to complete?

An idea I am trying to implement is the following.
I have 1000 urls to download data from to use it for post processing (say, calculating some statistics).
I don't really need all of the downloads to finish successfully, but as many as possible.
I assume that some of the locations might be unavailable, either responding nothing valuable (e.g., HTTP 503) or taking more that TO=10 seconds of time to process a request.
I have T=5 threads to process the urls in parallel, giving the equal timeout TO to each.
As soon as one completes (what I expect to happen far earlier that TO exceeds) I aggregate some statistics (what is a very fast operation) and start the next download (if any).
The solution I have come up so far with is
ExecutorService executorService = Executors.newFixedThreadPool(T);
ExecutorCompletionService<MyResult> completionService = new ExecutorCompletionService<>(executorService);
urls.forEach(url -> {
Callable<MyResult> callable = () -> new MyResult(url);
completionService.submit(callable);
});
for (int i = 0; i < urls.size(); i++) {
Future<MyResult> resultFuture = completionService.poll(TO, TimeUnit.SECONDS);
if (resultFuture == null)
continue;
MyResult myResult = resultFuture.get();
myAggregate(myResult.getRate());
}
It looks like somewhat I am trying to achieve. But it for instance neither gives every download the same timeout nor cancels the Futures properly. So, what is the correct solution?
Try using the invokeAll-Method, you simply put your Callables in a List and then call invokeAll() on your ExecutorService giving it a timeout as second and third argument.
executorService.invokeAll(callableList, 20, TimeUnit.SECONDS);

How to interrupt a function call in Java

I am trying to use a Third Party Internal Library which is processing a given request. Unfortunately it is synchronous in nature. Also I have no control on the code for the same. Basically it is a function call. This function seems to a bit erratic in behavior. Sometimes this function takes 10 ms to complete processing and sometimes it takes up to 300 secs to process the request.
Can you suggest me a way to write a wrapper around this function so that it would throw an interrupted exception if the function does not complete processing with x ms/secs. I can live with not having the results and continue processing, but cannot tolerate a 3 min delay.
PS: This function internally sends an update to another system using JMS and waits for that system to respond and sends apart from some other calculations.
Can you suggest me a way to write a wrapper around this function so that it would throw an interrupted exception if the function does not complete processing with x ms/secs.
This is not possible. InterruptException only gets thrown by specific methods. You can certainly call thread.stop() but this is deprecated and not recommended for a number of reasons.
A better alternative would be for your code to wait for the response for a certain amount of time and just abandon the call if doesn't work. For example, you could submit a Callable to a thread pool that actually makes the call to the "Third Party Internal Library". Then your main code would do a future.get(...) with a specific timeout.
// allows 5 JMS calls concurrently, change as necessary or used newCachedThreadPool()
ExecutorService threadPool = Executors.newFixedThreadPool(5);
...
// submit the call to be made in the background by thread-pool
Future<Response> future = threadPool.submit(new Callable<Response>() {
public Response call() {
// this damn call can take 3 to 3000ms to complete dammit
return thirdPartyInternalLibrary.makeJmsRequest();
}
});
// wait for some max amount of time
Response response = null;
try {
response = future.get(TimeUnit.MILLISECONDS, 100);
} catch (TimeoutException te) {
// log that it timed out and continue or throw an exception
}
The problem with this method is that you might spawn a whole bunch of threads waiting for the library to respond to the remote JMS query that you would not have a lot of control over.
No easy solution.
This will throw a TimeoutException if the lambda doesn't finish in the time allotted:
CompletableFuture.supplyAsync(() -> yourCall()).get(1, TimeUnit.SECONDS)
Being that this is 3rd party you cannot modify the code. As such you will need to do two things
Launch the execution in a new thread.
Wait for execution in current thread, with timeout.
One possible way would be to use a Semaphore.
final Semaphore semaphore = new Semaphore(0);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
// do work
semaphore.release();
}
});
t.start();
try {
semaphore.tryAcquire(1, TimeUnit.SECONDS); // Whatever your timeout is
} catch (InterruptedException e) {
// handle cleanup
}
The above method is gross, I would suggest instead updateing your desing to use a dedicated worker queue or RxJava with a timeout if possible.

How to use FallbackFuture to handle TimeoutException?

I have my task and fallback for it:
ListenableFuture<T> listenableAsyncTask = executorService.submit(asyncTaskCallable);
ListenableFuture<T> listenableFallbackTask = executorService.submit(fallBackTaskCallable);
From them, I form a fail tolerant ListenableFuture:
ListenableFuture<T> failTolerantListenableFuture = Futures.withFallback(listenableAsyncTask, new FutureFallback<T>() {
#Override
public ListenableFuture<T> create(Throwable t) throws Exception {
return listenableFallbackTask;
}
});
And I have a list of fail tolerant futures:
List<ListenableFuture<T>> listenableFutures = ...;
It's time to get the result, in a certain amount of time:
result = Futures.allAsList(listenableFutures).get(50,TimeUnit.MILLISECONDS);
At this point, I expect that if a task failed to finish within 50ms, the return output will be handled by the fallBackTask, which is a lightweight one.
But not as I planed, I got the following exception:
java.util.concurrent.TimeoutException: Timeout waiting for task.
Which causes me losing all results from other succeed tasks. It seems that the fallback didn't work in this case for me. Or I misunderstood the concept?
We need to distinguish between "the Future fails" and "the call to Future.get fails."
"The Future fails" if the task you submitted throws an exception. (For purposes of withFallback, we also consider cancellation to be a failure. That's not relevant here, though, and the behavior may change someday.)
"The call to Future.get fails" if any of the following happen:
the Future fails
the call times out
the call is interrupted
withFallback handles only the case in which the Future fails, without handling cases of timeout or interruption.
If your goal is to retrieve all the primary results that are done within 50 milliseconds, with all other cases falling back to the secondary results, you can try something like this, which uses withTimeout to automatically fail the Future after a given timeout:
List<ListenableFuture<T>> originalFutures = ...;
List<ListenableFuture<T>> defaultAfterTimeoutFutures = new ArrayList<>();
for (ListenableFuture<T> f : originalFutures) {
f = Futures.withTimeout(f, 50, MILLISECONDS, executor);
f = Futures.withFallback(f, ...);
defaultAfterTimeoutFutures.add(f);
}
result = Futures.allAsList(defaultAfterTimeoutFutures).get();
But note that that last get call may wait longer than 50 milliseconds: If a primary Future fails, then the get call must wait until its fallback is done. If you don't want to wait for the fallbacks, then you will need to wrap them with withTimeout, as well. And if you do wrap them, then they will fail after the timeout, at which point allAsList will also fail. If you don't want that, then you'll need to either use successfulAsList (instead of allAsList) or wrap the wrappers with withFallback again, this time with a value that is always available immediately.

Embeded Jetty, kill Request after a given time

I run a jar with an embedded Jetty. From time to time it happens that one request get stuck in some endless loop. Obviously fixing the endless-loop would be the best option. However, this is currently not possible.
So I am looking for an option, that checks if a request exists for more than e.g. 5 minutes, and kills the corresponding thread.
I tried the typical Jetty options:
maxIdleTime
soLingerTime
stopTimeout
None of them worked as expected. Is there another option to consider?
Do you access to the code that kicks of the code which takes too long to complete? If so you can use callable and an Executor to achieve this yourself, below is a unit test with an example:
#Test
public void timerTest() throws Exception
{
//create an executor
ExecutorService executor = Executors.newFixedThreadPool(10);
//some code to run
Callable callable = () -> {
Thread.sleep(10000); //sleep for 10 seconds
return 123;
};
//run the callable code
Future<Integer> future = (Future<Integer>) executor.submit(callable);
Integer value = future.get(5000, TimeUnit.MILLISECONDS); //this will timeout after 5 seconds
//kill the thread
future.cancel(true);
}

Categories

Resources