How to stop execution of CompletableFuture after timeout? - asynchronous

I have a use case where CompletableFuture is running in a separate thread pool. We use Java8, so I have implemented a timeout mechanism using ScheduledExecutorService.
CompletableFuture<Void> cf = CompletableFuture.runAsync(() -> {
// run some code asynchronously
}, executorService);
Below is the timeout mechanism I used, reference:
final CompletableFuture<Void> responseFuture = within(cf, Duration.ofSeconds(3));
responseFuture
        .thenAccept(s -> log.info("Completed Asynchronous Processing"))
        .exceptionally(throwable -> {
            log.error("Unrecoverable error", throwable);
            return null;
        });
public CompletableFuture<Void> within(CompletableFuture<Void> future, Duration duration) {
    final CompletableFuture<Void> timeout = failAfter(duration);
    return future.applyToEither(timeout, Function.identity());
}
public CompletableFuture<Void> failAfter(Duration duration) {
    final CompletableFuture<Void> promise = new CompletableFuture<>();
    scheduler.schedule(() -> {
        final TimeoutException ex = new TimeoutException("Timeout after " + duration);
        return promise.completeExceptionally(ex);
    }, duration.toMillis(), MILLISECONDS);
    return promise;
}
I am manually testing the TimeOutException by adding Thread.sleep() - After the timeout takes place, it goes in the exceptionally block and logs the error but continues the execution. I want the cf which is running in the executorService to stop processing after timeout.
My understanding is that, since cf is running in a separate threadpool it is not aware of the TimeOutException and hence continues processing. How do I achieve this? Am I approaching this right?

Related

Does HttpGet, HttpPost abort() method aborts the request even if it is taking more time to establish the connection

I have a scenario where in certain cases request need to be terminated based on alternate configuration. From https://www.baeldung.com/httpclient-timeout I understood that we can set hard time out. However not sure how to test this.
Does the below code aborts the request with in given time even if there is a scenario of connection or socket or read timeout
HttpGet getMethod = new HttpGet(
"http://localhost:8080/httpclient-simple/api/bars/1");
int hardTimeout = 5; // seconds
TimerTask task = new TimerTask() {
#Override
public void run() {
if (getMethod != null) {
getMethod.abort();
}
}
};
new Timer(true).schedule(task, hardTimeout * 1000);
HttpResponse response = httpClient.execute(getMethod);
For instance if connection time out is set to 10 seconds and it is taking more than 10 seconds then does it terminate in 5 seconds. Similarly for other timeout scenarios.
If Apache httpclient library does not support this, is there an alternative?
Thanks in advance.
Look here for setting connection and read timeouts with apache http client.

.Net Core SignalR: how to persist connections

I have an infinitely running process that pushes events from a server to subscribed SignalR clients. There may be long periods where no events take place on the server.
Currently, the process all works fine -- for a short period of time-- but eventually, the client stops responding to events pushed by the server. I can see the events taking place on the server-side, but the client becomes unaware of the event. I am assuming this symptom means some timeout period has been reached and the client has unsubscribed from the Hub.
I added some code to reconnect if the connection was dropped, and that has helped, but the client still eventually stops seeing new events. I know there are many different timeout values that can be adjusted, but it's all pretty confusing to me and not sure if I should even be tinkering with them.
try
{
myHubConnection = new HubConnectionBuilder()
.WithUrl(hubURL, HttpTransportType.WebSockets)
.AddMessagePackProtocol()
.AddJsonProtocol(options =>
{
options.PayloadSerializerSettings.ContractResolver = new DefaultContractResolver();
})
.Build();
// Client method that can be called by server
myHubConnection.On<string>("ReceiveInfo", json =>
{
// Action performed when method called by server
pub.ShowInfo(json);
});
try
{
// connect to Hub
await myHubConnection.StartAsync();
msg = "Connected to Hub";
}
catch (Exception ex)
{
appLog.WriteError(ex.Message);
msg = "Error: " + ex.Message;
}
// Reconnect lost Hub connection
myHubConnection.Closed += async (error) =>
{
try
{
await Task.Delay(new Random().Next(0, 5) * 1000);
await myHubConnection.StartAsync();
msg = "Reconnected to Hub";
appLog.WriteWarning(msg);
}
catch (Exception ex)
{
appLog.WriteError(ex.Message);
msg = "Error: " + ex.Message;
}
};
This all works as expected for a while, then stops without errors. Is there something I can do to (1) ensure the client NEVER unsubscribes, and (2) if the connection is lost (network outage for example) ensures the client resubscribes to the events. This client must NEVER timeout or give up trying to reconnect if required.

IgniteMesssaging works in sync mode

It seems that Ignite(2.0) Messaging's send function works in sync mode, it will be blocked be the listener. And below is my testing code.
ignite.message().localListen("TEST", (nodeId, Msg) -> {
try {
Thread.sleep(500);
} catch (Exception ex) {
}
return true;
});
for (int i = 0; i < 100; i++) {
ignite.message().send("TEST", "Hello World");
}
It cost about 50 seconds to send 100 messages, and it is almost equals the sleep time 500 ms * 100. seems the send function in sync mode not in async mode.
Does anybody know how to change the send function in async mode?
Thanks in advance.
Seems async listener invocation was missed while adding new API, but you still have two options:
Use deprecated withAsync(), unless sendAsync() will be added.
Pass your own Executor in predicate, if you always return true, for example.
I've just opened a ticket for that IGNITE-5570
It seems that you're testing within one node. In this case there is no message sent and listener is invoked synchronously. Network communication is asynchronous in Ignite, so if you do the testing on two nodes, you should not see such behavior.

async / await: If it doen't use threads what is it doing to running processing at the same time?

I am doing a little research to understand async / await of C# better.
I found a web site that has the following code to show how much slower synchronous processing is vs async / await:
public IActionResult Index()
{
Stopwatch watch = new Stopwatch();
watch.Start();
ContentManagement service = new ContentManagement();
var content = service.GetContent();
var count = service.GetCount();
var name = service.GetName();
watch.Stop();
ViewBag.WatchMilliseconds = watch.ElapsedMilliseconds;
return View();
}
[HttpGet]
public async Task<ActionResult> IndexAsync()
{
Stopwatch watch = new Stopwatch();
watch.Start();
ContentManagement service = new ContentManagement();
var contentTask = service.GetContentAsync();
var countTask = service.GetCountAsync();
var nameTask = service.GetNameAsync();
var content = await contentTask;
var count = await countTask;
var name = await nameTask;
watch.Stop();
ViewBag.WatchMilliseconds = watch.ElapsedMilliseconds;
return View("Index");
}
public class ContentManagement
{
public string GetContent()
{
Thread.Sleep(2000);
return "content";
}
public int GetCount()
{
Thread.Sleep(5000);
return 4;
}
public string GetName()
{
Thread.Sleep(3000);
return "Matthew";
}
public async Task<string> GetContentAsync()
{
await Task.Delay(2000);
return "content";
}
public async Task<int> GetCountAsync()
{
await Task.Delay(5000);
return 4;
}
public async Task<string> GetNameAsync()
{
await Task.Delay(3000);
return "Matthew";
}
}
I understand the above code at a high level and why it performs faster.
What I don't understand is if threads are not being used, how is the processing running at the same time?
I have read in a couple of places that async / await does not create new threads to do the processing. So, what is async / await doing to allow processing to happen at the same time? The three await Task.Delay are running in parallel, correct? If it is not creating 3 threads, what is it doing?
I just want to understand what is happening at a high level.
Let me know.
Thanks in advance.
if threads are not being used, how is the processing running at the same time?
Threads let you parallelize computations on the same system. When communications or other I/O are involved, there is a different system with which your code communicates. When you initiate the task, the other system starts doing work. This happens in parallel to your system, which is free to do whatever else it needs to do until you await the task.
The three await Task.Delay are running in parallel, correct?
They are not exactly running, they are sleeping in parallel. Sleeping takes very little resources. That's why they appear to be "running" in parallel.
What I don't understand is if threads are not being used, how is the processing running at the same time?
You can think of it as an event firing when the operation is complete, as opposed to a thread being blocked until the operation is complete.
I have read in a couple of places that async / await does not create new threads to do the processing.
async and await do not; that is true. For more about how async and await work, see my intro post.
So, what is async / await doing to allow processing to happen at the same time?
One of the primary use cases of async/await is for I/O-based code. I have a long blog post that goes into the details of how asynchronous I/O does not require threads.
The three await Task.Delay are running in parallel, correct?
I prefer to use the term "concurrently", just to avoid confusion with Parallel and Parallel LINQ, both of which were created for CPU-bound parallelism and do not work as generally expected with async/await. So, I would say that both parallelism and asynchrony are forms of concurrency, and this is an example of asynchronous concurrency.
(That said, using the term "parallel" is certainly in concord with the common usage of the term).
If it is not creating 3 threads, what is it doing?
Task.Delay is not an I/O-based operation, but it is very similar to one. It uses timers underneath, so it's completely different than Thread.Sleep.
Thread.Sleep will block a thread - I believe it does go all the way to an OS Sleep call, which causes the OS to place the thread in a wait state until its sleep time is expired.
Task.Delay acts more like an I/O operation. So, it sets up a timer that fires off an event when the time expires. Timers are managed by the OS itself - as time proceeds forward (clock ticks on the CPU), the OS will notify the timer when it has completed. It's a bit more complex than that (for efficiency, .NET will coalesce managed timers), but that's the general idea.
So, the point is that there is no dedicated thread for each Task.Delay that is blocked.

JAX-WS client ASYNC service invocation using WLS 10.3.3

I am writing an integration webservice which will consume various webservices from a couple different backend systems. I want to be able to parallelize non-dependent service calls and be able to cancel requests that take too long (since I have an SLA to meet).
to aid in parallel backend calls, I am using the ASYNC client apis (generated by wsimport using the client-side jax-ws binding alteration files)
the issue I am having is that when I try to cancel a request, the Response<> appropriately marks the request as canceled, however the actual request is not really canceled. apparently some part of the JAX-WS runtime actually submits a com.sun.xml.ws.api.pipe.Fiber to the run queue which is what actually does the request. the cancel on the Result<> does not prevent these PIPEs from running on the queue and making the request.
has anyone run into this issue or a similar issue before?
My code looks like this:
List<Response<QuerySubscriberResponse>> resps = new ArrayList<Response<QuerySubscriberResponse>>();
for (int i = 0; i < 10; i++) {
resps.add(FPPort.querySubscriberAsync(req));
}
for (int i = 0; i < 10; i++) {
logger.info("Waiting for " + i);
try {
QuerySubscriberResponse re = resps.get(i).get(1,
TimeUnit.SECONDS); // execution time for this request is 15 seconds, so we should always get a TimeoutException
logger.info("Got: "
+ new Marshaller().marshalDocumentToString(re));
} catch (TimeoutException e) {
logger.error(e);
logger.error("Cancelled: " + resps.get(i).cancel(true));
try {
logger.info("Waiting for my timed out thing to finish -- technically I've canceled it");
QuerySubscriberResponse re = resps.get(i).get(); // this causes a CancelledExceptio as we would expect
logger.info("Finished waiting for the canceled req");
} catch (Exception e1) {
e1.printStackTrace();
}
} catch (Exception e) {
logger.error(e);
} finally {
logger.info("");
logger.info("");
}
}
I would expect that all of these requests would end up being cancelled, however in reality they all continue to execute and only return when the backend finally decides to send us a response.
as it turns out this was indeed a bug in the jax-ws implementation. Oracle has issued a Patch (RHEL) against wls 10.3.3 to address this issue.

Resources