Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • 00:54
    Aaronontheweb milestoned #6157
  • 00:54
    Aaronontheweb labeled #6157
  • 00:54
    Aaronontheweb labeled #6157
  • 00:54
    Aaronontheweb labeled #6157
  • 00:22
    Aaronontheweb synchronize #6156
  • 00:22
    Aaronontheweb commented #6156
  • Oct 06 23:30
    dependabot[bot] synchronize #6097
  • Oct 06 23:30

    dependabot[bot] on nuget

    Bump System.Configuration.Confi… (compare)

  • Oct 06 23:30
    dependabot[bot] synchronize #6142
  • Oct 06 23:30
    dependabot[bot] edited #6097
  • Oct 06 23:30

    dependabot[bot] on nuget

    Bump Microsoft.Extensions.Objec… (compare)

  • Oct 06 23:30
    dependabot[bot] edited #6142
  • Oct 06 23:30
    dependabot[bot] synchronize #5417
  • Oct 06 23:30

    dependabot[bot] on nuget

    Bump System.Threading.Channels … (compare)

  • Oct 06 23:30
    dependabot[bot] edited #5417
  • Oct 06 23:30
    dependabot[bot] synchronize #5859
  • Oct 06 23:30

    dependabot[bot] on nuget

    Bump NUnit from 3.7.1 to 3.13.3… (compare)

  • Oct 06 23:30
    dependabot[bot] synchronize #6020
  • Oct 06 23:30

    dependabot[bot] on nuget

    Bump PublicApiGenerator from 9.… (compare)

  • Oct 06 23:30
    dependabot[bot] synchronize #5370
Vasily Kirichenko
@vasily-kirichenko
public override int MaximumConcurrencyLevel
        {
            get { return 1; }
        }
Shukhrat Nekbaev
@snekbaev
@vasily-kirichenko thank you!
Shukhrat Nekbaev
@snekbaev
Question about ConsistentHashingPool. Eventual goal is to have one actor per IConsistentHashable, no reuse. It seems that ConsistentHashingPool requires instance count, which means it will be reused, which in turn means I can't have state in the actor assuming it is per, say UserId. In that case I think I'm better off by manually creating actors for each UserId and store those in Dictionary or so. Or is it possible to actually tell ConsisntentHashingPool to have one actor per UserId? I did see some Resizer option, wasn't sure it was that?
Shukhrat Nekbaev
@snekbaev

A follow up would be:

public sealed class CHRChildActor : UntypedActor
{
    private int? processedUserId;
    private static int instanceCounter = 0;

    protected override void PreStart()
    {
        Console.WriteLine( Self.Path );

        base.PreStart();

        instanceCounter++;
    }

    protected override void OnReceive( object message )
    {
        message.Match().With<Work>( HandleWork )
               .Default( Unhandled );
    }

    private void HandleWork(Work work)
    {
        Console.WriteLine( $"Work received for userId {work.UserId}" );
        Console.WriteLine( $"Instance counter: {instanceCounter}" );

        if (processedUserId == null)
        {
            processedUserId = work.UserId;
        }

        if (processedUserId != work.UserId)
        {
            throw new Exception( "Being reused!" );
        }
    }

    public sealed class Work : IConsistentHashable
    {
        public Work(int userId)
        {
            UserId = userId;
        }

        public int UserId { get; }
        public object ConsistentHashKey => UserId;
    }
}

basically it throws exception if being reused, now, parent sends 5 messages

for (var i = 0; i < 5; i++)
{
    _child.Tell( new CHRChildActor.Work( i ) );
}

and the way _child actor is created:

_child = Context.ActorOf( Props.Create( () => new CHRChildActor()).WithRouter( new ConsistentHashingPool( 10 ) ) );
Vasily Kirichenko
@vasily-kirichenko
what is instanceCounter value?
Ismael Hamed
@ismaelhamed
@snekbaev, AFAIK consistent hashing will give you a range of UserIds per hash
Shukhrat Nekbaev
@snekbaev

so, size is 10, but 5 messages are sent. I was expecting it not to collide, i.e. throw exception, but it does, then I tried also setting the name:

_child = Context.ActorOf( Props.Create( () => new CHRChildActor()).WithRouter( new ConsistentHashingPool( 10 ) ), "a" );

ran and got the exception, then I added one more letter to the name:

_child = Context.ActorOf( Props.Create( () => new CHRChildActor()).WithRouter( new ConsistentHashingPool( 10 ) ), "ab" );

Ran and... got no exception. I was expecting one, but got none. Rerun 10 times, no exception. If I change to "a" or remove the name - exception is there, if I have "ab" - no exception. I'm afraid to ask, but is there some weirdness going on in here or am I missing something?

Vasily Kirichenko
@vasily-kirichenko
turn on debug logs and look at what actors and when are created
Shukhrat Nekbaev
@snekbaev
@vasily-kirichenko instanceCounter is a poor man's way to count PreStart. Basically if actor is not restarted I know how many instances are there :)
Vasily Kirichenko
@vasily-kirichenko
I meant what is its value :)
Shukhrat Nekbaev
@snekbaev
the child actor above, it has Console.Log, I can see the names of actors when they are created, order of console output is out of order though
normal run:
akka://Test/user/$a/ab/$c
akka://Test/user/$a/ab/$b
akka://Test/user/$a/ab/$h
akka://Test/user/$a/ab/$i
akka://Test/user/$a/ab/$j
akka://Test/user/$a/ab/$f
akka://Test/user/$a/ab/$g
CHRParentActor - PreStart
akka://Test/user/$a/ab/$e
akka://Test/user/$a/ab/$a
akka://Test/user/$a/ab/$d
Work received for userId 0
Instance counter: 10
Work received for userId 3
Instance counter: 10
Work received for userId 1
Instance counter: 10
Work received for userId 2
Instance counter: 10
Work received for userId 4
Instance counter: 10
crash:
akka://Test/user/$a/a/$a
akka://Test/user/$a/a/$g
akka://Test/user/$a/a/$i
akka://Test/user/$a/a/$h
akka://Test/user/$a/a/$j
akka://Test/user/$a/a/$e
akka://Test/user/$a/a/$c
akka://Test/user/$a/a/$b
akka://Test/user/$a/a/$f
akka://Test/user/$a/a/$d
CHRParentActor - PreStart
Work received for userId 0
Instance counter: 10
Work received for userId 2
Instance counter: 10
Work received for userId 1
Instance counter: 10
Work received for userId 3
Instance counter: 10
Work received for userId 4
Instance counter: 10
akka://Test/user/$a/a/$e
akka://Test/user/$a/a/$d
akka://Test/user/$a/a/$a
akka://Test/user/$a/a/$h
akka://Test/user/$a/a/$i
akka://Test/user/$a/a/$b
akka://Test/user/$a/a/$c
akka://Test/user/$a/a/$f
akka://Test/user/$a/a/$j
akka://Test/user/$a/a/$g
[ERROR][23.7.2018 11:27:27][Thread 0005][akka://Test/user/$a/a] Being reused!
Cause: System.Exception: Being reused!
   at TestActors.ConsistentHashRouting.CHRChildActor.HandleWork(Work work) in c:\Workspace\c#\akka.net\TestActors\ConsistentHashRouting\CHRChildActor.cs:line 40
   at Akka.Case.With[TMessage](Action`1 action)
   at TestActors.ConsistentHashRouting.CHRChildActor.OnReceive(Object message) in 
REDACTED
Bartosz Sypytkowski
@Horusiath
@snekbaev you can always Context.Watch over your actors - if they are killed (i.e. as a result of not being albe to replay they journal) they will notify watchers with Terminated message. Btw. if this happens in production, it means that your event journal has been corrupted and can no longer serve as a reliable source of data - in that case waiting for the response is the least of your problem.
Shukhrat Nekbaev
@snekbaev
this is a test app I'm using to learn Akka :) and to test things faster :)

btw, I ran into some quirks with:

 message.Match().With<Work>( HandleCrash )
                   .Default( Unhandled );

the pattern matching API, I'd assume it is not meant to be used by end users? Yesterday, I was "watch"ing and waiting for "Terminated" message, but never got it, though was getting unhandled messages, when checked, it was some Akka.Case which wrapped the "Terminated" message. Because of that I reworked the message handler to switch

Shukhrat Nekbaev
@snekbaev
message.Match().With<SEChildChildActor.Crash>( HandleCrash )
       .Match().With<Terminated>(HandleTerminated)
       .Default( o =>
                 {
                     Console.WriteLine( o );
                     Unhandled(o);
                 } );
became:
switch (message)
{
    case SEChildChildActor.Crash crash:
        HandleCrash( crash );
        break;

    case Terminated terminated:
        HandleTerminated(terminated);
        break;

    default:
        Unhandled( message );
        break;
}
Vasily Kirichenko
@vasily-kirichenko
I believe ConsistentHashPool guarantees that messages with same key are routed to the same actor (but it does not guarantee that there is single actor per key). It seems it keeps a ring of actors and select one by index.
Shukhrat Nekbaev
@snekbaev
@vasily-kirichenko any ideas why not-naming/short-naming the pool affects that rotation?
Vasily Kirichenko
@vasily-kirichenko
no
Vasily Kirichenko
@vasily-kirichenko
so, I don't think the resizer can be used at all
because if nr of actors grows, messages may be routed to different actors
Shukhrat Nekbaev
@snekbaev
yeah, I'd probably go with a list/dictionary and create actors per "some id"
Vasily Kirichenko
@vasily-kirichenko
let me check some books on this pool
Shukhrat Nekbaev
@snekbaev
btw, what is the common practice for that: say I want actor per user, I can create actor for each user and prefix the actor name with userId. Then, if needed, I can use ActorSelection to talk to it directly. Another way, is to have a list in some UserManagerActor, which has userIds mapped to each IActorRef. But in that case to talk to a child UserActor I will need to route through the UserManagerActor
Vasily Kirichenko
@vasily-kirichenko
ActorSelection would be too slow I'm afraid
it should be avoided in most cases
Bartosz Sypytkowski
@Horusiath
@snekbaev if you're using clusters, akka cluster sharding gives you exactly that
Vasily Kirichenko
@vasily-kirichenko
yeah, but I'm afraid he does not use cluster.
Bartosz Sypytkowski
@Horusiath
then a simple user coordinator can work
Vasily Kirichenko
@vasily-kirichenko
which holds a userid -> actorref dictionary?
I mean using ActorSelection is not good for this
@snekbaev
image.png
Bartosz Sypytkowski
@Horusiath
@vasily-kirichenko @snekbaev if a coordinator is a single purpose, you don't need dictionary or anything:
Receive<SendTo>(send => {
  string recipient = send.Recipient;
  object message = send.Message;
  var child = GetChild(recipient);
  if (Equals(child, ActorRefs.Nobody)) 
  {
    child = Context.ActorOf(childProps, recipient);
  }
  child.Forward(message);
});
Vasily Kirichenko
@vasily-kirichenko
ah, GetChild
cool
Shukhrat Nekbaev
@snekbaev
no cluster, no remoting so far, just a test app :)
Vasily Kirichenko
@vasily-kirichenko
I hope it's O(1) ;)
Shukhrat Nekbaev
@snekbaev
@vasily-kirichenko ActorSelection, I've been battling to avoid it, but then I'm left either pass it via constructor and the chain can be long, or try to init the actor with some message, which shifts those actors to use "Become", also they will probably use some "discovery" actor by ActorSelection anyway...
@Horusiath hm, I don't seem to have GetChild in Akka 1.3.8, did you mean: Context.Child( )?
Aaron Stannard
@Aaronontheweb
@eaba what persistence driver are you using?
@snekbaev yes he does
Context.Child is O(1) - it's a dictionary lookup
Vasily Kirichenko
@vasily-kirichenko
great
Ebere Abanonu
@eaba
@Aaronontheweb sqlserver
Aaron Stannard
@Aaronontheweb
yeah, so color me really, really skeptical that it's missing sequence numbers
it's the most heavily used