I have an actor definition as follows:
class ClientHandler(connection: ActorRef) extends Actor {
def receive = {
case Received(data) => {
val clientId = data.utf8String.stripLineEnd
Connector.saveConnection(clientId, self)
context.become {
case msg: ByteString => connection ! Write(msg)
case Received(msg) => connection ! Write(msg)
}
}
case None =>
}
}
There is a parent actor that is listening for clients that want to connect to a TCP server. Once a client connects, the parent actor instantiates a ClientHandler
and gives it the original connection so that the ClientHandler
can talk to the connected client directly.
There is another actor that pushes notifications to clients. That actor looks up clients by ID via Connector that returns an ActorRef
to an instance of ClientHandler
and then sends a ByteString using the !
operator. Like this:
val clientConn = Connector.getConnection(userId)
clientConn match {
case Some(conn) => conn ! payload
case None =>
}
I was pretty sure that whenever such a notification is pushed I can receive it in ClientHandler
using the case Received(msg)
within the become
block, but it didn't work. Instead the case msg: ByteString
works, but I don't understand why and what the difference between those two is.
I read the documentation for the Received
method and it says Whenever data are read from a socket...
does it mean that the Received
method will be matched only when the remote client writes something (because he writes to a socket), but when another actor (in this case one that is running on the same machine; where does this write go if not to a socket too?) writes something the case msg: ByteString
will be matched?