Sebastian Piu
Sebastian Piu

Reputation: 8008

Akka / Futures - pipe different messages depending on success or failure?

I've got the following piece of code on an Actor where I ask someone else for an action (persist something in an external DB)

If that is successful:
Then I send a message to myself to reflect the result of the action in my local state and then return that to the original sender.

In case of a failure on the persistence to the DB:
Then I want to reply with Status.Failure (as returned to me) directly to the current sender.

The code looks like this:

case Event(SomeAction(name), _) =>
  val origin = sender()
  ask(someOtherActor, SomeAction(name)).mapTo[ActionResult]
    .map(ActionCompleted)
    .onComplete {
       case Success(value) => self.tell(value, origin)
       case Failure(e) => origin ! Status.Failure(e)
    }

    stay()

  case Event(ActionCompleted(result), state) =>
    stay using state.update(result) replying result

The code above works, but I need to rely on copying the sender into a local variable to avoid closing over it.

I was wondering if there is any better way to do this with pipeTo?

Upvotes: 1

Views: 343

Answers (1)

You can build your own pipeTo that does what you need. I think routeTo would be a good name for it.

implicit class RouteTo[A](f: Future[A]) {
  import akka.pattern.pipe
  def routeTo(successDestination: ActorRef, 
              failureDestination: ActorRef)(
                implicit sender: ActorRef, 
                         ec: ExecutionContext): Unit =
    f onComplete {
      case s @ Success(_) => successDestination.tell(s, sender)
      case f @ Failure(_) => failureDestination.tell(f, sender)
    }
}

import RouteTo._
Future("hello").routeTo(successRecipient, failureRecipient)

Upvotes: 3

Related Questions