I don't know the architecture in detail, but here's how I would explain it to myself:
The problem with Akka IO connector actors here is that they don't work in a request-response manner. And if you think about it - that makes sense, because TCP is not a request-response protocol. TCP doesn't even have a notion of message. From programmer's perspective TCP connection is just a pair of continuous byte streams - one in each direction. That's it.
Akka IO is a minimal actor layer on top of network protocols, so it's not surprising that it mimics this behaviour. When TCP actor receives some data from the network, it only knows one thing - that it should send a Received
message to the actor that originally sent the Connect
message. That's all. It has no idea that the data it received from the network is somehow related to the data that you sent earlier.
Adding to all of that, ask
pattern works only under assumption that when you send message A
to some actor, it will respond with the message B
by sending it exactly to the sender of message A
. As we already know, TCP actor doesn't do that - it simply sends everything to the sender of original Connect
message.
The reason why this assumption is required is that ask
pattern actually creates some sort of a "phantom" actor that is set as the sender of the message sent using ask
. This "phantom" actor will then receive the response and invoke all the callbacks registered on the Future
. As a side note - be aware that those callbacks are invoked completely independently of the sending actor, i.e. they may run concurrently to it!
So, I would finally conclude that the ask
pattern used like this will not work with Akka IO, because it's simply too low level for such an abstraction. If you still want it, you need to create you own layer of abstraction on top of Akka IO, e.g. some simple intermediate actor that covers TCP connector actor and implements the request-response behaviour.