Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return Future Message from an Actor

Tags:

scala

akka

scalaz

I have an existing API which returns a Future. Now introducing an Actor for one of the use cases and trying to continue using same service API from it. From below you can see MyService.saveValues return future.

object MyActor {
   implicit val ec = scala.concurrent.ExecutionContext.Implicits.global
   implicit val timeout = Timeout(1 second)
   case class SampleMessage(list: List[String])
   val actorSystem =  //get actorSystem that was created at the startup


  def saveMessage(list: List[String])  ={
    val res = (actorSystem.actorOf(Props[MyActor]) ? SaveMyMessage(list) ).mapTo[Future[\/[Throwable,String]]
 //res map{ r=>

 //}

 }
}
class MyActor extends Actor {
import MyActor._

def receive = {
  case SaveMyMessage(list) =>

   val originalSender = sender

   val res : Future[\/[Throwable,String] ] = MyService.saveValues(list)


   originalSender ! res
  }
}

As you can see in def saveMessage I am using ask to wait for a result from an actor. However ask also creates its own future so result (val res) in saveMessage becomes Future[Future[T]] which looks annoying. What's the best way to deal with this scenario?

like image 200
user2066049 Avatar asked Feb 13 '23 13:02

user2066049


1 Answers

pipeTo forwards the result of a Future to an ActorRef.

import akka.pattern.pipe


val originalSender = sender
val res : Future[\/[Throwable,String] ] = MyService.saveValues(list)
res pipeTo originalSender

If saveValues throws, your future never complete and will end up timing something out though.

If you ever end up with Future[Future[A]], but want Future[A] as a result of sequencing/traversing or something, you can always "flatMap that shit."

import ExecutionContext.Implicits.global
val foo: Future[Future[Int]] = ???
val bar: Future[Int] = foo.flatMap(identity)

If you already depend on scalaz (and scalaz.contrib if on scalaz 7.0.x), you can use join defined in monad syntax.

import scalaz.syntax.monad._
import scalaz.contrib.std.scalaFuture._
val bar2: Future[Int] = foo.join
like image 158
drstevens Avatar answered Feb 19 '23 00:02

drstevens