In Akka, is there a way to restrict messages to actors to be of a specific static type other than using the "Typed Actor" APIs that use an RPC style programming model?
Can I use the message passing style with Akka without throwing away static type safety at the actor boundaries?
For example, I'd like to use code like this:
sealed abstract class FooMessage case object Foo extends FooMessage case object Bar extends FooMessage class FooActor extends Actor[FooMessage] { def receive = { case Foo => () // OK // Would raise a compiler error: // case s: String => error("Can't happen, String is not a subtype of FooMessage") } } val fooActor = actorOf[FooActor] fooActor ! Foo // OK // Won't compile: fooActor ! "Hello"
Perhaps one would have to extend some base trait or have a construct like Either
to allow for system level messages (Exit
, etc.).
java.io.Serializable. An ActorRef is the identity or address of an Actor instance. It is valid only during the Actor’s lifetime and allows messages to be sent to that Actor instance.
Akka “Typed Actors”, now replaced by Akka Typed, were an implementation of the Active Objects pattern. Essentially turning method invocations into asynchronous dispatch instead of synchronous that has been the default way since Smalltalk came out.
Akka is a toolkit for building highly concurrent, distributed, and resilient message-driven applications for Java and Scala. Akka Insights is intelligent monitoring and observability purpose built for Akka.
Then you'd have to encode the message type into the Actor ref, which would drastically decrease the value of something like the ActorRegistry.
Also, with powerful mechanics like "become" (which is fundamental to the actor model) typing the messages is less valuable.
Since Akka doesn't leak memory when a message is not matched to the current behavior, there is not the same risk of sending the "wrong" messages to the "wrong" actor.
Also, Actors are by nature dynamic, so if you want to make them static, use TypedActor (which is not RPC, it's just as RPC as regular actors, void methods are ! calls, Future return type is !!! and other return types are based on !!)
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.
Does that help?
In Scala stdlib there was an excuse for making basic actors untyped (which is not applicable to Akka, because it doesn't support nested receives, as I remember). Lift, in its turn, supports typed actors out-of-the-box.
However, using channels, it's still possible to create strongly typed actors with stdlib:
object TypedActor { def apply[A](fun: PartialFunction[A, Any]): OutputChannel[A] = { val sink = new SyncVar[Channel[A]] actor { val in = new Channel[A](self) sink set in loop { in react { case any => reply(fun(any)) } } } sink.get } } sealed abstract class FooMessage case object Foo extends FooMessage case object Bar extends FooMessage object Test { val fooActor = TypedActor[FooMessage]{ case Foo => println("OK") } fooActor ! Foo fooActor ! "Hello!" // doesn't compile -> Type mismatch; found: String("Hello!"); required: FooMessage; }
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