How to watch remote Akka Actor? - scala

I am learning akka-remote and one of the things I do in my LocalActorSystem is getting remote actor reference and send messages to him
class LocalActor extends Actor {
val remote = context.actorSelection("akka.tcp://HelloRemoteSystem#127.0.0.1:5150/user/RemoteActor")
var counter = 0
def receive = {
case "START" =>
remote ! "Hello from the LocalActor"
case msg: String =>
println(s"LocalActor received message: '$msg'")
if (counter < 5) {
sender ! "Hello back to you"
counter += 1
}
}
}
My Remote looks like
object Remote extends App {
val system = ActorSystem("HelloRemoteSystem", ConfigFactory.load("remote"))
val remoteActor = system.actorOf(Props[RemoteActor], name = "RemoteActor")
remoteActor ! "The RemoteActor is alive"
}
class RemoteActor extends Actor {
def receive = {
case msg: String =>
println(s"RemoteActor received message '$msg'")
sender ! "Hello from the RemoteActor"
}
}
I also wanted to watch remoteActor so that if its dead, LocalActorSystem get to know. So I did
val remote = context.actorSelection("akka.tcp://HelloRemoteSystem#127.0.0.1:5150/user/RemoteActor")
context watch remote
but then compiler fails with following message
Question
How come I am able to send message to ActorSelection since it is not Actor?
How can I watch RemoteActor?
Update
However, the deprecated API does not complain
val remote = context.actorFor("akka.tcp://HelloRemoteSystem#127.0.0.1:5150/user/RemoteActor")
context watch remote

When you do a lookup via actorSelection, that type of object you get back is an ActorSelection and not an ActorRef. Now, an ActorSelection does support both tell (!) and ask (?) so you can interact with it the same way you would an ActorRef. But an looking up actors via actorSelection supports the concept of a wild card, so the ActorSelection you get back potentially represents more than one actor and would allow you to send messages to more than one actor. For instance, if you did :
system.actorSelection("/user/foo/*")
this would give you an ActorSelection for all children under the parent ActorRef bound to the name foo. If there were two children and you send a message via that ActorSelection, that message would be delivered to both children.
In your case, it looks like you are looking up a single actor instance. In that case, you can get an ActorRef from your ActorSelection by calling resolveOne on it. This will return a Future[ActorRef] that when completed will provide you with an ActorRef that you can watch remotely. You could also send the ActorSelection an Identify message and wait for the ActorIdentity response containing the ref to watch.
You should check out the docs here, specifically the Identifying Actors via Actor Selection section.

Related

Akka: Keep unmatched messages in the mailbox

I'm familiar with Erlang/Elixir, in which messages that are in a process' mailbox remain in the mailbox until they are matched:
The patterns Pattern are sequentially matched against the first message in time order in the mailbox, then the second, and so on. If a match succeeds and the optional guard sequence GuardSeq is true, the corresponding Body is evaluated. The matching message is consumed, that is, removed from the mailbox, while any other messages in the mailbox remain unchanged.
(http://erlang.org/doc/reference_manual/expressions.html#receive)
However, with Akka Actors unmatched messages are removed from the mailbox.
This is annoying when implementing for instance forks in a dining philosophers simulation:
import akka.actor._
object Fork {
def props(id: Int): Props = Props(new Fork(id))
final case class Take(philosopher: Int)
final case class Release(philosopher: Int)
final case class TookFork(fork: Int)
final case class ReleasedFork(fork: Int)
}
class Fork(val id: Int) extends Actor {
import Fork._
object Status extends Enumeration {
val FREE, TAKEN = Value
}
private var _status: Status.Value = Status.FREE
private var _held_by: Int = -1
def receive = {
case Take(philosopher) if _status == Status.FREE => {
println(s"\tPhilosopher $philosopher takes fork $id.")
take(philosopher)
sender() ! TookFork(id)
context.become(taken, false)
}
case Release(philosopher) if _status == Status.TAKEN && _held_by == philosopher => {
println(s"\tPhilosopher $philosopher puts down fork $id.")
release()
sender() ! ReleasedFork(id)
context.unbecome()
}
}
def take(philosopher: Int) = {
_status = Status.TAKEN
_held_by = philosopher
}
def release() = {
_status = Status.FREE
_held_by = -1
}
}
When a Take(<philosopher>) message is sent to the fork,
we want the message to stay in the mailbox until the fork is released and the message is matched. However, in Akka Take(<philosopher>) messages are dropped from the mailbox if the fork is currently taken, since there is no match.
Currently, I solve this problem by overriding the unhandled method of the Fork actor and forwarding the message to the fork again:
override def unhandled(message: Any): Unit = {
self forward message
}
I believe this is terribly inefficient as it keeps sending the message to the fork until it is matched. Is there another way to solve this problem which does not involve continuously forwarding unmatched messages?
I believe that worst case I will have to implement a custom mailbox type that mimics Erlang mailboxes, as described here: http://ndpar.blogspot.com/2010/11/erlang-explained-selective-receive.html
EDIT: I modified my implementation based on Tim's advice and I use the Stash trait as suggested. My Fork actor now looks as follows:
class Fork(val id: Int) extends Actor with Stash {
import Fork._
// Fork is in "taken" state
def taken(philosopher: Int): Receive = {
case Release(`philosopher`) => {
println(s"\tPhilosopher $philosopher puts down fork $id.")
sender() ! ReleasedFork(id)
unstashAll()
context.unbecome()
}
case Take(_) => stash()
}
// Fork is in "free" state
def receive = {
case Take(philosopher) => {
println(s"\tPhilosopher $philosopher takes fork $id.")
sender() ! TookFork(id)
context.become(taken(philosopher), false)
}
}
}
However, I don't want to write the stash() and unstashAll() calls everywhere. Instead, I want to implement a custom mailbox type that does this for me, i.e. stashes unhandled messages and unstashes them when a message has been processed by the actor. Is this possible?
I tried to implement a custom mailbox which does this, however, I can't determine whether a message did or did not match the receive block.
The problem with forward is that it may re-order the messages if there are multiple messages waiting to be processed, which is probably not a good idea.
The best solution here would seem to be to implement you own queue inside the actor that gives the semantics that you want. If you can't process a message immediately then put in on the queue, and when the next message arrives you can process as much of the queue as possible. This would also allow you to detect when senders give inconsistent messages (e.g. Release on a fork that they did not Take) which otherwise will just build up in the incoming mailbox.
I would not worry about efficiency until you can prove it is a problem, but it will be more efficient if each receive function only processes the messages that are relevant in that particular state.
I would avoid using var in the actor by putting the state in the parameters to the receive methods. And the _status value is implicit in the choice of receive handler and doesn't need to be stored as a value. The taken receive handler only needs to process Release messages and the main receive handler only needs to process Take messages.
There exists a sample project in the Akka repository that houses multiple implementations of the "Dining Philosophers" problem. A key difference between your approach and theirs is that they implement both the utensils and the philosophers as actors, whereas you define only the utensil as an actor. The sample implementations show how to model the problem without dealing with unhandled messages or using a custom mailbox.

What happens to unmatched messages with Akka?

The Akka documentation says that the mailbox is NOT scanned for messages. Each message is handled after another (FIFO by default) in the order of their arrival. However, when I send a message from an actor to another which is not matched be the receiving actor, it is neither moved to the deadletters actor (which would appear in the log I suppose) nor does it block handling the next message in the mailbox which arrives one second later and can be handled correctly.
What does happen to the unmatched message from the mailbox?
I am using Scala 2.10.4 and Akka 2.4-SNAPSHOT in sbt.
package main.scala
import akka.actor._
class SRActor(dest: ActorRef) extends Actor with ActorLogging {
dest ! A
dest ! B
context.stop(self)
override def receive = {
case _ => {
log.info("Finally got something")
}
}
}
class SRActorReceiver extends Actor with ActorLogging {
override def receive = {
case B =>
log.info("Finally got B")
}
}
Actor creation:
package main.scala
import akka.actor._
case object A
case object B
object ErrorApp extends App {
// SR: Send nowhere received
var system6 = ActorSystem("ErrorActorSystem")
val srActorReceiver = system6.actorOf(Props(classOf[SRActorReceiver]), "sractorreceiver")
val sractor = system6.actorOf(Props(classOf[SRActor], srActorReceiver), "sractor")
// wait until actors have finished
Thread.sleep(1000)
system6.shutdown
Copied from docs
Please note that the Akka Actor receive message loop is exhaustive,
which is different compared to Erlang and the late Scala Actors. This
means that you need to provide a pattern match for all messages that
it can accept and if you want to be able to handle unknown messages
then you need to have a default case as in the example above.
Otherwise an akka.actor.UnhandledMessage(message, sender, recipient)
will be published to the ActorSystem's EventStream.
There is also unhandled method in Actor trait that you can override. (docs)
def unhandled(message: Any): Unit
User overridable callback.
Is called when a message isn't handled by the current behavior of the actor by default it fails with either a akka.actor.DeathPactException (in case of an unhandled akka.actor.Terminated message) or publishes an akka.actor.UnhandledMessage to the actor's system's akka.event.EventStream

How to send a message from an actor to a Websocket using Play! 2.4?

I'm working with Play! Scala 2.4 and I have a Websocket handled by an actor as following:
object MyWebSocketActor {
def props(out: ActorRef) = Props(classOf[MyWebSocketActor], out)
}
class MyWebSocketActor #Inject()(out: ActorRef) extends Actor {
override def receive = {
case msg: String => out ! ("I received your message: " + msg)
case _ => out ! "I did not received your message: "
}
}
class MessagesController extends Controller {
def openSocket = WebSocket.acceptWithActor[String, String] { request => out =>
MyWebSocketActor.props(out)
}
}
It works well but I would like to send to it (MyWebSocketActor) some messages from an other actor and I don't manage to make it.
I tried to start it when my application starts with AkkaGuiceSupport like this: bindActor[MyWebSocketActor]("MyWebSocketActor") in order to be able to inject it in an other actor like this: (#Named("MyWebSocketActor") myWebSocketActor: ActorRef) but I get an error since I did not provide an ActorRef when I bind the actor.
The Guice error is:
No implementation for akka.actor.ActorRef was bound.
while locating akka.actor.ActorRef
for parameter 0 at controllers.MyWebSocketActor
How can I do that?
The "instance" of MyWebSocketActor is created per connection. So when you want to send a message to it, I guess you want to send message to all instances of MyWebSocketActor (which will transfer those messages to all browsers which have a connection to the websocket)
In that case, you can use the "PubSub" module, have MyWebSocketActor subscribe to a topic, and publish message from your other actors to that.
Here's a activator template which has very good sample regarding this: http://www.lightbend.com/activator/template/akka-clustering?_ga=1.54579683.939088969.1455862030
Here's the document for PubSub module http://doc.akka.io/docs/akka/2.4.2/scala/distributed-pub-sub.html

Obtaining data from ActorRef in akka

I have the following Actor Model declaration in akka:
val wireA = system.actorOf(Props(new Wire(false)), "Input")
val wireB = system.actorOf(Props(new Wire(false)), "Output")
inverter ! generateOutput(wireA, wireB)
From the generateOutput(input:ActorRef, output:ActorRef),
I need to access the boolean parameter which constructs each particularActorRef (i.e the paramater false which is found in each respective Wire Constructor.
How does it can be reached?
You can send a message to each actor, asking for its current status:
case object Status
case object StatusResult(value: Boolean)
class MyActor(wire: ActorRef) extends Actor {
wire ! Status
def receive = {
case StatusResult(value) => ...
}
wireA and wireB are ActorRefs, they do not expose their state and the only way to communicate with them is via messages.
It's not the way you should play with Actors. You get the ActorRef and you you play with it only with the messages. You can ask the actor of the value of the boolean by passing a message to it:
wireA ! "getVal"
and waiting for the response in the sender actor. Please check the basic tutorial on Actors:
http://alvinalexander.com/scala/scala-akka-actors-ping-pong-simple-example

What's the minimal code required to have two local instances communicate with Akka actors?

I wonder what's the minimal code required to start two instances of an application on a machine, which can send to and receive messages from each other.
As far as I understand, I would need
to start an actor which can process messages.
to tell this instance that there is another instance where messages can be sent to.
How can I do 1. and 2. in Akka?
From Akka's home page:
// server code
class HelloWorldActor extends Actor {
def receive = {
case msg => self reply (msg + " World")
}
}
remote.start("localhost", 2552).register("hello-service", actorOf[HelloWorldActor])
// client code
val actor = remote.actorFor("hello-service", "localhost", 2552)
val result = (actor ? "Hello").as[String]