These are chat archives for akkadotnet/akka.net

3rd
Oct 2017
jalchr
@jalchr
Oct 03 2017 06:24
@Horusiath Thanks, highly appreciated
jalchr
@jalchr
Oct 03 2017 10:06
@Horusiath I'm thinking about using DData as a state holder for ensuring message delivery. So instead of scattering state in every actor, I have it centralized and cluster-ready. What's your thoughts on this ?
Aaron Stannard
@Aaronontheweb
Oct 03 2017 15:15
@jalchr DData is intended for having multiple writable replicas of the same state distributed throughout the cluster
so it's like having N copies of the same actor
but the DData data structures (CRDTs) allow for the state of all N replicas to be merged together into a consistent view of the entity as a whole eventually
but there are tradeoffs in terms of the types of things you can do with your entity's state
for instance, some of the collection data structures may not allow you to delete items from the collection (you have to use a "tombstone" instead to indicate that something has been removed)
and some of the counter data structures are monotonic (don't allow decrements)
if you're working on reliable delivery type problems
I made a YouTube video about this last year, let me see if I can grab it
in general, I recommend not using exactly once if you can avoid it
but if you really need it, that video goes through how to implement it
Aaron Stannard
@Aaronontheweb
Oct 03 2017 15:20
and the technique I use there is exactly once without strong ordering
meaning each message is delivered independently from every other message
if you need to do exactly once delivery AND preserve ordering for all messages to each individual recipient
you'd need to ditch using an AtLeastOnceDeliveryActor base class
and implement something custom where each send operation to each recipient is atomic
and any subsequent sends get queued up until the current send is ACKed
and then you can proceed from there
in a happy-path scenario the performance is probably OK
once you actually start dealing with prolonged trouble on the network though then that technique is going to result in back-ups quickly
especially if you end up with a poisoned message
I'm working on some finance applications at the moment; real-time price analysis, trading indicators, and eventually an execution engine
In the spec design I have currently we only use something stronger than at most once delivery inside the execution engine
if I miss some real-time order book events from the exchanges I'm connected to
Aaron Stannard
@Aaronontheweb
Oct 03 2017 15:25
¯_(ツ)_/¯
however, if my ability to process those real-time order book events is slow
then my application can't really do its job properly
we will use the stronger delivery guarantee in the execution engine though
because my view of an account balance and the exchange's view of the account balance have to be identical
otherwise the trading algorithms are going to try to execute trades that can't be filled or might otherwise blow away the liquidity (cash-on-hand) parameters the users set... which would be bad
AnchishkinAlex
@AnchishkinAlex
Oct 03 2017 16:06
hi! I have a problem: there are two independent projects and I am using Akka Remoting for connection. I am also using Autofac DI.
Two projects. Two actor systems. Two Autofac DI containers.
Actor of the first ActorSystem calls actor of the second ActorSystem which should have constructor injection.
But the first actor system doesn't know (and shouldn't know) about this dependencies.
Is it possible to call this actor after resolving dependency through the second actor system?
Aaron Stannard
@Aaronontheweb
Oct 03 2017 16:19
@AnchishkinAlex are you remotely deploying those actors?
if not, then none of this stuff matters - both actors are started independently
and neither needs to know about each other's constructor arguments
they just need to acquire a remote actor reference to each other
which you can via an ActorSelection initially
AnchishkinAlex
@AnchishkinAlex
Oct 03 2017 16:31
Ok, we tried to use ActorSelection but it needs hardcode address of actor.
Is it possible to get address of actor from HOCON?
Aaron Stannard
@Aaronontheweb
Oct 03 2017 16:31
yep, you can create a custom HOCON field
to store the address a remote node
I do this inside the client-server app from our Akka.NET trainings
let me see if I can grab it...
akkatime{
             sessions{
              handshake-timeout = 4.0s #max time to complete the handshake timeout process
              verify-timeout = 1.0s #max time to authentication an end-user locally on the server
              verify-chat = on
             }
             server = "akka.tcp://akkatime@127.0.0.1:14445"
          }

          akka {
the akkatime section is custom
and I have a akkatime.server property that the client reads from configuration in order to figure out how to contact the server
var actorSystem = ActorSystemRefs.AkkaTimeSystem = ActorSystem.Create("akkatime");
            var serverAddress = ActorSystemRefs.ServerAddress = Address.Parse(actorSystem.Settings.Config.GetString("akkatime.server"));
            var serverStatus =ActorSystemRefs.ServerConnectivityActor =
                actorSystem.ActorOf(
                    Props.Create(() => new ServerConnectivityStatusActor((Address)serverAddress.Clone(), ServerConnectivityStatus.Disconnected)),
                    ActorPaths.ServerConnectivity.Name);
which I then read in here when I'm starting my ActorSystem
and that serverAddress gets passed to an actor that uses an ActorSelection to contact another actor on the server
AnchishkinAlex
@AnchishkinAlex
Oct 03 2017 16:37
Thank you. Could you provide link to this example? I'll explain it
explore*
Aaron Stannard
@Aaronontheweb
Oct 03 2017 16:41
wish I could, but it's part of the training materials we distribute to our customers
that being said, we do have all of these ones
the WebCrawler one for Akka.Cluster is probably the most relevant there
AnchishkinAlex
@AnchishkinAlex
Oct 03 2017 16:46
Thanks! I saw Akka.NET Bootcamp, Chat Server Example but not this samples :smile:
Aaron Stannard
@Aaronontheweb
Oct 03 2017 16:46
you're welcome!
AnchishkinAlex
@AnchishkinAlex
Oct 03 2017 16:47
And I know about your post "When I should use Actor Selection?". Is this situation relevant, isn't it?
Aaron Stannard
@Aaronontheweb
Oct 03 2017 16:47
yes it is
generally, IActorRef is going to be both more performant and flexible at run-time
since it has the benefit of location transparency and doesn't need to be "resolved"
but ActorSelection is ideal in situations where you don't have a reference to an actor yet but still need to contact it
and you know roughly where it is in the hierarchy
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
Oct 03 2017 16:52
it's interesting
So well! We will try Actor Selection for this moment. Thanks again! All the best! :smile:
vicosoft4real
@vicosoft4real
Oct 03 2017 17:40
Can some please explain the philosophy behind this Cluster Sharding shenanigans.
Aaron Stannard
@Aaronontheweb
Oct 03 2017 17:40
@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
Oct 03 2017 17:42
sounds good
Aaron Stannard
@Aaronontheweb
Oct 03 2017 17:42
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
Oct 03 2017 17:42
but we cannot have full control of the created entity/actor
Aaron Stannard
@Aaronontheweb
Oct 03 2017 17:42
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
Oct 03 2017 17:42
ok
Aaron Stannard
@Aaronontheweb
Oct 03 2017 17:42
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
Oct 03 2017 17:43
ok
vicosoft4real
@vicosoft4real
Oct 03 2017 17:49
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
Oct 03 2017 17:50
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
Oct 03 2017 17:50
hmm
Aaron Stannard
@Aaronontheweb
Oct 03 2017 17:51
you can pass in a Props class created using DI too
since the actors don't get deployed remotely
vicosoft4real
@vicosoft4real
Oct 03 2017 17:52
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)
);
if i send message to shard region as shardRegion .Tell(new ShardEnvelope(id, messagea));
vicosoft4real
@vicosoft4real
Oct 03 2017 17:59
@Aaronontheweb is it possible to send message to actorB with message2
@Aaronontheweb are u with me?
Aaron Stannard
@Aaronontheweb
Oct 03 2017 18:00
I think so.... the message extractor is looking for a property called Recipient on the message
ah I see
you're using an envelope for that
but yeah, that message will be received by your persistent actor
vicosoft4real
@vicosoft4real
Oct 03 2017 18:02
ok