On typed Actor interaction patterns

I discovered Akka relatively recently, and after reading the great “Akka in Action” book and various other materials, I’ve finally been dipping my toes into some coding. I’ve skipped starting to code with classic actors, in favour of typed actors.

When thinking about how to code some toy actors, one thing that has confused me somewhat is the the guidance around “Request-Response” and “Adapted Response”, described in Actor interaction patterns

In thinking about this myself, I think I have arrived at a correct understanding now, but would be happy for someone to give me some confirmation or denial :slight_smile:

The following are the points in the documentation that initially surprised me (but it’s likely I’ve not correctly understood their meaning in this context):

  1. “Actors seldom have a response message from another actor as a part of their protocol”

  2. “Most often the sending actor does not, and should not, support receiving the response messages of another actor.”

My perspective is, if one actor is to send messages to another actor via that other actor’s protocol, why wouldn’t, and shouldn’t, this sending actor also support receiving the response portion of that other actor’s protocol? (If you ask me my name, you would and should be prepared for me to reply back to you with a response)

I see some examples of this “Request-Response” pattern in the documentation examples, such as the Gabbler using the ChatRoom’s protocol. (The Gabbler object imports ChatRoom._, and can thus send PostMessages to ChatRoom, and it receives response messages of ChatRoom’s protocol as well.)

However, I do see that it is perhaps odd (and constraining?), that the Gabbler’s Behavior is of type “SessionEvent”, which is of the ChatRoom actor protocol - not of its own.

Is it the Actor’s Behavior being typed of messages of another actor’s protocol which is the crux of the issue?
Because I can imagine that if the typed actor needs to accept both messages of its own protocol, in addition to communicating with other actors via their protocol, then that could be when the “Adapted Response” interaction pattern is useful to employ? (This would certainly seem to be a common situation for a system with a number of actors collaborating together.)

So, might I conclude that an Actor involved in different types of request-response protocols might typically, and justifiably, feature both:

  • “Request-Response” style interaction (when viewed from its own perspective, as its “primary” protocol) - e.g. when it acts as the message recipient / responder
  • “Adapted-Response” style for initiating communication with other Actors (when acting as the requester / response receiver)

?

PS - akka is fantastic!

1 Like

Having the protocol of an actor A include a message that is defined for another actor B creates a cyclic dependency between the two. A is a client of B but B also has a source dependency on A.Command for one of its responses.

Cyclic dependencies is always a bit messy, a directed graph of dependencies in your code is easier to understand and reason about. They also makes it impossible to move the actors to different modules if a project outgrows being a single codebase.

In some cases a set of actors form a component of some sort, where they are intended to always be run together and some of them perhaps not even interacted with from outside. In such case the cyclic dependency may be more acceptable.

With union types coming in Scala 3 accepting the actors own protocol and some additional response messages may become nicer, see Eric Lootz recent article here: https://www.lunatech.com/2020/02/using-dotty-union-types-with-akka-typed/
You would likely want to hide the fact that the actor accepts the response messages though, this should be possible using .narrow so that the public API of the actor still is Behavior[A.Command].

1 Like

Thank you for the response, I will keep those points in mind as I build up some more practical experience with Actors.

I also spotted Eric’s interesting Part II post: https://www.lunatech.com/2020/02/using-dotty-union-types-with-akka-typed-part-ii/

Revisiting my old comment here, having come to, I think, a better understanding now. Just in case any others might find it useful.

The Style Guide’s Where to define messages helped things click for me, as it introduces the notion of a shared protocol object, in addition to the style of defining the protocol in an actor’s companion object.

It seems the protocol-in-companion-object style is preferred, but knowing that the shared protocol object style is also an option helped to clarify.

The ideas in Public versus private messages relating to the shared protocol object style, around using a type-hierarchy with narrow to restrict the public messages also became clear, after actually implementing some timers and using the TestKit to have my actors under test return private messages regarding their state. Very useful technique indeed.