Posting this here instead of the Unity forums simply because I really value some of the knowledgeable people on this forum.
Note that the code below is specific to C# (Unity).
So I have a server that uses an actor model with message passing, it's actually a fully distributed system. Message reliability is at most once. Any sequencing and additional reliability are handled at the business (game) logic layer.
On the client side I have a simple actor system which mirrors how the server works. So we have the same paradigm with the same rules end to end. For example sending a message from client to server uses the same api as sending server to server or server to client. There are a few minor differences but overall it's the same.
A bit more detail on the actual api as that will be important.
An actor has just one important method with the following signature:
void OnReceive(object message);
This method accepts messages and the user is then responsible for taking it from there and building whatever logic is required.
The actor system which manages everything has a static method to find any actor in the system (they are registered on creation):
static UntypedActor Find(string name);
Sending a message to an actor looks like this:
Sending a message to a remote actor:
Or just sending to the server without specifying an actor in which case a default routing mechanism kicks in:
Now on to the actual question. Given that a lot of people who use this will have existing systems in place, what is the most appropriate interface to existing code? I'm not out to force everyone into embracing the actor model end to end. (the context here is that this is a client for an open source server).
For incoming messages my first idea is to provide a callback api. A message gets delivered to an actor, and you can then do as much or little logic as you want in the actor, then fire a callback to pass data on to another part of your system.
For outgoing messages I'm thinking about sticking with the paradigm of always keeping message creation in the actor. So if you are off in say a chat gui, and want to send a chat message to your group, you might make a call like so:
ActorSystem.Find("ChatManager").Tell("you guys all suck I'm out","group");
The actor would take that message and then create a message the server understands and send it to the server.
I was also thinking about wrapping this type of call in a static method on the actor. Would make it easier to see what calls are available, and easier to document in code.
It's worth noting that messages are protocol buffers, and I've designed the message structure to model an entity component system. So the process for an end developer to design new messages is fairly simple. Actors do deal with composing messages, but the calls to serialize are abstracted into another layer. At some later date I might provide actual entity and component classes to abstract it a bit more, but right now that's not a priority.
Would love to get some feedback on the approaches outlined above.