Enumerating available actors in Akka.NET cluster

Maxim Gershkovich

I have two actors, lets call them ActorA and ActorB. Both actors reside in their own separate process as a Topshelf based Windows Service.

Basically they look like this.

public class ActorA : ReceiveActor
{
    public ActorA()
    {
        this.Receive<ActorIdentity>(this.IdentifyMessageReceived);
    }


    private bool IdentifyMessageReceived(ActorIdentity obj)
    {
        return true;
    }
}

public class ActorB : ReceiveActor
{
    private readonly Cluster Cluster = Akka.Cluster.Cluster.Get(Context.System);


    public ActorB()
    {

        this.Receive<ActorIdentity>(this.IdentifyMessageReceived);
        this.ReceiveAsync<ClusterEvent.MemberUp>(this.MemberUpReceived);
    }

    protected override void PreStart()
    {
        this.Cluster.Subscribe(this.Self, ClusterEvent.InitialStateAsEvents, new[]
        {
            typeof(ClusterEvent.IMemberEvent),
            typeof(ClusterEvent.UnreachableMember)                
        });
    }

    protected override void PostStop()
    {
        this.Cluster.Unsubscribe(this.Self);
    }

    private async Task<bool> MemberUpReceived(ClusterEvent.MemberUp obj)
    {
        if (obj.Member.HasRole("actora"))
        {
            IActorRef actorSelection = await Context.ActorSelection("akka.tcp://mycluster@localhost:666/user/actora").ResolveOne(TimeSpan.FromSeconds(1));
            actorSelection.Tell(new Identify(1));
        }

        return true;
    }

    private bool IdentifyMessageReceived(ActorIdentity obj)
    {
        return true;
    }
}

My config files are super simple

ActorA:

akka {
    log-config-on-start = on
    stdout-loglevel = DEBUG
    loglevel = DEBUG
    actor.provider = cluster
    remote {
        dot-netty.tcp {
            port = 666
            hostname = localhost

        }
    }
    cluster {
        seed-nodes = ["akka.tcp://mycluster@localhost:666"]
        roles = [actora]
    }
}

ActorB:

akka {
    log-config-on-start = on
    stdout-loglevel = DEBUG
    loglevel = DEBUG
    actor.provider = cluster
    remote {
        dot-netty.tcp {
            port = 0
            hostname = localhost
        }
    }
    cluster {
        seed-nodes = ["akka.tcp://mycluster@localhost:666"]
        roles = [actorb]
    }
}

I now want to identify all the given actors attached to my cluster. I do this by waiting for the cluster node MEMBER UP event and trying to send an Identify() message to the given actor to receive a reference to it.

The problem is that I cannot seem to be able to successfully send the message back to ActorA. Infact when executing the above code (despite the fact that I have the correct reference in the ActorSelection method) the ActorIdentity message is invoked in ActorB rather than ActorA.

I have tried handling all received message in ActorA and it appears I never receive the Identity message. However I can successfully send any other type of message ActorA using the same ActorSelection reference.

So can anyone provide any insight? Why is my identity message never reaching my target actor?

Bartosz Sypytkowski

ActorIdentity message is invoked in ActorB rather than ActorA.

This works as intended, as you're sending Identify request from actor B → A, for which ActorIdentity is a response message (send automatically from A → B).

You can already observe this behavior in action, since:

Context.ActorSelection(path).ResolveOne(timeout)

is more or less an equivalent of

Context.ActorSelection(path).Ask<ActorIdentity>(new Identify(null), timeout: timeout)

Identify is a system message, which is handled always before any programmer-defined message handlers are invoked - for this reason you probably won't catch it in your own handlers.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related