Type safe actor messages

 One of my pain points with the actors library is how to handle replies to a message. The library provides the methods ‘!?’ and ‘!!’, but without type safety. Client code needs to cast the reply to the expected type:

 

 (actor !? MyMessage()).asInstanceOf[Boolean]

 

Also, it is hard to know what type the result should be. Even if all the messages an actor expects are located in one file, there’s no indication (other than comments) about what the reply type is.

 

Another issue is that if an actor does reply to a message, but the sender does not react to it, then it is kept in the sender’s mailbox and may interfere with future reacts or simply take up memory

 

To fix this, first, define a trait that tags the reply of an actor to a message:

 

trait Reply[T] {   
  def result
(a: Any): T = a.asInstanceOf[T]
}

 

And use it:

 

case class MyMessage() extends Reply[Boolean]

 

Now we can pimp the actors library and add methods that use this information.

·      !?! is like !?, but with the correct return type

·      !!! is like ! but always consumes the reply

 

class RichActor(self: Actor) {
  def 
!?![T : Manifest](msg: Reply[T]): T = 
    msg.
result((self !? msg))
    def 
!!![T : Manifest](msg: Reply[T]) = if(manifest[T].erasure == Void.TYPE) self ! msg else {
      val out 
= new OutputChannel[Any] {
        def receiver 
= null
        def forward
(msg: Any) = null
        def send
(msg: Any, replyTo: OutputChannel[Any]) = null
        def 
!(msg: Any) = null
      
}

      self.send
(msg, out)
    
}
  
}
}

 

Developer