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.
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.
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)
I have a setup in which an actor(A) creates an actor(B) which it supervises and restarts when it crashes. From outside the actor system I want to get some value from the 'nested' actor B.
I can directly ask the actorSystem for the nested actor using:
val nestedActorB = myActorSystem.actorFor("/user/A/B")
Can I keep a reference to this actor or should I ask the actorSystem for the ref each time I want to ask the nested actor something. (Or should I ask the parent actor for the ref)?
What would be a best practice in this scenario?
(scala 2.9.1 and akka 2.0.4)
Thanks,
Albert
Yes you can keep a reference to the actor and not ask the system every time with actorFor.
There is a difference between local and remote actors and the documentation passage you are referring to is ambiguous and I've opened a ticket.
A local actor is only looked up once during the actorFor call so it needs to exist before you look it up, while sends to a remote actor are always by path and the remote actor is looked up on the remote node every time.
Even after the restart the reference stays the same. B will always be a child of A so the "/A/B" path is stable. If A is a top level actor, you will always find him under"/user/A". So yeah, "/user/A/B" will always point to the same actor.
As you can see in the akka doc, a reference is an object that, at runtime, traverses the actor tree every time you send a message or check the liveliness of the actor you are referring to.
This means you can use the reference you obtain with the actorFor method any time you want to communicate with that actor, even if the actor belonging to that path is restarted or even if it's already terminated.
In order to notify external (to AKKA) components in case an error occurred within an Actor, we use an ErrorHandler listener per one of the SO solutions.
Some errors require a complete process / JVM stop. In which case unless we call:
EventHandler.shutdown()
It keeps the process up.
What would be a clean way to shutdown JVM process in this case? And if we do need to use EventHandler.shutdown(), what would be the most logical ( AKKA? ) place to invoke it from?
If you're running the Akka Microkernel it will be done for you. If you're running it using an AkkaLoader in a ServletContainer, it will be done for you. Do you have a defined application lifecycle?
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)
}
}