Where should actor messages be declared? - scala

I'm developing an application using Akka, and a thing that kind of bugs me the whole time regards message declaration with the Actor's. Where should I declare the messages? In the receivers companion object or the senders companion object or on some third place?

The Akka team recommends Message should be defined in the same place the props method should be: in the Receiver's Companion object because the Receiver implements the receive partial function and needs to know about all the messages it supports. Also, multiple senders can send a set of messages (implemented by the Receiver), so you cannot put it in one single sender.

If the official Typesafe Activator template activator-akka-scala-seed is of any importance regarding Akka's good practices the messages should be part of companion object as shown in the following PingActor actor (copied directly from the template):
package com.example
import akka.actor.{Actor, ActorLogging, Props}
class PingActor extends Actor with ActorLogging {
import PingActor._
var counter = 0
val pongActor = context.actorOf(PongActor.props, "pongActor")
def receive = {
case Initialize =>
log.info("In PingActor - starting ping-pong")
pongActor ! PingMessage("ping")
case PongActor.PongMessage(text) =>
log.info("In PingActor - received message: {}", text)
counter += 1
if (counter == 3) context.system.shutdown()
else sender() ! PingMessage("ping")
}
}
object PingActor {
val props = Props[PingActor]
case object Initialize
case class PingMessage(text: String)
}
Note PingActor that holds all the accepted messages by the actor (as you may've noticed it's not followed strictly since PongActor.PongMessage is also accepted, but not defined in the companion object PingActor).
From another question How to restrict actor messages to specific types? the Viktor said:
The common practice is to declare what messages an Actor can receive
in the companion object of the Actor, which makes it very much easier
to know what it can receive.

Related

Send message to parent actor in Akka Typed

Title is self-explanatory, I want to be able to send a message to a parent actor (meaning I want parent's ActorRef). In Akka Classic (untyped), the ActorRef for a parent actor can be obtained from the child's ActorContext via:
context.parent
(see, for instance, this question (in Java)).
However, the akka.actor.typed.scaladsl.ActorContext in Akka Typed does not expose an ActorRef for the parent. Is there an idiomatic means in Scala to obtain an ActorRef for the parent actor?
TLDR:
Inject the parent actor reference into the child when creating it.
Akka Typed enforces strict protocols, so you need to make it absolutely clear that "this actor talks to another actor". The accepted answer is a workaround (casting to classic and using the parent), but has its downsides: now you do not enforce types anymore.
Here is some code that should get you started. See how all the types are enforced. You can model the traits differently, but you should get the drift:
object ParentActor {
sealed trait Command
case class DoSomething() extends Command
// you do not have to do this, but creating another trait
// allows you to narrow the amount of messages the parent can receive from the child
sealed trait ChildNotification extends Command
case class MessageFromChild() extends ChildNotification
def apply(): Behavior[Command] = {
Behaviors.receive( (context, message) =>
message match {
case DoSomething() =>
// create a child that knows about its parent
context.spawn(ChildActor(context.self), "child")
Behaviors.same
case MessageFromChild() =>
context.log.info("I received a message from my child")
Behaviors.same
})
}
}
object ChildActor {
sealed trait Command
case class Work() extends Command
// inject the parent here (or any other actor that matches the signature)
def apply(parent: ActorRef[ParentActor.ChildNotification]): Behavior[Command] = {
Behaviors.receive( (context, message) =>
message match {
case Work() =>
// send message to parent actor (or any other actor with that type)
parent ! ParentActor.MessageFromChild()
Behaviors.same
})
}
}
By the way, I am using the "functional" syntax of akka typed, but you can use the more "object-oriented" syntax as well. It follows the same approach.
If you're in typed Akka, the only [Scala] type that could encompass ActorRefs of all possible parent actors is ActorRef[Nothing], which is an ActorRef you can't send messages to, so that's of limited utility.
At least for as long as the classic APIs exist:
import akka.actor.typed.scaladsl.adapter._
type ClassicActorRef = akka.actor.ActorRef
val parentActorRef = context.toClassic.parent
This will be an untyped ActorRef, i.e. you're free to send messages which the parent actor will never accept.
If you want a typed reference to an actor's parent, you'll need to embed that when spawning the child actor, just as if you want a typed reference to the sender of the current message you need to embed replyTos in your protocol.
(context.sender is absent in the typed ActorContext for the same reason that context.parent is absent; the workaround for replicating classic context.sender is analogous: context.toClassic.sender)

What happens to unmatched messages with Akka?

The Akka documentation says that the mailbox is NOT scanned for messages. Each message is handled after another (FIFO by default) in the order of their arrival. However, when I send a message from an actor to another which is not matched be the receiving actor, it is neither moved to the deadletters actor (which would appear in the log I suppose) nor does it block handling the next message in the mailbox which arrives one second later and can be handled correctly.
What does happen to the unmatched message from the mailbox?
I am using Scala 2.10.4 and Akka 2.4-SNAPSHOT in sbt.
package main.scala
import akka.actor._
class SRActor(dest: ActorRef) extends Actor with ActorLogging {
dest ! A
dest ! B
context.stop(self)
override def receive = {
case _ => {
log.info("Finally got something")
}
}
}
class SRActorReceiver extends Actor with ActorLogging {
override def receive = {
case B =>
log.info("Finally got B")
}
}
Actor creation:
package main.scala
import akka.actor._
case object A
case object B
object ErrorApp extends App {
// SR: Send nowhere received
var system6 = ActorSystem("ErrorActorSystem")
val srActorReceiver = system6.actorOf(Props(classOf[SRActorReceiver]), "sractorreceiver")
val sractor = system6.actorOf(Props(classOf[SRActor], srActorReceiver), "sractor")
// wait until actors have finished
Thread.sleep(1000)
system6.shutdown
Copied from docs
Please note that the Akka Actor receive message loop is exhaustive,
which is different compared to Erlang and the late Scala Actors. This
means that you need to provide a pattern match for all messages that
it can accept and if you want to be able to handle unknown messages
then you need to have a default case as in the example above.
Otherwise an akka.actor.UnhandledMessage(message, sender, recipient)
will be published to the ActorSystem's EventStream.
There is also unhandled method in Actor trait that you can override. (docs)
def unhandled(message: Any): Unit
User overridable callback.
Is called when a message isn't handled by the current behavior of the actor by default it fails with either a akka.actor.DeathPactException (in case of an unhandled akka.actor.Terminated message) or publishes an akka.actor.UnhandledMessage to the actor's system's akka.event.EventStream

Scala and Akka - Testing actors as a system with Akka Testkit

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.

Navigating the code of an actor system in Intellij IDEA

I use IntelliJ IDEA, but the question could relate to other IDEs. There is a great way to navigate the code with Ctrl+click. From the method call it jumps to the method declaration. It really boosts the productivity.
Actor systems are based on message passing. Example in Akka with Scala:
class MyMessage
object MyMessage
class MyActor1 extends Actor {
context.actorOf(Props[MyActor2]) ! MyMessage
}
class MyActor2 extends Actor {
def receive = {
case MyMessage =>
...
}
}
Is there a way to navigate in code between sending the message and receiving the message?
I mean clicking on ! will take me to the definition of ! method in ScalaActorRef, but that's 99% chance that I don't want that. Jumping to the corresponding receive method (or, if possible, to correct case: case MyMessage) would be more appropriate.
How do you navigate the code between actors?
I don't think it is possible in general because an actor can change its behavior at runtime, including what messages it can process - as opposed to methods which can be statically indexed. For example, receive function may be computed depending on the actor state:
class MyActor extends Actor {
var i = 0
def receive = firstReceive
def commonReceive = {
case Increment =>
i += 1
if (i % 3 == 0) context.become(firstReceive)
else context.become(secondReceive)
}
def firstReceive = commonReceive orElse {
case Ping =>
sender ! "zero"
}
def secondReceive = commonReceive orElse {
case Ping =>
sender ! "one or two"
}
}
Now the actor handles messages differently depending on which messages it handled before. And this is only a simple example - actual actor behavior may even be received from the outside!
case class Behavior(receive: Actor.Receive)
class MyActor extends Actor {
def receive = {
case Behavior(r) => context.become(r)
}
}
Another difficulty which is even greater is that you usually have an ActorRef to which you send messages with !. This ActorRef has no static connection with the actor class which contains message handling logic - it is instantiated with Props which can use arbitrary code to determine which actor class should be used:
val r = new Random
val a = actorSystem.actorOf(Props(if (r.nextInt(100) > 50) new FirstActor else new SecondActor))
a ! Message // which handler should this declaration lead to?
This makes finding actual message handler next to impossible.
If you think that it may be worth it to support simpler cases, like the one you provided, you can always submit a feature request to YouTrack.
Not perfect, but what could help would be to use Find Usage (Alt+F7) on the type of the message. For that you probably have to navigate to the type Declaration (Ctrl+Shift+B) first
I wonder if there is an easy way to create a shortcut for the combination.
Another idea would be to use the Structural Search which might be able to find things like excpressions, that match on the class name ...
Once you created a template to your liking you can then record a macro

Obtaining data from ActorRef in akka

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