When is the supervisor strategy invoked ? Is it when the exception is thrown for an Actor. In below code :
#Override
public SupervisorStrategy supervisorStrategy() {
System.out.println("supervisorStrategy");
return strategy;
}
The println statement is not invoked when actor is created. Is this expected behaviour ?
Unlike the not-to-well-named receive method, which is only called during Actor initialization to acquire the PartialFunction that will handle incoming messages, the supervisorStrategy method is used when failures occur. It is a regular method that does the work of deciding how to handle a failure in a descendant Actor.
Hmm... I just noticed you're using Java, so the part about receive is presumably different for you, but the supervisorStrategy statement still applies.
Related
I'm doing something like this:
...lots of surrounding context...
val actor = context.actorOf(Props(new Actor(...))
(actor ? message) onComplete {
case Done => {
println("done")
Do stuff with the surrounding context of this actor
}
case _ => {
println("got wildcard") // try to handle error message here
}
}
Actor is failing at initialization with
akka.actor.ActorInitializationException (in that actors context)
In the parent actor I am getting **dead letters encountered.**
since actor was never created properly and "message" couldn't be delivered.
In this scenario the "ask?" pattern never returns properly.
I could create a SupervisorStrategy in the parent global level, but I need to understand the context of the actor that generated the exception and it isn't possible (or convenient) handling it at the global level
Is there a way to "catch" the initialization exception in the "ask" context actor ? message?
According to akka philosophy ask should be used only when you interact with the actor from the outside of the actor system.
Since you have a reference to the context seems that you are inside the actor code. So you should try to get rid of ask.
If I'm wrong and you call ask from non-akka code then you shouldn't try to rely on anything that happens inside the actor system. All that you have is an ActorRef with no guaranties what is on the other side of this reference.
I created an FSM with Akka. However, my FSM doesn't only get messages passed that are relevant for its FSM state. Its children may also pass ActorRefs up to it, which my FSM should then pass further up to its parent. Since FSMs in Akka are (naturally) also actors, I would like to override receive to catch those ActorRefs. However, doing that broke the FSM functionality of the actor. What's the proper way to handle a situation like this?
Messages that are not relevant for any FSM state can be handled in whenUnhandled:
whenUnhandled {
case Event(someActorRef: ActorRef, _) =>
context.parent ! someActorRef
stay()
}
Though, overriding receive should, afaik, work, too.
I have an Actor, which acts as a Supervisor, but also needs to "return" data to the caller, wether this is an actor or not shouldn't matter.
I am asking my Supervisor, let's call him SV.
SV Processes the message I send to him, and sends back a response.
val system = ActorSystem("ActorSystem")
val sv = system.actorOf(Props[SV], name = "SV")
sv ? msg
And SV's recieve method looks like this:
def receive = {
case msg => (someChild ? msg).pipeTo(sender)
...
}
This all works jolly fine.
The problem is when the child throws an exception, this exception is caught by the supervisor strategy.
override def supervisorStrategy = OneForOneStrategy () {
case e : Throwable => {
val newResponse = someNewResponse
sender ! newResponse
...
}
}
sender is not longer a reference to whoever called SV in the first place, and I can't seem to work out how to send a message back to the askee, and get back to my original flow.
One of the three Actor rules is: “An Actor can send a finite number of messages to other Actors it knows.” The last two words are critical here: if the supervisor has not been introduced to the original sender somehow and the failure (exception) itself does not contain the sender’s reference either, then the supervisor cannot possibly send a message to the sender. Either you catch all exceptions in the child actor, wrap them together with the sender in your own exception type and then rethrow, or the original message needs to travel via the supervisor to the child and back, so that the supervisor can see that a reply is outstanding when a failure occurs.
Are you using the supervisor strategy and exceptions to control the flow or your data? Consider using the type system (Option type or a Failure on the response Future) for "exception" cases in your child actors and handle the response flow without exceptions.
The supervisor strategy is for unhandled exceptions.
When an unhandled exception occurs you lose the ability to respond with a message to the sender. Unless you wrap the sender in the unhandled exception like Roland Kuhn suggests.
Let the supervisor strategy instead handle how the actor system should respond to your unhandled exceptions by mapping them to a Directive.
I have an actor that has a mutable state. In my receive method, I pattern match the messages and call some service that would return a Future. This Future would modify the state in my Actor instance. Is this state not thread safe? Since the Future would be executing in a different thread, is the state in my Actor this guaranteed to be thread safe?
No that will not be threadsafe as you correctly assumed. Futures run on any thread that the execution context provides.
The way to solve this is to pipe it back to the same actor. All actor's inputs must always be messages. You can find the documentation here.
Some example code:
import akka.pattern.pipe
//... inside the Actor somewhere:
val futureResult: Future[YourType] = something.thatReturnsAFuture()
futureResult.pipeTo(self)
And then amend your receive block so the result will be processed after the future completes and it is sent back to this actor:
case result: YourType => //...
In an Actor model implementation in Scala, can we override the bang(!) operator.
Can we modify the operation of message passing by overloading this operator?
Example scenario:
I need to include logging of information when any actor invokes another
actor by passing a message. So by overloading the message pass(!) operator, Can I
track the message passing between different actors and avoid including logger
statement for every actor message passing call?
In an Actor model implementation in Scala, can we override the bang(!) operator.
You can, but I would strongly recommend against it.
Example scenario: I need to include logging of information when any actor invokes another actor by passing a message.
This won't work with any actors which don't extend your type: Akka system actors, actors created by libraries, etc.
This can already be done by Akka, just set akka.debug.receive = on.
In Akka you cannot actually override the ! operator, since you cannot create subclasses of ActorRef in a meaningful way (i.e. they would not be generated by the respective factory methods), and the reason for this is that it is not actually what you want (please trust me here).
Your stated use-case is already covered by built-in functionality:
import akka.event.LoggingReceive
def receive = LoggingReceive {
case x => ...
}
which will log a message for each invocation if you enable these configuration settings:
akka {
loglevel = DEBUG
actor.debug {
receive = on // this enables the above
autoreceive = on // same for the likes of PoisonPill, Kill, …
lifecycle = on // will log actor creation, restart, termination
}
}
You can try the following code.
override def !(msg:Any):Unit =
{
//logic for writing to logs..
super.!(msg)
}
This works fine. However, i want to differentiate behavior of !, depending upon the messages I am sending. for example below:
actor_name!(arg1,arg2,arg3)
actor_name1!(arg4, arg5)
How do i differentiate between these two message sending notation in the overriding code?