Syntax to dynamically add mixin to an actor - scala

I have an actor that sends messages to another actor. It also creates this other actor and does not know its type at compile time. On creation it needs to add a mixin. I am wondering how to solve this syntactically. So for example if we have:
trait MyMixin extends Actor {
abstract override def receive = {
case msg =>
// Do something
super.receive(msg)
}
}
class Sender(targetClass: Class) extends Actor {
// Here I want to create the actor such that I can add the mixin
// eg. If I knew the class at compile time I could do the following:
// val target = context.actorOf(Props(new TargetActor with MyMixin))
val target = context.actorOf(Props(???))
target ! someMsg
...
}
So the question is how to combine the two classes for a run time creation?
Thanks
Des

Related

Scala: How to extend an Akka actor?

I wrote an Akka base-actor that can handle some common messages. I want to reuse this basic behavior in a sub-actor, by extending the base-actor (not by composition of the base-actor).
I have seen several approaches in previous questions. They are all valid but also may be improved:
How extend behaviour of super actor in akka
and
How do I best share behavior among Akka actors?
To make the implementation cleaner, I am trying to achieve the following:
When defining the sub-actor, I try to extend only the base-actor (not both Actor and sub-actor). However, I was not able to force the compiler to do this.
I also try to not rename the receive partial function, because it is a kind of convention.
Here is a sample of my implementation:
//This is the base-actor that implements the common behavior
trait BetterActor extends Actor {
abstract override def receive = {
super.receive orElse { case _ => println("Missing pattern!") }
}
}
//This is the actor that implements the additional behavior.
//I actually wanted to extend BetterActor. It was not possible.
class MyActor extends Actor {
def receive = {
case i: Int =>
println(s"Yay!!! Got $i")
}
}
Here are two alternative ways how I can create an instance of the sub-actor, which combines both the common and the additional behaviors:
//1.
val myBetterActor = system.actorOf(Props(new MyActor with BetterActor), "myBetterActor")
//2.
class MyBetterActor extends MyActor with BetterActor
val myBetterActor = system.actorOf(Props[MyBetterActor], "myBetterActor")
Finally, I may invoke the sub-actor by:
myBetterActor ! 2
myBetterActor ! "a"
Problems with my implementation:
When I create an instance of the sub-actor, only then I can mix in the base-actor, either directly (1) or by defining a new class that mixes in the base-actor.
Like I said before, I would prefer to mix in the base-actor when I define the sub-actor. Not when I try to create an instance of the sub-actor.
P.S. It's fascinating that the designers of this framework did not see it necessary to make this common requirement easy to accomplish.
i suppose as long as you're not trying to override behavior with BetterActor, you could try something like this:
trait BetterActor extends Actor {
override def unhandled(message: Any): Unit = message match {
case e: CommonMessage => println("COMMON!")
case e => super.unhandled(e)
}
}
class MyActor extends BetterActor {
override def receive = {
case i: Int => println(s"Yay!!! Got $i")
}
}

How to construct an actor together with its wrapper?

I'm trying to write an actor called ActorManager which wraps another actor called RealActor. The idea is that the ActorManager can process all messages going in and out of RealActor, allowing to add additional logic like filtering or buffering. The outside world is supposed to communicate with the RealActor only through its manager, much like in real world.
A first draft would look like this:
class ActorManager(realActor: ActorRef) extends Actor {
def receive = {
case _ => { /* pre-process messages */ }
}
}
class RealActor(actorManager: ActorRef) extends Actor {
def receive = {
case _ => { /* actual business logic */ }
}
}
This however raises the question how to construct both actors at once, or more specifically how to define the corresponding Props given the circular dependency of the two actors. I'm not sure if the general lazy val pattern is applicable when defining Props.
I also would like to avoid the work-around of constructing one of the two first, combined with introducing an explicit Register protocol to connect them.
Such a case is much better solved by using an actor hierarchy instead of plain actor siblings. Since the main intent here is to hide the RealActor from the outside world, it makes much more sense that its ActorRef is accordingly wrapped/owned by the outer ActorManager.
This means that the RealActor reference has to be created within the ActorManager scope. This can be achieved by passing the parent an ActorRef => Props function, allowing to create the child actor:
// Parent
class ActorManager(getRealActorProps: ActorRef => Props) extends Actor {
val realActor = context.actorOf(getRealActorProps(self))
def receive = {
case _ => { /* pre-process messages */ }
}
}
// Child
class RealActor(actorManager: ActorRef) extends Actor {
def receive = {
case _ => { /* actual business logic */ }
}
}
object RealActor {
def propsActorManager(getRealActorProps: ActorRef => Props) =
Props(new ActorManager(getRealActorProps))
def propsRealActor(actorManager: ActorRef) =
Props(new RealActor(actorManager))
def props() =
Props(new ActorManager(actorManager => propsRealActor(actorManager)))
}
Note that it is now even possible to hide the fact that the RealActor is wrapped by providing an appropriate props definition, which builds the ActorManager -> RealActor hierarchy implicitly.
See also this blog post why flat actor hierarchies are considered an anti-pattern.
Something of this sort may work well for you:
import akka.actor._
class Manager extends Actor {
def realActor: ActorRef = context.child("real")
.getOrElse(context.actorOf(RealActor.props, "real"))
override def receive: Receive = {
case msg ⇒ realActor forward msg
}
}
object RealActor {
def props: Props = Props(new RealActor)
}
class RealActor extends Actor {
override def receive: Receive = {
case _ ⇒
}
}
Creating child actor through parent's context seems to be sufficient for creating parent-child hierarchy. The parent can be obtained by calling context.parent in child actor.

Mixins with Akka

I have an actor to which I want inject dependency using mixin. Code:
trait ProductsAware {
def getProducts: List[Product]
}
trait MyActor extends Actor with ProductsAware {
val products = getProducts
...
}
As you can see I'm just trying to decouple MyActor from concrete instance of ProductsAware trait, and provide concrete instance in other place (when creating actor).
And this is concrete implementation of ProductsAware trait:
trait ProductsAwareFirstImpl {
override def getProducts = {List(new Product())}
}
And I want to create new MyActor and inject to MyActor this concrete implementation ProductsAwareFirstImpl:
system.actorOf(Props[MyActor])
The problem is that is not safe at compile time, i.e. anyone can forget to mix the ProductsAwareFirstImplto MyActor
You can use a different Actor Props construction technique, namely the Props(new Actor) as documented here. Just make sure you are careful and not closing over any state, e.g. putting it in a object and calling it via a method should be safe. This is described in the documentation, but a quick mockup would look like this:
object MyActor {
def newActorWithFirstImpl = new MyActor with ProductsAwareFirstImpl
}
//...
system.actorOf(Props(MyActor.newActorWithFirstImpl))
To be sure that some trait is mixed to you actor you may user explicit self type reference:
trait MyActor extends Actor {
self: ProductsAware =>
val products = getProducts
// ...
}
So no one could instantiate MyActor without mixin ProductsAware

Strategy pattern in Akka

This is an continuation of my previous question How do I get around type erasure on Akka receive method
I have 10 type of events which extends from Event that I need to handle.
I want to implement business logic for each event in separate trait, because because mixing all 10 event handler functions will produce several hundreds(if not thousands) lines of code.
I don't want to create different Actor types for each event. For example:
class Event1Actor extend Actor{
def receive ={
case Event1(e) => //event1 Business Logic
}
}
class Event2Actor extend Actor{
def receive ={
case Event2(e) => //event2 Business Logic
}
}
and the same Event3Actor, Event4Actor,etc....
Such code seems ugly to me, because I need to implement business Logic inside each Actor.
Implementing 10 different traits and 10 different Actor classes seems also as bad design.
I'm seeking for some kind generic solution based on design pattern, for example strategy pattern.
case class EventOperation[T <: Event](eventType: T)
class OperationActor extends Actor {
def receive = {
case EventOperation(eventType) => eventType.execute
}
}
trait Event {
def execute //implement execute in specific event class
}
class Event1 extends Event {/*execute implemented with business logic*/}
class Event2 extends Event {/*execute implemented with business logic*/}
hope this is what you are looking for and helps, I have used this patternt to remove the redundant amount of actors wrapping all actions under a single actor executing different type of events.
You could try something like this, which involves auto-composing receive functionality via a base trait. First the code:
case class Event1(s:String)
case class Event2(i:Int)
case class Event3(f:Float)
trait EventHandlingActor extends Actor{
var handlers:List[Receive] = List.empty
override def preStart = {
val composedReceive = handlers.foldLeft(receive)((r,h) => r.orElse(h))
context.become(composedReceive)
}
def addHandler(r:Receive) {
handlers = r :: handlers
}
def receive = PartialFunction.empty[Any,Unit]
}
trait Event1Handling{ me:EventHandlingActor =>
addHandler{
case Event1(s) => println(s"${self.path.name} handling event1: $s")
}
}
trait Event2Handling{ me:EventHandlingActor =>
addHandler{
case Event2(i) => println(s"${self.path.name} handling event2: $i")
}
}
trait Event3Handling{ me:EventHandlingActor =>
addHandler{
case Event3(f) => println(s"${self.path.name} handling event3: $f")
}
}
So you can see in the EventHandlingActor trait we set up a List of type Receive that can be added to by each specific handling trait that we stack into a concrete actor. Then you can see the definitions of the handling functionality for each event defined in a separate trait that is calling addHandler to add another piece of handling functionality. In preStart for any kind of EventHandlingActor impl the receive functions will be composed together with receive being the starting point (empty by default) before hot-swapping out the receive impl with context.become.
Now for a couple of impl actors as an example:
class MyEventHandlingActor extends EventHandlingActor
with Event1Handling with Event2Handling with Event3Handling
case class SomeOtherMessage(s:String)
class MyOtherEventHandlingActor extends EventHandlingActor with Event1Handling{
override def receive = {
case SomeOtherMessage(s) => println(s"otherHandler handling some other message: $s")
}
}
The first one only handles events, so all it needs to do is define which ones it handles my mixing in the appropriate traits. The second one handles one type of event but also some other message that is not an event. This class overrides the default empty receive and provides functionality to handle the non-event message.
If we tested the code like so:
val system = ActorSystem("test")
val handler = system.actorOf(Props[MyEventHandlingActor], "handler")
handler ! Event1("foo")
handler ! Event2(123)
handler ! Event3(123.456f)
val otherHandler = system.actorOf(Props[MyOtherEventHandlingActor], "otherHandler")
otherHandler ! Event1("bar")
otherHandler ! SomeOtherMessage("baz")
Then we would see output similar to this (with the order changing due to asynch handling of messages):
otherHandler handling event1: bar
handler handling event1: foo
handler handling event2: 123
handler handling event3: 123.456

Testing preStart function of Akka actor

There is parent actor which in preStart creates child actors, one for every "active" user. Now I'd like to write a test asserting that it really happens, I mean child actors are really created for preconfigured users.
class IntegrationActor(settingsDao: UserSettingsDAO, childMaker: ActorRefFactory => UserId => ActorRef) extends Actor with StrictLogging {
val createUserActor = childMaker(context)
override def preStart(): Unit = {
val e = settingsDao.findAllEnabled()
e.map(_.userId).foreach(createUserActor)
}
// ...
}
I have test like this, but it doesn't work as all is happening off-main-test-thread
// mockMaker is already defined/mocked
it should "create child actors for users with enabled integration when started" in {
// given
val us = UserSettings(...)
Mockito.when(settingsDao.findAllEnabled()).thenReturn(Set(us))
// when
system.actorOf(Props(new IntegrationActor(settingsDao, mockMaker)))
// then
verifyMockMakerCalledFor(us)
}
I was trying to assign CallingThreadDispatcher to parent actor, but with no luck.
Theoretically I could just new this class and test it as usual, but Actor's can't be new-ed by hand.
Is there any other way to do this other than extracting stuff to trait with self type being Actor? Not sure it's the right way.