Best practice to make cleanup after Scala Future is complete - scala

I want to make some cleanup (like close db connection) after a Future is complete.
Currently I achieve it this way:
Future { ... } onComplete {
case Success(v) =>
// ...
conn.close()
case Failure(ex) =>
// ...
conn.close()
}
There's duplicate code and it's also tedious.
Is there any best practice to this?

Since the same action conn.close() is performed on both success and failure, consider executing it as a side-effect using andThen like so
Future { ... } andThen { _ => conn.close() }
Similarly, using onComplete we could do
Future { ... } onComplete { _ => conn.close() }
The difference between andThen and onComplete is that latter will return Unit, that is, discard the returned value of the Future.

The sad truth is that Scala Futures don't have this basic feature built in. I would therefore strongly suggest using a modern effect system like ZIO or cats-effect, both of which solve this problem and a myriad of others that Futures have. The easiest way to do what you want is to use the bracket method:
https://zio.dev/docs/overview/overview_handling_resources
Now bracket works great, but there's a way that usually works even better: the Managed type. It's virtually impossible to write code that leaks resources if you consistently use Managed when acquiring resources:
https://zio.dev/docs/datatypes/datatypes_managed
That said,if you absolutely must use Futures, you'll have to write your own try-finally equivalent. Or you can use mine:
def tryFinally[A](tryy: => Future[A])(finallyy: => Future[Any])(
implicit ec: ExecutionContext): Future[A] =
Future.fromTry(Try(tryy)).flatten.transformWith { t =>
finallyy.flatMap((_: Any) => Future.fromTry(t))
}

I like to use map, you can do something like this:
val mapped: Future[String] = future.map(_ => "OK").recover{case _ => "KO"}

Related

How to unwrap a Future[Either[Throwable,T ]] to Either[Throwable,T]

I have a function(myFunc) in scala that gives Future[Either[Throwable,T ]] . Now I need to unwrap and get Either[Throwable,T ] out of it and pass to as an input parameter to another function (anotherFunc).
def myFunc(input: String): Future[Either[Throwable, HttpResponse]] = {
....
}
def anotherFunc(response: Either[Throwable, T]) # signature
anotherFunc(myFunc("some string"))
Normally we use map to transform a Future but thats not helping me here
myFunc("some string").map { _ =>
anotherFunc(_)
}
This causes problem with the return of the block from where I am calling .
You can't unwrap the value of a Future because a Future represents the result of an asynchronous computation that may or may not be available yet. By default, futures and non-blocking, encouraging the use of callbacks instead of typical blocking operations.
What you can do is either:
use combinators such as map, flatMap, filter to compose futures in a non-blocking way.
register a callback using the onComplete method, or foreach if you want to call a callback only when the Future completes successfully.
block the main thread using Await.result, if this is absolutely necessary, although is discouraged. If you want to transform the Future result or combine it with others, you should opt for the 2 previos non-blocking ways mentioned.
That being said. These are the preferred approaches:
def anotherFunc[T](response: Future[Either[Throwable, T]]) = {
response.onComplete {
case Failure(exception) => // process exception
case Success(value) => // process value
}
}
def anotherFunc2[T](response: Future[Either[Throwable, T]]) = {
response.map {
case Left(exception) => // process exception
case Right(value) => // process value
}
}
Then you can do:
anotherFunc(myFunc("some string"))
anotherFunc2(myFunc("some string"))
EDIT:
If you can't change the signature of anotherFunc[T](response: Either[Throwable, T]) then just do:
myFunc("some string").map(anotherFunc)

Convert a scala.util.Try to a scala.concurrent.Future

I started migrating my Scala 2.11 code base to Scala 2.12. In my application I had a method that looked like this:
Future {
someMethodReturningTry()
} onSuccess {
case Success(result) => processResult()
case Failure(reason) => log.error(s"Couldn't do it: ${reason.getMessage}")
}
Now, if you compile this with Scala 2.12, you'll get:
method onSuccess in trait Future is deprecated (since 2.12.0): use foreach or onComplete instead (keep in mind that they take total rather than partial functions)
So I started exploring how I could solve this in an elegant way.
The someMethodReturningTry() method really should return a Try[], since it involves parsing some text structure and that might fail, so I prefer to keep the return type for that method the same.
The best I could think of is
Future {
someMethodReturningTry()
} flatMap {
case Success(result) => Future.successful(result)
case Failure(reason) => Future.failed(reason)
} onComplete {
case Success(result) => processResult()
case Failure(reason) => log.error(s"Couldn't do it: ${reason.getMessage}")
}
But that feels a bit redundant: creating a Future just to model the fact that something in the future (which already is captured inside a Future) went well.
This approach creates an extra Future which I hope to get rid of, but I can't figure out how. Any suggestions?
It's not clear to me why you don't just...
Future {
someMethodReturningTry() match {
case Success(result) => processResult(result)
case Failure(reason) => log.error(s"Couldn't do it: ${reason.getMessage}")
}
}
You're free to handle, or ignore, the Future failure separately.
You could adjust your pattern matching in the following way:
Future {
someMethodReturningTry()
} onComplete {
case Success(Success(result)) => processResult()
case Success(Failure(reason)) => log.error(s"Couldn't do it: ${reason.getMessage}")
case Failure(reason) =>
log.error(s"The future failed: ${reason.getMessage}")
// or do nothing
}
Note that the onSuccess callback is executed only if the Future succeeds, so your original code didn't do anything if the Future contained an exception. If that is your intent, you can leave the case Failure(reason) => clause above blank (but it's probably more helpful to retain the error logging as shown).

Idiomatic way to handle side effect and return value in Scala functions

How would you construct a function in which you both want to do a side effect and return a value?
For example I would like the following function:
def futureFromHttpCall: Future[HttpResponse] =
doHttpCall.foreach(publishDomainEvent).returnOriginalFuture
(somehow I have a feeling that monads will come up so if that is the path Im somewhat familiar with cats if there is a solution for this problem there?)
The simplest thing I can think of is instead of "hiding" the side effect inside the Future[T] returning method, expose it as a continuation on the future:
def futureFromHttpCall: Future[HttpResponse] = doHttpCall
And then you could either onComplete on it as a side effect:
futureFromHttpCall.onComplete {
case Success(_) => publishDomainEvent
case Failure(e) => // Stuff
}
Making the effect explicit. Or if you're inside an actor system, you can can pipeTo the Future to your receive method and handle success / failure there.
I think your Future should only complete when all of your domain events are pushed. They should be a Future as well. Then you can use Future.sequence to wait for all of them to complete before returning.
Your question is a little unclear but i assume doHttpCall is a list of some type.
def doHttpCall(): Future[Seq[X]] = ???
def publishDomainEvent(x:X): Future[Unit] = ???
def futureFromHttpCall(): Future[Seq[X]] = {
val firstFuture = ???
firstFuture.flatMap { xs =>
val xxs: Seq[Future[Unit]]= xs.map(publishDomainEvent)
Future.sequence(xxs).map { _ => re }
}
}
All of this waiting can be pretty helpful when testing.

Jedis in scala and handling errors

I am trying to find the best way to handle jedis commands from scala. I am trying to implement a finally block, and prevent the java exceptions from bubbling up to my caller.
Does the following code make sense, and is it the best I can do performance wise, if I want to ensure that I handle exceptions when redis may be down temporarily? This trait would be extended by an object, and I'd call objectname.del(key). I feel like I'm combining too many concepts (Either, Option, Try, feels like there should be a cleaner way)
trait MyExperiment {
implicit class TryOps[T](val t: Try[T]) {
def eventually[Ignore](effect: => Ignore): Try[T] = {
val ignoring = (_: Any) => { effect; t }
t transform (ignoring, ignoring)
}
}
val jpool:JedisPool = initialize()
// init the pool at object creation
private def initialize(): JedisPool =
{
val poolConfig = new JedisPoolConfig()
poolConfig.setMaxIdle(10)
poolConfig.setMinIdle(2)
poolConfig.setTestWhileIdle(true)
poolConfig.setTestOnBorrow(true)
poolConfig.setTestOnReturn(true)
poolConfig.setNumTestsPerEvictionRun(10)
new JedisPool( poolConfig , "localhost" )
}
// get a resource from pool. This can throw an error if redis is
// down
def getFromPool: Either[Throwable,Jedis] =
Try(jpool.getResource) match {
case Failure(m) => Left(m)
case Success(m) => Right(m)
}
// return an object to pool
// i believe this may also throw an error if redis is down?
def returnToPool(cache:Jedis): Unit =
Try(jpool.returnResource(cache))
// execute a command -- "del" in this case, (wrapped by
// the two methods above)
def del(key: String) : Option[Long] = {
getFromPool match {
case Left(m) => None
case Right(m) => Try(m.del(key)) eventually returnToPool(m) match {
case Success(r) => Option(r)
case Failure(r) => None
}
}
}
}
Not an exact answer, but I moved on after doing some performance testing. Using the standard java-ish exception blocks ended up being much faster at high iterations (at 10,000 iterations, it was about 2.5x faster than the (bad) code above). That also cleaned up my code, although it's more verbose.
So the answer I arrived at is to use the Java-style exception blocks which provide for the finally construct. I believe it should be significantly faster, as long as exceptions are a very rare occurance.

In scala how to wrap a PartialFunction?

In scala, Futures have a sort of rescue function that takes a PartialFunction. This code is skipped if the Future resolved with a response but is called if a failure occurs.
I want to simple wrap the partial function in a proxy that always executes code that writes to a stat counter. At first I was thinking I would just create another PartialFunction but soon realized that does not work very well with the isDefined, then apply as I really want this to be called every time.
How do I go about proxying the PartialFunction such that my code is always called when the Future has an exception?
To summarize the comments: You can use the onFailure callback to execute some side-effecting code (logging) when a Future fails.
val future = Future(1 / 0)
future.onFailure {
case _ => println("I have seen the Future, and it doesn't look good.")
}
As #cmbaxter notes, you could also use andThen on the Future, which accepts a PartialFunction[Try[A], B] and returns the original Future. So you could apply the side-effecting function using andThen, and than recover afterwards. You could even chain them multiple times.
Future(1 / 0)
.andThen { case Failure(_) => println("Future failed.") }
.recover { case e: ArithmeticException => 0 }
.andThen { case Failure(_) => println("Tried to recover, and still failed.") }
Or a helper that always includes it:
object FutureLogger {
def apply[A](a: => A): Future[A] = Future(a).andThen {
case Failure(_) => println("FAILURE")
}
}