Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • 02:22
    to11mtm commented #4594
  • 02:22
    to11mtm commented #4594
  • 00:40
    to11mtm commented #4594
  • 00:36
    Aaronontheweb commented #4594
  • 00:35
    Aaronontheweb commented #4594
  • 00:34
    to11mtm commented #4594
  • 00:34
    to11mtm commented #4594
  • 00:33
    to11mtm commented #4594
  • 00:07
    to11mtm commented #4594
  • Oct 29 20:36
    Aaronontheweb commented #4598
  • Oct 29 20:36
    Aaronontheweb milestoned #4598
  • Oct 29 20:36
    Aaronontheweb assigned #4598
  • Oct 29 20:36
    Aaronontheweb labeled #4598
  • Oct 29 19:36
    zbynek001 opened #4598
  • Oct 29 18:47
    zbynek001 synchronize #4587
  • Oct 29 18:20
    Aaronontheweb commented #4594
  • Oct 29 17:55
    Aaronontheweb closed #4589
  • Oct 29 17:55
    Aaronontheweb labeled #4597
  • Oct 29 17:55
    Aaronontheweb commented #4597
  • Oct 29 17:36
    Aaronontheweb commented #4597
Aaron Stannard
@Aaronontheweb
most people build their actor hierarchies top-down
where the top level actors filter messages down to their children and so forth
so by convention, most developers treat their top level actors like "public APIs"
therefore, it's usually safe to select those and trust that your message will eventually be routed to the correct concrete actor who will actually do the processing
and that actor will send you a reply back directly
you can also do some cool stuff with wildcard actor selections
i.e. akka.tcp://mysys@127.0.0.1:9110/user/myParent/*/myGrandChild
you can dynamically select all of the grand children of myParent named myGrandChild without knowing what the parent's name is
I used that to build our actor hierarchy visualizer in Petabridge.Cmd: https://cmd.petabridge.com/articles/commands/actor-commands.html#actor-hierarchy
AnchishkinAlex
@AnchishkinAlex
it's interesting
So well! We will try Actor Selection for this moment. Thanks again! All the best! :smile:
vicosoft4real
@vicosoft4real
Can some please explain the philosophy behind this Cluster Sharding shenanigans.
Aaron Stannard
@Aaronontheweb
@vicosoft4real Cluster.Sharding tries to guarantee that there is exactly one copy of a given entity inside your cluster at any given time
where each entity is represented as its own actor
it has tooling in place to do things such as redistribute entities when the cluster changes
buffer messages being sent to a given entity while it's being moved
and a placement algorithm for figuring out where it should spawn new ones
each entity should, ideally, persist its state somewhere
vicosoft4real
@vicosoft4real
sounds good
Aaron Stannard
@Aaronontheweb
so in the event that the entity passivates (shuts down after a period of inactivity) and needs to be recreated in the future
vicosoft4real
@vicosoft4real
but we cannot have full control of the created entity/actor
Aaron Stannard
@Aaronontheweb
or in the event that the entity gets moved
it can recover its previous state
you can define the Props that get used to spawn ALL entity actors
vicosoft4real
@vicosoft4real
ok
Aaron Stannard
@Aaronontheweb
but no, you don't have any control over how that actor is created
it's created lazily
when someone sends a message to the ShardRegion or ShardRegionProxy
and the sharding system uses a MessageExtractor to pull the entityId from the message
if an entity doesn't exist with that entityId yetr
it will be created
essentially it's doing the same thing the child-per-entity pattern does
vicosoft4real
@vicosoft4real
ok
vicosoft4real
@vicosoft4real
to actually have full control over an actor , like managing the state, persisting message to external DB, Cluster sharding may not be best approach.
Aaron Stannard
@Aaronontheweb
you can still use cluster.sharding for that
the actor can control its own life cycle
its just that the actor can be moved if a new node joins the cluster that can host shards
so it should be designed to behave like a persistent actor
where it has an explicit state recovery mechanism and processing stage it executes before it's allowed to process any new messages
vicosoft4real
@vicosoft4real
hmm
Aaron Stannard
@Aaronontheweb
you can pass in a Props class created using DI too
since the actors don't get deployed remotely
vicosoft4real
@vicosoft4real
please go along with me.
i have a shardenvilope :

public sealed class ShardEnvelope
{
public readonly string Recipient;
public readonly object Message;

    public ShardEnvelope(string recipient, object message)
    {
        Recipient = recipient;
        Message = message;
    }
}

}

an extrator : public class CustomMessageExtractor : HashCodeMessageExtractor
{
public CustomMessageExtractor(int maxNumberOfShards) : base(maxNumberOfShards) { }
public override string EntityId(object message) => (message as ShardEnvelope)?.Recipient;
public override object EntityMessage(object message) => (message as ShardEnvelope)?.Message ?? message;
// public string ShardId(object message)
// {
// return (message as ShardEnvelope)?.ShardId.ToString();
// }
}
message A :smile: public class Message1
{
public Message1(string name1)
{
Name1 = name1;
}
    public string Name1 { get; }
}
Actor A public class ActorA: AtLeastOnceDeliveryReceiveActor
{
    public override string PersistenceId { get; }
    readonly ILoggingAdapter _logger = Context.GetLogger();

    public ActorA()
    {
        PersistenceId = Uri.UnescapeDataString(Self.Path.Name);
        _logger.Info($"Instantiating {nameof(ActorA)} in the constructor with path {Self.Path}");
        Command<Message1>(msg =>
        {
            _logger.Info($"log message {msg.Name1}");
            IActorRef shardRegion2 = Context.System.BootstrapShard<ActorB>("web-node1");
            // Context.ActorOf(Props.Create<ActorB>());

        });
        //Command<Message2>(msg =>
        //{
        //    _logger.Info($"log message {msg.Name1}");

        //});
    }
}
public class ActorB : ReceivePersistentActor
{
    public override string PersistenceId { get; }
    readonly ILoggingAdapter _logger = Context.GetLogger();

    public ActorB()
    {
        PersistenceId = Uri.UnescapeDataString(Self.Path.Name);

        _logger.Info($"Instantiating {nameof(ActorB)} in the constructor with path {Self.Path.Name}");
        Command<Message2>(msg =>
        {
            _logger.Info($"log message {msg.Name1}");

        });

    }
}
at start up I configure my shardding as :smile: ClusterSharding sharding = ClusterSharding.Get(eduSaaSSystem);
IActorRef shardRegion = sharding.Start(
typeName: typeof(ActorA).Name,
entityProps: Props.Create<ActorA>(), // the Props used to create entities
settings: ClusterShardingSettings.Create(eduSaaSSystem)
.WithCoordinatorSingletonSettings(ClusterSingletonManagerSettings.Create(eduSaaSSystem))
.WithRole("web-node")
,
messageExtractor: new CustomMessageExtractor(100 * 10)
);