No router actor broadcasting unknown message to children - scala

I am trying to forward a message to each child of an actor.
I have two problems here:
trying to route any message to the children without knowing what message it is
access all the children at once.
So I am merely trying to have my actor do a router job but without being one... I have formerly asked a question which concluded that I could not use a router, see: Routees referring to Router.
What I am looking for is a way to spare me the boring writing of a message for each type and each child.
Is there a way to evade this work? With a method? I thought children (http://doc.akka.io/api/akka/2.0/akka/actor/ActorContext.html) would work but it does not.

Not sure why something like this won't work for you:
class ParentRouter extends Actor{
def receive = {
case message =>
context.children foreach (_.forward(message))
}
}

Related

Scala Akka broadcasting send message to all child actors from Parent Context

In my task parent actor create some child actors and send message to them
def apply(): Behavior[CreateBranch] = {
Behaviors.receive { (context, message) =>
val child1 = context.spawn(Child(), "child1")
val child2 = context.spawn(Child(), "child2")
val child3 = context.spawn(Child(), "child3")
context.children.foreach {
child ! Child.SomeMessage
{
}
}
Child actor defined as:
object Child {
sealed trait SomeMessage
def apply():Behavior[SomeMessage] = {
// some behaviour
{
}
But expression "context.children" does not work: children defined as Iterable[ActorRef[Nothing]] instead of Iterable[ActorRef[Child.SomeMessage]]
In documentation about "context.children" ActorContext.children
"this is not a useful way to lookup children when the purpose is to send messages to them."
And this document suggest alternative way of realisation - but it about of 30 lines of code!
Is there any other alternative way to realise broadcast message send ?
There is no way in general to guarantee the static type of the child actors (and the same is true of the parent actor and the guardian actor (context.system)).
However, if you're absolutely sure that all children will accept the message you can
context.children.foreach { child =>
child.unsafeUpcast[Child.SomeMessage] ! Child.SomeMessage
}
As the name implies, this is unsafe and allows you to send messages without any guarantee that the child will handle them. Since the implementation of an Akka Typed Behavior involves a classic actor which performs message casts, a mismatch between Behavior and ActorRef can cause the actor to immediately fail. unsafeUpcast is (at least from the sender's perspective...) safer than an asInstanceOf cast, as this at least guarantees that you're actually calling ! on an ActorRef.
You asked "Is there any other alternative way to realise broadcast message send ?".
Levi's answer is the most technically correct. But I think the "real" answer is not to use context.children. This complication is caused by the type system trying to protect you from something that is a very legitimate concern. That collection contains ALL children. And there are lots of times I might spawn a child just to monitor a timeout, receive a single message, or some other task that might not understand that message.
If you want to send a specific message to child actors, as was pointed out in Levi's answer, you probably don't really mean "all child actors", you mean "all child actors who understand this message". And although there are some other ways you could do this, I always find it easiest just to maintain your own collection of ActorRefs for an actor of a particular type. If I have "worker actors" I maintain my own sequence and then the message types just work automagically.
My experience is that you should really only use context.children for system-type operations. But anything else, I maintain my own collection. That way if I create a new type of child actor at a later date, I don't break any assumptions I'm making about the type of child actors and what messages they can receive.

Play WebSocketActor createHandler with custom name

I am using (learning to) handle websockets in play application.
My controller is using WebSocket.acceptWithActor
def clientWS = WebSocket.acceptWithActor[JsValue, JsValue] { _ =>
upstream => ClientSesssionActor.props(upstream)
}
and all is well except some other "supervisor" actor needs to be able to use context.actorSelection(...) to communicate with all/some of those ClientSessionActors.
But all my ClientSessionActors are created with a path like this one :
[akka://application/system/websockets/ REQ_ID /handler]
Here is the line where WebsocketActorSupervisor creates them :
val webSocketActor = context.watch(context.actorOf(createHandler(self), "handler"))
That is where the "handler" part of the path comes from.
I would like to pass in a specific name for my ClientSessionActor instead of getting "handler".
Overloading the whole call stack with one more parameter seems inelegant: there is WebSocketActor.scala with Connect, WebSocketActorSupervisor(props and constructor), WebSocketsActor receive and then everything inside the WebSocket.scala.
I know I can pass the supervisor reference to the props, but what about the case when the "supervisor" has been restarted and needs to reconnect with his minions.
One more thing, I realize that I might be able to get all the "handler" actors, but there are more than 2 kinds of handlers. Yes I could have them ignore msgs directed at the other groups of handlers but this just feels so redundant sending out 3 times more msgs than I should have to.
Any suggestions ?
James ? :)
Thank you
How about each ClientSesssionActor sends a Register message to supervisor on preStart and store them in eg. val sessions = new HashMap[String, ActorRef].
And then unregister by sending Unregister in postStop
private class WebSocketsActor extends Actor {
import WebSocketsActor._
def receive = {
case c # Connect(requestId, enumerator, iteratee, createHandler) =>
implicit val mt = c.messageType
context.actorOf(WebSocketActorSupervisor.props(enumerator, iteratee, createHandler),
requestId.toString)
}
}
Here is code how play creates actors for handling websockets, it names with requestId.
I have also same question :) why not make it to name with custom names.

Where to shutdown actors

we have a lot of actors that get created as
class BankActor extends Actor{
def receive ={
case CreateCustomer(message) => context.actorOf(Props[CustomerActor]) ! message
}
}
And CustomerActor creates other actors in a similar manner. Reason for creating actors in such a way is potentially there will be hundreds(or even thousands) of CreateCustomer messages that BankActor will be receiving in them. I thought creating them on the fly is a better way (given Actor is a low memory footprint). I didn't think having a "pool" of CustomerActor was a right thing to do because biz req is clear there will be lots and lots of "CreateCustomer" messages. can you share your thoughts on this? Now going back to question about stopping "CustomerActor" : where should I be doing context.stop(self) inside "CustomerActor"'s "receive" method, should it be the last thing in every "case" block in there? What's the best practice around this?
Avoid creating top-level actors unless you have a good reason to. (Use context.actorOf)
Send the newly created actor a PoisonPill after the "message" if you don't want to encode the shutdown within the created actor.
class BankActor extends Actor{
def receive = {
case CreateCustomer(message) =>
val customer = context.actorOf(Props[CustomerActor])
customer ! message
customer ! PoisonPill // message ordering is preserved on a per-sender basis (for all normal mailboxes)
}
}

Akka and Actor behavior interface

I just start trying myself out with Scala. I grow confident enough to start refactoring an ongoing multi-threaded application that i have been working on for about a year and half.
However something that somehow bother and i can't somehow figure it out, is how to expose the interface/contract/protocole of an Actor? In the OO mode, i have my public interface with synchronized method if necessary, and i know what i can do with that object. Now that i'm going to use actor, it seems that all of that won't be available anymore.
More specifically, I a KbService in my app with a set of method to work with that Kb. I want to make it an actor on its own. For that i need to make all the method private or protected given that now they will be only called by my received method. Hence the to expose the set of available behavior.
Is there some best practice for that ?
To tackle this issue I generally expose the set of messages that an Actor can receive via a "protocol" object.
class TestActor extends Actor {
def receive = {
case Action1 => ???
case Action2 => ???
}
}
object TestActorProtocol {
case object Action1
case object Action2
}
So when you want to communicate with TestActor you must send it a message from its protocol object.
import example.TestActorProtocol._
testActorRef ! TestActorProtocol.Action1
It can become heavy sometimes, but at least there is some kind of contract exposed.
Hope it helps

Any way of appending to the act method in scala?

First off, I am new to Scala:
I am writing a logging facility in Scala that will simply be a class that extends the Actor class. This way a user can just extend this class and the logging features will be available. Basically, I want to write to a log file every time an actor that extends this class sends or receives a message. For clarification every actor will have its own log file which can be collated later. I am taking a Lamport clocks style approach to ordering the events by having each Actor (who extends this class) have their own time variable that gets updated on a message send-receive and the actor will compare the current time variable (simply a positive integer) with the sender's and update its time variable with the greater of the two.
For now I chose to make it a simple method like
sendMessage(recipient, message)
For sending messages. This will just log to the file that the actor is going to send a message to X.
Now, the part that I am stumped on is doing logging when receiving messages. When an actor gets a message I simply want to log this event in a format like
myLogFile.writeLine(self.ToString+": Got a message from "+X+" at time: "+messageSendTime+", processed the message at" +Math.max(myCurrTime+1, messageSendTime+1))
However I need to know who sent this message, unless I force upon the user to include this info (namely the sender's name, time variable, etc) in the messages themselves, it gets hard(er). Is there any way to get the reference of the actual sender? I want this to work with remote actors as well. The only way I can think of is if I append to the act method that the user defines in his/her class with some extra case statements like:
def act {
case => // the user's case statements
...
//somehow I append these statements to the end for the Logger class's use
case (LoggerClassRegisterInboundMessage, message, timeStamp)
InboundMessagesMap.put(timeStamp, message)
}
By having this functionality I can do all the logging "behind the scenes" with these hidden messages being sent whenever the user sends a message. However this only works if the sender also uses the Logging facility. So a more general question is: is there a way in Scala to get the name/toString of a sender in Scala regardless of the sender's class?
I'm actually OK with going with the assumption that every class that sends messages will extend the Logger class. So if anyone knows how to append to the act like or something similar to the above example I will be equally grateful!
As it was said in the comments, Akka is the way to go. It's so much more powerful than the current Scala Actor API which will become deprecated with 2.10 anyway.
But, to attack your specific problem, you could create a trait for actors which support logging, in a way similar to this (I don't know if this actually works, but you can try it):
trait LoggingActor extends Actor {
override def receive[R](pf: PartialFunction[Any, R]): R = {
//we are appending to the partial function pf a case to handle messages with logging:
val loggingPf = pf orElse {
case (LoggerClassRegisterInboundMessage, message, timeStamp) => {
//do somthing with this log message.
message //returning the unwrapped result afterwards
}
}
super.receive(loggingPf)
}
//overriding the send as well
override def !(msg: Any): Unit {
//Wrap it in a logging message
super ! (LoggerClassRegisterInboundMessage, msg, getTimestamp())
}
}
And you would create your actors with something like this:
val myActor = new MyActor with LoggingActor
Hope it helps !