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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With