Hi,

I have a use-case where the sender of an event shall be able to specify 
whether the event shall be processed in the background or an answer is 
expected. I wanted to express these semantics by specifying a 'replyTo: 
Option[ActorRef]' in the message rather than adding a flag to the message. 
The constraint here is that it shall work from outside the actor system as 
well (ie. I would need something like the ask pattern, which basically 
returns a future, if the event isn't sent from within an actor).

I thought about these approaches, none of which seemed quite right:

- Send the event with the ask pattern: This would mean I don't have a 
replyTo in the message, but a flag (eg. 'responseWanted'). If the flag is 
set to true, the processing actor would respond -- otherwise not. The 
problem here is that the ask pattern always expects a response within the 
specified timeout or throws an exception if no response is received. Also, 
I'd rather have an explicit replyTo attribute in the event instead of the 
flag.

- Send the event with tell: This would mean the sender needs to be an actor 
as well or somehow else obtain an ActorRef to be sent along for the 
response. This would mean I'd have to create an ActorRef on the fly to 
handle the response.

Eventually I ended up implementing a bit of boilerplate code that combines 
the two approaches (heavily inspired by the ask pattern's impl): If the 
sender is not interested in a response, it can just fire the event with a 
regular tell and set the replyTo to None. If the sender wants a response, 
however, it would invoke a function with this signature: *def 
askOpt(msgFactory: ActorRef => Any, target: ActorRef): Future[Any]* This 
creates an actor on the fly, creates the event with the newly created 
actor's ref and then sends that to the target from inside the new actor. It 
then races against a scheduled task, just like the ask pattern.


So my questions are:
- Is this a good approach? I feel like I am re-implementing lots of things 
that already exist in the ask pattern, however all of that is inacessible 
from the outside
- Specifying the replyTo in the message will become much more prominent 
with akka-typed (as far as I understand). How would ask work in that 
scenario? (seems somewhat similar)

Thanks a lot!

- Reto



Boilerplate Code:

  def ask(msgFactory: ActorRef => Any, target: ActorRef)(implicit system: 
ActorSystem, timeout: Timeout): Future[Any] = {

    val result = Promise[Any]()

    val actor = system.actorOf(PromiseActor.props(result, msgFactory, 
target))

    import system.dispatcher
    val f = system.scheduler.scheduleOnce(timeout.duration) {
      result tryComplete Failure(new AskTimeoutException(s"Ask timed out on 
[$target] after [${timeout.duration.toMillis} ms]"))
    }

    result.future onComplete { _ =>
      try actor ! PoisonPill finally f.cancel()
    }

    result.future
  }

  private class PromiseActor(p: Promise[Any], evtFactory: ActorRef => Any, 
target: ActorRef) extends Actor {

    override def preStart: Unit = {
      target ! evtFactory(self)
    }

    override def receive: Receive = {
      case res: Any =>
        p.success(res)
        context.stop(self)
    }

  }

-- 
>>>>>>>>>>      Read the docs: http://akka.io/docs/
>>>>>>>>>>      Check the FAQ: 
>>>>>>>>>> http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>>      Search the archives: https://groups.google.com/group/akka-user
--- 
You received this message because you are subscribed to the Google Groups "Akka 
User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to akka-user+unsubscr...@googlegroups.com.
To post to this group, send email to akka-user@googlegroups.com.
Visit this group at https://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.

Reply via email to