JBarber
JBarber

Reputation: 212

Scala sending messages to self Good or Bad?

I'm using json4s with play framework and I have some places where I'll run a post/get request in a future, then onSuccess parse the response in to an object and have the actor send it back to itself.. Here's an example:

WS.url(authUrl).post("username=admin&password=admin") map {
  response =>
    self ! (parse(response.body) \ "body").extract[AuthObject]
}

and then back in the receive method:

case AuthObject(_, sid) => //handle authorization token

Is this bad practice? What's the correct way to go about this? The advantage I see is being able to have your actors data flow handled by a single control structure, but of course I could be wrong in saying that's an advantage.

Upvotes: 4

Views: 287

Answers (2)

Jean
Jean

Reputation: 21595

The recommended way to send future results to actors is to use the pipe pattern. You code would then look like this:

def receive:Reveice= {
  case authUrl:String => 
    val authObjectF=WS.url(authUrl).post("username=admin&password=admin") map { response => 
      (parse(response.body) \ "body").extract[AuthObject]
    } 
    authObjectF pipeTo self
}

The reason this is considered superior to map {x => self ! x } is error handling. If you don't handle the error cases, they will simply be silently discarded. Using the pipepattern, the errors will be wrapped in a akka.actor.Status.Failure and sent to the destination actor (in this case to self) in place of the result.

Piping the result of a future to self is a common pattern, possibly used in conjunction with context.become/unbecome and stash to create state machines.

It is still very easy to close over actor internal mutable state in a map/flatmap and break the concurrency guarantees of the actor model in doing so. If you are manipulating futures in actors I strongly suggest reading this http://doc.akka.io/docs/akka/2.3.2/general/jmm.html#jmm-shared-state if you haven't done so already.

Upvotes: 8

Reid Spencer
Reid Spencer

Reputation: 2785

There's nothing inherently wrong with it. Sending a message to yourself is similar to a human keeping a "to do" list and putting something at the end of the list. Your actor will get there .. eventually. And, that's really the only concern: the timing of when AuthObject message gets processed. If your application only requires ordering but not time guarantees then it is fine to process it that way.

I would be wary, however, of your \ operator returning a JsError in the case there is no "body" field in your response.body (presumably Json). In that case your message never gets sent and there's no error delivered anywhere either.

Upvotes: 1

Related Questions