Tuesday, 31 July 2018

scala.concurrent.Future leaks on timeouts.

Almost any business operation should have a reasonable deadline - if not completed before - it loses it value.
Imagine situation when we are building the service that should give a response in 500 milliseconds - if it's not ready we should return error.

Just to reduce the number of source code lines in example we will use Await.result - that allows to set the timeout for waiting.
If we define our heavy operation as:
We find out that despite service produces error on timeout - and we notify the users on that - we actually haven't canceled the heavy task itself. It keeps running despite the result isn't needed. Another simple example with akka-streams:
It's output is:
error: java.util.concurrent.TimeoutException: The stream has not been completed in 100 milliseconds.
I'm executed anyway

There is no way to get ride off resources leak except the changing the way how heavyOperation is working. For example if it's query to Cassandra - it should be regulated via timeouts, retry policy and other setting to limit the maximum execution time to expected duration.
Sometimes it's not that easy to predict and limit execution time as a result to avoid resource's leak. Akka streams proposes Back-pressure solution that actually isn't easy to apply for all the cases.
There is another way to cancel the jobs explicitly, for example Monix library implements Cancelable Of course cancelable is something that you have to manage explicitly - the way you would like the job to be cancelled. But the handling of timeouts is easy to use operation:

If we want to stop thread execution from our synthetic example we can use Task with cancelable behaviour:
- of course the real cancelation is sometimes hard to implement it correctly.
How do you handle the timeouts for long running tasks?

No comments:

Post a Comment