Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to restrict actor messages to specific types?

Tags:

scala

akka

actor

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.).

like image 477
mkneissl Avatar asked Apr 05 '11 06:04

mkneissl


People also ask

What is ActorRef in Akka?

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.

What is Akka typed?

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.

What is Scala Akka?

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.


2 Answers

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?

like image 80
Viktor Klang Avatar answered Sep 28 '22 04:09

Viktor Klang


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;  } 
like image 29
Vasil Remeniuk Avatar answered Sep 28 '22 02:09

Vasil Remeniuk