Akka, Generic ActorRef? - scala

I'm rather new to Scala so this may be a trivial question. I'm trying to put together a simple project in Akka and I'm not sure how to handle a situation where I need to store a reference to an actor of a constrained type.
Let's assume I have an actor trait
trait MyActorTrait extends Actor
Then somewhere else I would like to define another trait with a member
def reference: ActorRef[MyActorTrait]
That obviously doesn't work since ActorRef doesn't care about the target actor's type (or does it?). Is there any way to constrain the reference to only accept references to actors that extend MyActorTrait?

By design, there is no way you can access the underlying Actor through ActorRef (or, pretty much, any other way). So, constraining the type like you describe is pointless, there would be absolutely no difference in what you can do with ActorRef[Foo] vs. ActorRef[Bar].
Not saying, this is a good thing (few things in Akka can be characterized that way IMO), but that's just the way it is.

The way you try to reference an actor in another actor is not right. Actors form a hierarchy. So it gives you a path to refer an actor. There are mainly three ways you could reference another actor using
Absolute Paths
context.actorSelection("/user/serviceA")
Relative Paths
context.actorSelection("../brother") ! msg
Querying the Logical Actor Hierarchy
context.actorSelection("../*") ! msg
You may have a look at the doc - https://doc.akka.io/docs/akka/2.5/general/addressing.html.

After some digging around I believe I've found a way.
First I create a trait which will preserve the actor type
trait TypedActorRef[T <: Actor] {
def reference: ActorRef
type t = T
}
Then implement a generic apply which instantiates a private case class extending the trait
object TypedActorRef {
private case class Ref[T <: Actor] (reference: ActorRef) extends TypedActorRef[T]
def apply[T <: Actor](actor: T) = {
Ref[T](actor.self)
}
}
With that I can keep a reference which is restricted an actor of the type I want.
trait OtherActor extends Actor
trait MyActor extends Actor
{
def otherActorsReference: TypedActorRef[OtherActor]
}
This seems OK to me, at least this seems not to upset the compiler, but I'm not sure if this solution prevents from creating other extensions of the TypedActorRef which may not respect the same constraints.

Related

Importing Scala companion object in file where it is defined

I have a ThisThing.scala file containing:
class ThisThing() extends BaseThing[ThisEvent, ThisState]
object ThisThing {
sealed trait ThisEvent
case class Load(uuid: UUID) extends ThisEvent
case object Stop extends ThisEvent
sealed trait ThisState
case object Loading extends ThisState
case object Loaded extends ThisState
}
Where ThisThing needs to be parameterized by the types of event and state it handles. This requires also having an import:
import ThisThing._
Which feels really strange, to have to import something from the same file. I'm guessing I'm doing something non idiomatic and that there is a better way to structure it?
It's a bit strange, but in principle valid.
It's non-idiomatic, because you are trying to hide ThisEvent and ThisState inside ThisThing's companion object, but at the same time you expose these types in the signature of ThisThing ... extends BaseThing[ThisEvent, ThisState].
The problem is that not only you, but also every user of ThisThing will have to unpack ThisThings companion object in order to write down the type BaseThing[ThisEvent, ThisState]:
// much later, in someone else's code in a galaxy far, far away
import foo.bar.baz.ThisThing.{ThisEvent, ThisState} // awkward to use!
val t: BaseThing[ThisEvent, ThisState] = new ThisThing
So... If you think that someone will want to access ThisEvent and ThisState later, then move them out of the ThisThing companion.
If you think that nobody should even know that ThisThing is actually a
BaseThing[X, Y], then you have an abstraction leak anyway, and you could handle it by declaring ThisThing as a trait, and then implementing a concrete class that extends both ThisThing and BaseThing inside the ThisThing's companion object, so that BaseThing does not leak to the outside.
To summarize, it's one of two scenarios:
Scenario 1: BaseThing[ThisEvent, ThisState] should be visible from the outside. In this case, ThisEvent and ThisState are buried a bit too deep in the companion object, and are therefore awkward to access.
Scenario 2: BaseThing[ThisEvent, ThisState] is an abstraction leak.
Just a random guess: If you just want to parameterize something like an Akka FSM, leave it as it is now. I think it's common, because nobody outside should really care how an actor is actually implemented. It's impossible to obtain an explicit reference to ThisThing anyway, because all you ever see are the ActorRefs, so that the actual instance is hidden. In this case the "abstraction leak" isn't too critical, because nobody ever sees an actual instance of your FSM.

Can we define trait inside a object in scala

I just started to learn scala and currently learning about Akka through this Learning Akka course
I'm confused about the code style, the author has created a trait inside a object.
object MusicController {
sealed trait ControllerMsg
case object Play extends ControllerMsg
case object Stop extends ControllerMsg
def props = Props[MusicController]
}
I understand that Scala object provides singleton ability and a way to define all static method in class through companion object.
Can anyone help me understanding this syntax ? Thanks
You will often see this with Actors. It is good practice to define the messages that an Actor responds to in its companion object, which happens here.
The sealed trait part isn't really necessary. You just often see this in Scala with case classes/objects. Also, being sealed means that you will get a warning if your match is not exhaustive when you pattern match on instances of it.

Why is receive called a method?

The Akka docs call Actor's receive as a method. But as per the API it is a abstract type member rather than an abstract method. Any reason why receive is termed as a method?
Yeah, docs could be improved a bit.
If you take a look into the Actor trait, you will notice that receive is indeed a method. The Actor.Receive in its signature is the type member you are referring to, defined in the Actor object.
So, receive is an abstract method that every Actor needs to implement. Its type is partial function; you can easily tell because it takes a bunch of case statements, e.g.
def receive = {
case "test" => log.info("received test")
case _ => log.info("received unknown message")
}
Each case statement takes Any and returns Unit, so the actual type of the partial function is PartialFunction[Any, Unit]. For clarity and simplicity, Akka guys decided to create a placeholder for that particular type, they called it Receive and they put it in the Actor companion object.
Small digression: a lot of folks are not really happy with messages being of type Any and Akka guys have promised to introduce typed messages; not sure if they delivered it yet in the latest release though.

Scala: Dispatch

I'm willing how to implement an extensible dispatch mechanism in Scala.
For example:
I have a trait called Sender (with a method 'send') and a bunch of classes that implement that trait (MailSender, IPhoneSender, AndroidSender). On top of them there is a class which implements the same trait but dispatches the message to the above senders depending the type of the message.
I know I can use pattern matching, but my problem with that approach is about extensibility: If someone wants to add another sender (i.e. WindowsPhoneSender), he must add a new case to the pattern matching method (thus breaking the open-closed principle). I don't want developers to modify the library's code, so I need this to be as extensible as possible.
I thought about a chain of responsibility approach (in Java I would do that), but is there a better way in Scala? (My knowledge in Scala is limited, but I know the Scala compiler does a lot of magical things)
Thanks!
It would be clearer if you gave a more concrete use case, but you might be looking for the typeclass pattern:
case class AndoidMessage()
case class WindowsMessage()
trait Sender[M]{
def send(message: M)
}
implicit object AndroidSender extends Sender[AndroidMessage]{...}
implicit object WindowsSender extends Sender[AndroidMessage]{...}
def mySendMethod[M: Sender](message: M) = {
// use the implicit Sender[M] to send the message
}
//AndroidSender is resolved implicitly
mySendMethod(new AndroidMessage())
//third party can define their own message and their own
//implicit sender for it (perhaps in a companion object
//so it's resolved automatically)
case class BeosMessage()
object BeosMessage{
implicit object BMSender extends Sender[BeosMessage]{...}
}

Cake pattern w/ akka: Providing implicit actorSystem to several layers

I'm currently baking my first cake pattern, so please bear with me.
I took my working monolithic app and I cutted it into functional layers. The cut looks clean but resulted in two of the layers that depend on an implicit ActorSystem.
I tried to solve this dependency like this:
trait LayerA {
this: ActorSystemProvider =>
private implicit val implicitActorSystem = actorSystem
import implicitActorSystem.dispatcher // implicit execution ctx
...
}
... and similarly for LayerX
My assembly class looks like:
class Assembly extends LayerA with LayerB with LayerX with ActorSystemProvider
where ActorSystemProvider simply instantiates the actor system.
This does not work given that the ActorSystem does not exist when the dependencies are resolved and the val's are instantiated, resulting in a NPE. This also looks really ugly and I'm sure there has to be a nicer/easier way to deal with it.
How should I deal with shared implicit dependencies among layers when using the cake pattern, like ActorSystem in this case?
Thanks
Self types is not a requirement for building a caked architecture, actually i use self types only in cases when a trait is a component of a layer. So when i need to place some implicit into the scope (for example ActorRefFactory for Spray Client) i just mix a trait in :
trait ActorSystemProvider {
implicit def actorSystem: ActorSystem
}
And on the lowest layer (so called "end of the world") i have the following code structure:
trait ServiceStack
extends SomeModule
with SomeModule2
with SomeModule3
with ActorSystemProvider
object ServiceLauncher extends App with ServiceStack {
val actorSystem = ActorSystem("ServiceName")
}
It's an oversimplified example (if you want a great example of a real system build on top of a Cake Pattern then you should definitely take a look at the Precog system, example where different modules/layers connects), but not you can mix implicit ActorSystem when you need it.
If you can instantiate the vals lazily rather than eagerly, you can make the implicitActorSystem a lazy val instead of a val. So it only gets executed when it is accessed the first time. I think this should solve the problem of NPE.
(Another little known interesting fact posted by #ViktorKlang FYI: If the initialization of a lazy val throws an exception, it will attempt to reinitialize the val at next access.)
Another way would be to make each of your methods which need execution context accept an implicit executionContext like:
trait LayerA {
def getUser(id: Int)(implicit ec: ExecutionContext) = {
...
}
}