Is it possible to send a message to all actors in an actor system? I've been looking at the Broadcast router example, but that is so marginal I can't comprehend how I add actors to the router dynamically.
We are using scala for akka.
Thanks!
system.actorSelection("/user/*") ! msg
Selects all children of the guardian and sends them the msg.
If you want send a message to all actor who are dynamically created, you can use eventBus
I personally use the system.eventStream for my case.
From an actor, you can send to everyone :
context.system.eventStream.publish(StatisticsMessage())
or directly with system.
actor must subscribe with :
context.system.eventStream.subscribe
I extends from :
trait SubscriberActor extends Actor {
def subscribedClasses: Seq[Class[_]]
override def preStart() {
super.preStart()
subscribedClasses.foreach(this.context.system.eventStream.subscribe(this.self, _))
}
override def postStop() {
subscribedClasses.foreach(this.context.system.eventStream.unsubscribe(this.self, _))
super.postStop()
}
}
Related
In my Scala application say I have Actor A and Actor B. I want to devise a test case in ScalaTest that would allow me to send a message to Actor A and see what message it sends to Actor B in order to see if A is properly processing it's data and sending the right message to B. How would one test this? It took me a long time to get this cooked up on my own...but it does seem to mostly work.
class A extends Actor { ... }
class B extends Actor { ... }
class C(p: TestProbe) extends B {
override def receive = {
LoggingReceive {
case x =>
println(x.toString)
p.ref ! x
}
}
}
case class MsgToB(...)
// Spec class which extends TestKit
"A" should {
"send the right message to B" {
val p = TestProbe()
val a = TestActorRef[A]
val c = TestActorRef(Props(new C(p)))
// Assume A has a reference to C. Not shown here.
a ! msg
// Assert messages
p.expectMsgType[MsgToB]
}
}
Is this the best means of doing this? Is there a better practice?
To me it sounds like what you want is to test the behaviour of actor A in isolation. In order to do this, you need to be able to control how actor A gets its reference to actor B. For example, you could provide the reference in the actor's constructor:
import akka.actor.{Actor, ActorRef, Props}
class A(refToB: ActorRef) extends Actor { ... }
object A {
def props(refToB: ActorRef): Props = Props(new A(refToB))
}
There are alternative ways you can pass the reference to actor B to actor A, but using the constructor is arguably the easiest choice. In the example above, we also provide a method for creating the correct Props for the actor.
Now that you can control the reference to actor B, you can replace the actor reference with test probe in tests.
import akka.testkit.TestProbe
// Initialise a test probe
val probe = TestProbe()
// Actor A with reference to actor B replaced with the test probe
val a = system.actorOf(A.props(probe.ref))
// Send a message to actor A
a ! someMessage
// Verify that the probe received a correct response from actor A
p.expectMsgType[MsgToB]
Notice that I created the actor using the actor system from the TestKit instead of using the TestActorRef. This means that the actor message processing will be asynchronous instead of synchronous. Personally, I've found the asynchronous testing style to be a better fit because it better represents how the actor is run in a production system. Asynchronous testing is also recommended in the official documentation.
I want to log all received messages to all actors in my Akka app.
There is a config akka.actor.debug.receive that will log all messages sent to an actor if that actors receive method is a LoggingReceive.
According to http://doc.akka.io/docs/akka/current/additional/faq.html it means wrapping all receive methods with LoggingReceive as in How to log all incoming messages from Akka (Java)
def receive = {
LoggingReceive {
case x ⇒ // do something
}
}
Is there a way to do this implicitly, or by config?
Not that I know of, but you should very easily be able to do something like this:
trait LoggingReceiveActor extends Actor{
def receive = LoggingReceive(loggedReceive)
def loggedReceive:Receive
}
class MyActor extends LoggingReceiveActor{
def loggedReceive = {
case _ =>
}
}
Any actor that inherits from LoggingReceiveActor now has to provide an impl for loggingReceive and if you do that, then when debug logging is enabled then this kind of actor will log the messages received.
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
Now, I am asked to add logging function in akka's actor.
When a message is received, before it is handled, this message should be written into log.
And before a message is sent out, this message should be logged first.
I think I should override the receive and send functions in Actor. Suppose I create a trait actorlog which extends Actor. And class myActor extends actorlog. But in myActor, I need to override receive function (it seems it causes problems here). So I am confused what I should do.
PS. I know akka provides logging. But now I need implement this function by myself.
There is a utility to get logging of the received messages in Akka. It's briefly mentioned in the logging documentation. Basically you wrap your receive function in it like this:
def receive = LoggingReceive {
// your normal receive here
}
And then you enable it in your config with:
akka.actor.debug.receive=on
The information will be logged at debug level.
Besides the other answers here, another approach is to use orElse to prepend a partial function to your receive. In that partial function, put the logging in isDefinedAt so it gets called on every message.
For example:
trait ReceiveLogger {
this: Actor with ActorLogging =>
def logMessage: Receive = new Receive {
def isDefinedAt(x: Any) = {
log.debug(s"Got a $x")
false
}
def apply(x: Any) = throw new UnsupportedOperationException
}
}
class MyActor extends Actor with ActorLogging with ReceiveLogger {
def receive: Receive = logMessage orElse {
case ...
}
}
Using orElse is a general approach for composing receive behavior. In most cases I am composing things like this:
def otherBehavior: Receive = {
case OtherMessage => ...
}
class MyActor extends Actor {
def receive = otherBehavior orElse {
case ...
}
}
A good example of the stackable traits approach can be seen in this presentation: http://www.slideshare.net/EvanChan2/akka-inproductionpnw-scala2013
use stackable modificator abstract override for stackable call of receive method.
use new feature of Akka: event-sourced actor system (docs here).
All the tutorials that I have read work like this:
class HelloWorldActor extends Actor {
def receive = {
case "Hello" => self.reply("World")
}
}
val myActor = system.actorOf(Props[MyActor], name = "myactor")
I am wondering if AKKA supports the act() function inside an Actor class like this:
class HelloWorldActor extends Actor {
def act() = {
}
}
And then you can call:
val myActor = new HelloWorldActor
myActor.start()
I want to do this because my actor won't be receieving any messages. It just works on its own. So can I use the act() function inside my AKKA actor?
In Akka, your actor should start automatically after creation using the system. But it sounds as if you want to use the actor like a plain thread we all know from Java. I would say that this is not the right way from an idiomatic point of view. You can of course just add a start message to your actor, send it to the actor after creation, and do your processing in the handler. But perhaps you should consider using a plain thread or a Future instead of an actor if you do not want to react on any message?