I started playing with the Actor model, and in particular with Akka.NET. Overall I think I have a good idea of what's all about, but of course the devil is in the detail. I was thinking about adopting Akka.NET in an already existing codebase, and therefore I'd like to estimate how much of the existing abstractions can be kept. The idea is that some specific high-level interfaces could be kept, and some adapter implementations would be written to seamlessly go back and forth across the actors world and the users of the existing interfaces, but I'm not sure if that's recommended and what types of specific problems I should expect to face.
Trivial example:
public interface IGetSet<in TK, TV>
{
TV Get(TK key);
void Set(TK key, TV value);
}
public class GetSet<TK, TV> : IGetSet<TK, TV>
{
private readonly ActorRef _getSetActor;
public GetSet(ActorRefFactory system)
{
_getSetActor = system.ActorOf(Props.Create(() => new GetSetActor()));
}
public TV Get(TK key)
{
var x = _getSetActor.Ask<TV>(new GetSetActor.Get(key));
return x.Result; //blocking, I know, it's just an example
}
public void Set(TK key, TV value)
{
_getSetActor.Tell(new GetSetActor.Set(key, value));
}
class GetSetActor : ReceiveActor
{
readonly Dictionary<TK, TV> _values = new Dictionary<TK, TV>();
public class Get
{
public Get(TK key) { Key = key; }
public TK Key { get; private set; }
}
public class Set
{
public Set(TK key, TV value) { Key = key; Value = value; }
public TK Key { get; private set; }
public TV Value { get; private set; }
}
public GetSetActor()
{
Receive<Get>(g => Sender.Tell(_values[g.Key], Self));
Receive<Set>(g => _values[g.Key] = g.Value);
}
}
}
...
var gs = new GetSet<string, int>(ActorSystem.Create("Wasp"));
gs.Set("a", 42);
var i = gs.Get("a");
In this case the IGetSet
interface comes from the traditional world, and its implementation lets us transition back and forth with the actors world. I tried to be nice with actors, which are never used in ways different from message passing, so overall this (trivial, of course) exercise looks promising, but I'd like to know if there's anything more I should pay attention to since day 1.
I've been reading about avoiding additional non-actor-based async code taking closures on actors' state, that's clear and I'm not doing it, but maybe there's more which I can't see. My final goal is to use this pattern quite extensively, down to point I'd write actor-oriented implementations of Rx's ISubject
(which BTW I already did and it was easy, but again I'm not sure I paid enough attention to all I should).
I also read a bit about Typed Actors, but I'm not a Scala expert so maybe I'm not grasping all the details from the code samples, and I'm not sure they are already available within Akka.NET (doc page is a 404)