While executing code within one actor, I need to check if the actor is still alive.
Would this be advisable or is there a better way?
if (self != akka.actor.DeadLetter) {
// do something
}
Thanks!
EDIT---
Thanks for all your inputs. What happens is the following. I am using Play. As my actor starts, upon an incoming request, a timeout is scheduled.
Promise.timeout({
Logger.info(s"$self, timeout expired")
// do something
}, timeoutValue)
Sometimes the actor is stopped for other reasons before the timeout expires (for instance, the client disconnects). In that case, what I see then in the logs is
Actor[akka://application/deadLetters], timeout expired.
To my understanding, this means that the default deadLetters actor is executing that code. So my question really is: what is the best way to check if the Promise code is executed after the actor is terminated, and prevent it from going further if that is the case?
You should familiarize yourself with the actor lifecycle: http://doc.akka.io/docs/akka/2.3.4/scala/actors.html#Actor_Lifecycle
From inside an actor you can implement the postStop() callback that will be called immediately before your actor is going to be stopped. If you want to monitor the lifecycle of the actor from another actor you should use DeathWatch: http://doc.akka.io/docs/akka/2.3.4/scala/actors.html#Lifecycle_Monitoring_aka_DeathWatch
If your actor is dead, no code within the actor will be running.
You can check if specific actor is available, with actorSelection, and then send a message to whatever is returned as a result (if there will be nothing, no message will be sent).
ActorContext.actorSelection(<your-actor-name>) ! someMessage
I think you can watch your actor and if you receive message Terminated you are sure that your actor is not running.
ActorContext.watch(self)
Related
How can I test an actor? Since the calls are not synchronous, and one messages can cause multiple messages to be sent, what are the ways of testing it?
E.g. How can I test that my actor sent 3 messages in response to another message?
In general you cannot test what an actor has done unless it interacts with a trait or interface you provide in the construction or in an input message. So if you have an actor like the following.
actor MyActor
be do_stuff(receiver: MyReceiver)
You use a pattern where you combine a timer, for a timeout, and a wrapper actor that provides MyReceiver to test if the actor actually did send the message or sequence of messages that where expected.
Pony already includes the ponytest package with some support for this kind of tests. You can check the PonyTest actor at GitHub. Basically you have to specify a timeout and ensure one of your actors calls complete in the test helper for success. Note that the API has changed since the last stable version.
I'm started to learn Akka and in many official examples I see that request-response implemented using tell pattern. I.e. after worker made his work he sends result as new message back to sender. For example in this Pi approximation official tutorial shown how to design application where Master sends some work to workers and then awaits for results as another message.
Master code:
def receive = {
case Calculate ⇒
for (i ← 0 until nrOfMessages) workerRouter ! Work(i * nrOfElements, nrOfElements)
case Result(value) ⇒
pi += value
nrOfResults += 1
if (nrOfResults == nrOfMessages) {
// Send the result to the listener
listener ! PiApproximation(pi, duration = (System.currentTimeMillis - start).millis)
// Stops this actor and all its supervised children
context.stop(self)
}
}
Worker code:
def receive = {
case Work(start, nrOfElements) ⇒
sender ! Result(calculatePiFor(start, nrOfElements)) // perform the work
}
But I'm wondering why this example didn't use ask pattern? What is wrong with using ask pattern here?
If it's ok to use ask pattern here, then I have another question: how I can stop all worker actors after work is done?
Should my worker actors send PoisonPill message to themselves?
Or should Master actor Broadcast(PoisonPill)?
Or there some another more elegant way?
ask is useful when integrating actors with Future APIs, but they do introduce some overhead. Further, Future completions do not come through an actor's mailbox and are scheduled on a thread separate from the one used by the mailbox, meaning that receiving a future completion inside an actor introduces the need for doing multi-thread coordination.
Meanwhile, if you use tell to send to a worker and have it tell the sender in response, the communication will always flow properly through the mailbox channel.
Additionally, it is much easier to discern the inputs an actor deals with if they all come in via receive rather than some coming in via receive and other's as completions of ask messages.
To address you PoisonPill questions, the answer is likely depends. You might opt for a worker-per-message approach in which case the worker should kill itself. If instead you use a worker pool, you could make the supervisor responsible for scaling that pool up and down, having it send the PoisonPill or have workers time out on idleness, once again killing themselves.
After starting an actor
val a = actor {
loop {
react {
case "end" => exit
...
}
}
}
And sending "end" message to it
a ! "end"
I want to make sure the thread is finished.
How can it be joined?
As far as I know an actor can't be joined explicitly as in the Java-way. The concept is to introduce event-based programming, so it should only react on events.
You can trap the exit however and link your initial actor (A) to the ending actor (B) via link. That way the initial actor A receives an event when B ends. If you don't get any event you know the actor hasn't terminated. See the thread here: https://stackoverflow.com/a/4304602/999865
If you don't care about resources and knows that the thread will terminate you can also make the actor inherit from DaemonActor. Daemon actors doesn't block any system resources.
Seems to me that the "actor-way" of doing what you want is actually have your actor reply with a message "Done" to the requester, so it can take action. That way it is all still asynchronous event handling
Suppose I have a running Scala application with actors. I suspect one actor does not work, i.e. either it exited or it is "stuck" or it is running in a loop.
Now I would like to know what is exactly going on with the actor. Is there any way in Scala to check actors/their mailboxes from the outside of the application, e.g. with JMX ?
I guess if an actor exited because of an uncaught Throwable the Scala actor library always writes this in the log. Is it correct? I can check also if an actor is stuck using a JVM thread dump.
What else can I use to check if my actor is running?
You can call the getState method.
In Scala, an actor can be notified when another (remote) actor terminates by setting the trapExit flag and invoking the link() method with the second actor as parameter. In this case when the remote actor ends its job by calling exit() the first one is notified by receiving an Exit message.
But what happens when the remote actor terminates in a less graceful way (e.g. the VM where it is running crashes)? In other words, how the local actor can discover that the remote one is no longer available? Of course I would prefer (if possible) that the local actor could be notified by a message similar to the Exit one, but it seems not feasible. Am I missing something? Should I continuously polling the state of the remote actor (and in this case I don't know which is the best way to do that) or is there a smarter solution?
But what happens when the remote actor terminates in a less graceful way (e.g. the VM where it is running crashes)
Actor proxy stays alive accepting messages (and loosing them), and waiting for you to restart the JVM with remote actor. Watching for JVM crashes (and other failures happening on the infrastructure level) is far beyond Scala responsibilities. Good choice for that could be monitoring through JMX.
In other words, how the local actor can discover that the remote one is no longer available?
You may define a timeout interval (say 5000 millis). If remote actor doesn't reply during this interval, it's a sign for you that something unexpected is happening to remote actor, and you may either ask it about its state or just treat it as dead.
Should I continuously polling the state of the remote actor (and in this case I don't know which is the best way to do that) or is there a smarter solution?
You may put a kind of a polling load balancer/dispatcher in front of a group of actors, that will use only those actors that are alive and ready to process messages (which makes sense in case of remote actors that may suddenly appear/disappear behind the proxy) -> Can Scala actors process multiple messages simultaneously?
The book Actors in Scala mentions (not tested personally):
Trapping termination notifications.
In some cases, it is useful to receive termination notifications as messages in the mailbox of a monitoring actor.
For example, a monitoring actor may want to rethrow an exception that is not handled by some linked actor.
Or, a monitoring actor may want to react to normal termination, which is not possible by default.
Actors can be configured to receive all termination notifications as normal messages in their mailbox using the Boolean trapExit flag. In the following example actor b links itself to actor a:
val a = actor { ... }
val b = actor {
self.trapExit = true
link(a)
...
}
Note that before actor b invokes link it sets its trapExit member to true;
this means that whenever a linked actor terminates (normally or abnormally) it receives a message of type Exit.
Therefore, actor b is going to be notified whenever actor a terminates (assuming that actor a did not terminate before b’s invocation of link).
So "what happens when the remote actor terminates in a less graceful way"?
It should receive an Exit message even in the case of an abnormal termination.
val b = actor {
self.trapExit = true
link(a)
a ! 'start
react {
case Exit(from, reason) if from == a =>
println("Actor 'a' terminated because of " + reason)
}
}