Map a Future for both Success and Failure - scala

I have a Future[T] and I want to map the result, on both success and failure.
Eg, something like
val future = ... // Future[T]
val mapped = future.mapAll {
case Success(a) => "OK"
case Failure(e) => "KO"
}
If I use map or flatmap, it will only map successes futures. If I use recover, it will only map failed futures. onComplete executes a callback but does not return a modified future. Transform will work, but takes 2 functions rather than a partial function, so is a bit uglier.
I know I could make a new Promise, and complete that with onComplete or onSuccess/onFailure, but I was hoping there was something I was missing that would allow me to do the above with a single PF.

Edit 2017-09-18: As of Scala 2.12, there is a transform method that takes a Try[T] => Try[S]. So you can write
val future = ... // Future[T]
val mapped = future.transform {
case Success(_) => Success("OK")
case Failure(_) => Success("KO")
}
For 2.11.x, the below still applies:
AFAIK, you can't do this directly with a single PF. And transform transforms Throwable => Throwable, so that won't help you either. The closest you can get out of the box:
val mapped: Future[String] = future.map(_ => "OK").recover{case _ => "KO"}
That said, implementing your mapAll is trivial:
implicit class RichFuture[T](f: Future[T]) {
def mapAll[U](pf: PartialFunction[Try[T], U]): Future[U] = {
val p = Promise[U]()
f.onComplete(r => p.complete(Try(pf(r))))
p.future
}
}

Since Scala 2.12 you can use transform to map both cases:
future.transform {
case Success(_) => Try("OK")
case Failure(_) => Try("KO")
}
You also have transformWith if you prefer to use a Future instead of a Try. Check the documentation for details.

In a first step, you could do something like:
import scala.util.{Try,Success,Failure}
val g = future.map( Success(_):Try[T] ).recover{
case t => Failure(t)
}.map {
case Success(s) => ...
case Failure(t) => ...
}
where T is the type of the future result. Then you can use an implicit conversion to add this structure the Future trait as a new method:
implicit class MyRichFuture[T]( fut: Future[T] ) {
def mapAll[U]( f: PartialFunction[Try[T],U] )( implicit ec: ExecutionContext ): Future[U] =
fut.map( Success(_):Try[T] ).recover{
case t => Failure(t)
}.map( f )
}
which implements the syntax your are looking for:
val future = Future{ 2 / 0 }
future.mapAll {
case Success(i) => i + 0.5
case Failure(_) => 0.0
}

Both map and flatMap variants:
implicit class FutureExtensions[T](f: Future[T]) {
def mapAll[Target](m: Try[T] => Target)(implicit ec: ExecutionContext): Future[Target] = {
val promise = Promise[Target]()
f.onComplete { r => promise success m(r) }(ec)
promise.future
}
def flatMapAll[Target](m: Try[T] => Future[Target])(implicit ec: ExecutionContext): Future[Target] = {
val promise = Promise[Target]()
f.onComplete { r => m(r).onComplete { z => promise complete z }(ec) }(ec)
promise.future
}
}

Related

Why are Futures in scala realised using a collection in the companion object?

I'm not sure whether I chose the right title for my question..
I'm interested as to why the collection in the companion object is defined. Am I mistaken that this collection will have only one f in it? What I am seeing is a collection with exactly one element.
Here's the Future I'm dealing with:
trait Future[+T] { self =>
def onComplete(callback: Try[T] => Unit): Unit
def map[U](f: T => U) = new Future[U] {
def onComplete(callback: Try[U] => Unit) =
self onComplete (t => callback(t.map(f)))
}
def flatMap[U](f: T => Future[U]) = new Future[U] {
def onComplete(callback: Try[U] => Unit) =
self onComplete { _.map(f) match {
case Success(fu) => fu.onComplete(callback)
case Failure(e) => callback(Failure(e))
} }
}
def filter(p: T => Boolean) =
map { t => if (!p(t)) throw new NoSuchElementException; t }
}
Its companion object:
object Future {
def apply[T](f: => T) = {
val handlers = collection.mutable.Buffer.empty[Try[T] => Unit]
var result: Option[Try[T]] = None
val runnable = new Runnable {
def run = {
val r = Try(f)
handlers.synchronized {
result = Some(r)
handlers.foreach(_(r))
}
}
}
(new Thread(runnable)).start()
new Future[T] {
def onComplete(f: Try[T] => Unit) = handlers.synchronized {
result match {
case None => handlers += f
case Some(r) => f(r)
}
}
}
}
}
In my head I was imagining something like the following instead of the above companion object (notice how I replaced the above val handlers .. with var handler ..):
object Future {
def apply[T](f: => T) = {
var handler: Option[Try[T] => Unit] = None
var result: Option[Try[T]] = None
val runnable = new Runnable {
val execute_when_ready: Try[T] => Unit = r => handler match {
case None => execute_when_ready(r)
case Some(f) => f(r)
}
def run = {
val r = Try(f)
handler.synchronized {
result = Some(r)
execute_when_ready(r)
}
}
}
(new Thread(runnable)).start()
new Future[T] {
def onComplete(f: Try[T] => Unit) = handler.synchronized {
result match {
case None => handler = Some(f)
case Some(r) => f(r)
}
}
}
}
}
So why does the function execute_when_ready leads to stackoverflow, but that's not the case with handlers.foreach? what is the collection is offering me which I can't do without it? And is it possible to replace the collection with something else in the companion object?
The collection is not in the companion object, it is in the apply method, so there is a new instance for each Future. It is there because there can be multiple pending onComplete handlers on the same Future.
Your implementation only allows a single handler and silently removes any existing handler in onComplete which is a bad idea because the caller has no idea if a previous function has added an onComplete handler or not.
As noted in the comments, the stack overflow is because execute_when_ready calls itself if handler is None with no mechanism to stop the recursion.

Scala: Chain multiple functions with Try[T] as the return type

I am new to functional programming in Scala and am working on a module where each operators (class instance/object) are chained together. The operators has only one function and that returns a Try[T]. I'm looking for a more readable way of chaining them together.
trait Mapper {
def map(in: T): Try[T]
}
trait Reducer {
def reduce(in: T): Try[T]
}
trait Grouper {
def group(in: T, batchSize: int): Try[T]
}
Lets just say I have created the implementations for these traits. Now in my main function, I can do something like
object MyApp extends App {
val mapper: Mapper = ...
val reducer: Reducer = ...
val grouper: Grouper = ...
def run(): Try[Unit] = {
val inp: T = ...
mapper.map(inp) match {
case Success(x) => reducer.reduce(x) match {
case Success(y) => grouper.group(x) match {
case Success(z) => ..// some other function call
case Failure(e) => throw e
}
case Failure(e) => throw e
}
case Failure(e) => throw e
}
}
run()
}
Is there a way, I can avoid all these Success, Failure pattern matching and do it in a better way?
Simple and typical for-comprehension is the case:
def run(): Try[Unit] = {
val inp: T = ...
for {
mapResult <- mapper.map(inp)
reduceresult <- reducer.reduce(mapResult)
groupResult <- grouper.group(x)
} yield ()
}
You can find lot's of learning materials about this topic in internet, but essentially this is syntax sugar over flatMap, map, withFilter and foreach for cases like yours.

Link Multiple Either's

Consider the scenario
trait Checker {
def check()(implicit ec: ExecutionContext): Future[Either[String, Unit]]
}
This trait is implemented by various class's.
Lets say
class CheckerImpl1 extends Checker {
override def check()(implicit ec: ExecutionContext): Future[Either[String, Unit]] = ???
}
class CheckerImpl2 extends Checker {
override def check()(implicit ec: ExecutionContext): Future[Either[String, Unit]] = ???
}
Now, I need to define a new function that will call check() function for each of these implementation classes in sequence(sequence does not matter) and return a new either i.e. Future[Either[String, Unit]] where String here is concatenated string of left for the check() implementation result.
So if CheckerImpl1.check() returns Left("error1") and CheckerImpl2.check() returns Left("error2") then result of the new function will return Left("error1&error2") (& just separate two strings).
OR
So if CheckerImpl1.check() returns Right(()) and CheckerImpl2.check() returns Left("error2") then result of the new function will return Left("error2").
OR
So if CheckerImpl1.check() returns Right(()) and CheckerImpl2.check() returns Right(()) then result of the new function will return Right(()).
What I have done right now is
(CheckerImpl1.check(), CheckerImpl2.check())
.mapN {
case (Right(_), Right(_)) => Right(())
case (Left(err), Right(_)) => Left(err)
case (Right(_), Left(err)) => Left(err)
case (Left(err1), Left(err2)) => Left(err1 ++ "&" ++ err2)))
}
But this is not a ideal solution, because if I add more implementation, then I would need to add more of these case statement.
Is there a better way of doing this ?
So you have a List of Future Eithers.
val lfe :List[Future[Either[String,Unit]]] = ???
To get all the Left strings together in one Future[String] you could do this...
val res :Future[String] =
Future.sequence(lfe)
.map(_.flatMap(_.fold(Some(_),_ => None)).mkString(" & "))
If I understand correctly, you eventually want to get Future[Either[String, Unit]] type. Why not just .sequence futures and .fold the results?
val checkers: List[Checker] = ???
Future.sequence(checkers.map(_.check()))
.map { results => results.foldLeft(Right(()): Either[String, Unit]) {
case (Left(acc), Left(err)) => Left(s"$acc&$err")
case (Right(_), Left(err)) => Left(err)
case (acc, Right(_)) => acc
}}
The only code change you need now is to augment checkers list.
Somewhat more elegant using cats (if you are not familiar with kind projector plugin - that's where the * comes from).
import cats.implicilts._
checkers.map(_.check()).sequence
.map { results =>
results.map(_.toValidatedNec)
.sequence[ValidatedNec[String, *], Unit]
.leftMap(_.toList.mkString("&"))
.map(_ => ())
.toEither
}

Enable retries on the Scala function returning a Future

I have some functions which return Futures. The callers register callbacks by onComplete.
def makeHttpRequest(): Future[T] = ???
makeHttpRequest().onComplete {
case Success(v) => ???
case Failure(ex) => ???
}
Now I want to enable retries on these functions (or function callings). Is there any suggestion on how to achieve this?
There is no retry capability out-of-the-box. However based on Retry a function that returns a Future consider
def retry[T](n: Int, expr: => Future[T]): Future[T] =
Future.unit.flatMap(_ => expr).recoverWith {
case e if n > 1 => retry(n - 1, expr)
case e => Future.failed(e)
}
retry(3, makeHttpRequest())
https://scalafiddle.io/sf/otseSX0/0
or consider dedicated library such as softwaremill/retry.
def makeHttpRequest(maxRetryCount: Int, currentRetryCount: Int = 0): Future[T] = {
val responseFuture = ???
if (currentRetryCount == maxRetryCount)
responseFuture
else
responseFuture.recoverWith(makeHttpRequest(maxRetryCount, currentRetryCount + 1))
}
makeHttpRequest(3).onComplete {
case Success(v) => ???
case Failure(ex) => ???
}

How to know which Future fail when doing Future.sequence?

Here is an example receive part of an actor I'm working on:
def receive = {
case "begin" =>
val listOfFutures: IndexedSeq[Future[Any]] = workers.map(worker => worker ? Work("test"))
val future: Future[IndexedSeq[Any]] = Future.sequence(listOfFutures)
future onComplete {
case Success(result) => println("Eventual result: "+result)
case Failure(ex) => println("Failure: "+ex.getMessage)
}
case msg => println("A message received: "+msg)
}
When ask fails for one of the workers (in case of a timeout), sequence future completes with failure. However I want to know which worker(s) have failed. Is there a more elegant way rather than simply mapping listOfFutures one by one without using Future.sequence ?
You can use the future's recover method to map or wrap the underlying exception:
import scala.concurrent.{Future, ExecutionContext}
case class WorkerFailed(name: String, cause: Throwable)
extends Exception(s"$name - ${cause.getMessage}", cause)
def mark[A](name: String, f: Future[A]): Future[A] = f.recover {
case ex => throw WorkerFailed(name, ex)
}
import ExecutionContext.Implicits.global
val f = (0 to 10).map(i => mark(s"i = $i", Future { i / i }))
val g = Future.sequence(f)
g.value // WorkerFailed: i = 0 - / by zero
Thanks to #O__ I have come with another solution that may a better fit some some cases.
case class WorkerDone(name: String)
case class WorkerFailed(name: String)
import ExecutionContext.Implicits.global
val f = (0 to 10).map {
i => Future {i/i; WorkerDone(s"worker$i")}.recover{
case ex => WorkerFailed(s"worker$i")
}
}
val futureSeq = Future.sequence(f)
futureSeq onComplete {
case Success(list) => list.collect {case result:WorkerFailed => result}.foreach {failed => println("Failed: "+failed.name)}
case Failure(ex) => println("Exception: "+ex.getMessage)
}
// just to make sure program doesn't end before onComplete is called.
Thread.sleep(2000L)
I'm not sure that if my example is a good practice, but my aim is to know which workers did fail no matter how did they fail.