These are chat archives for akkadotnet/akka.net

15th
Jun 2018
Stéphane Erbrech
@serbrech
Jun 15 2018 06:14
Hello community :)
I was wondering if there is any reference on running akka.net cluster on top of a kubernetes cluster
@Aaronontheweb I see you have some plans for this? I'd be interested to know more
also, hello @paulinfrancis :D
DaKaLKa
@DaKaLKa
Jun 15 2018 07:25
@serbrech We run a show case application with akka.net cluster on top of a two node kubernetes cluster in the IBM Cloud. We use stateful sets for the seed nodes, so that the addresses don't change (currently fixed two seed nodes - but scaling is workding quite fine). Currently the application is running for about 2 Month (24/7) without any problems. The amount of messages is not so high (about 10msg/s).
Stéphane Erbrech
@serbrech
Jun 15 2018 08:10
thanks @DaKaLKa that's what I thought, nothing special except stateful set for the seed nodes then
Sebastien Bacquet
@sbacquet
Jun 15 2018 08:37
@Aaronontheweb
Hello Aaron
I can see the Akka.DistributedData.Tests.MultiNode tests are all skipped.
Do you know when the DistributedData feature is planned to be official (not beta) ?
Thank you and sorry if the question has already been asked !
me-slove
@me-slove
Jun 15 2018 14:09
@Aaronontheweb Good cluster article but it did leave one interesting question unanswered (unless I missed it). How do routers handle these comings and goings? It seems that your handler example would work very well for a "roll your own" controller/router
Aaron Stannard
@Aaronontheweb
Jun 15 2018 14:10
I think I mentioned how the built-in routers handle it in passing
let me see if I can dig that up real quick
it was only a sentence
or so
Other tools, like clustered routers, deal with network partitions by simply not routing new messages to unreachable nodes. If an unreachable node comes back, the routers will add those nodes back to the routing table and resume delivering messages.
so I actually have a series of "proper care and feeding of Akka.NET Cluster" posts stubbed out
me-slove
@me-slove
Jun 15 2018 14:12
thank you for finding it. more coffee when reading I guess :)
Aaron Stannard
@Aaronontheweb
Jun 15 2018 14:13
I pulled that first one and published it because my original post was getting pretty large
other topics I plan on addressing: Starting and Killing Nodes Gracefully
cluster planning and design - understanding how the connectivity model of Akka.Remote and Akka.Cluster works
so that one is drilling into things like "don't use load balancers" and such
and later in the summer I want to get into some DevOps type stuff with the cluster
monitoring and deployment
me-slove
@me-slove
Jun 15 2018 14:16
If you are looking for a priority vote, I vote for design and planning. specific why and why not use certain architectures and their trade offs.
Aaron Stannard
@Aaronontheweb
Jun 15 2018 14:16
yeah I can do something more general too
mostly I started writing these posts not because the underlying technology is complicated
me-slove
@me-slove
Jun 15 2018 14:17
For me, that's the hardest part right now. Deciding whether to use a cluster or not or just remoting
Aaron Stannard
@Aaronontheweb
Jun 15 2018 14:17
but rather because using that technology requires developers to approach the problems in ways that are pretty novel compared to good, old-fashioned web applications
me-slove
@me-slove
Jun 15 2018 14:17
I don't like pools so only use groups
Aaron Stannard
@Aaronontheweb
Jun 15 2018 14:17
and I wanted to help fill some of the conceptual gaps between what most .NET developers already know how to do
vs. what using a tool like Akka.NET or Akka.Cluster can help you do when you use it the way it's intended to be used
"not better or worse, but simply different"
me-slove
@me-slove
Jun 15 2018 14:18
also another vote, more like your "futures" video where you talked through the industry/technology changes. that was very enlightening
you see so many projects it's nice to get a broader view
Aaron Stannard
@Aaronontheweb
Jun 15 2018 14:19
which video was that?
was that a .NET Fringe talk from a few years back?
me-slove
@me-slove
Jun 15 2018 14:20
let me get the link but it was talking about docker/cassandra/etc.
Aaron Stannard
@Aaronontheweb
Jun 15 2018 14:20
ohhhhhhhh
that was my talk at the Cassandra Conference
me-slove
@me-slove
Jun 15 2018 14:21
yep. that's it
Aaron Stannard
@Aaronontheweb
Jun 15 2018 14:32
nice
I can certainly do more of that
way easier than writing a tutorial!
:p
@sbacquet I didn't realize they were skipped; must be some more hardening required for those specs
I want to get that stuff out of beta ASAP
decoupling Akka.Cluster.Sharding from Akka.Persistence is a win-win for many users
DData is essential to doing that
I wish I could offer a timeline on when that would happen
but I'm spread pretty thin at the moment and I know @Horusiath is hard at work on the multi-datacenter cluster stuff we're including in the Akka.NET v1.4 release
Sebastien Bacquet
@sbacquet
Jun 15 2018 15:51
Ok thank you @Aaronontheweb for your answer.
Re-enabling the tests could be a good first move on the path of making DData official, at least to ensure that no major regression is introduced.
Aaron Stannard
@Aaronontheweb
Jun 15 2018 16:20
gotta debug them too
there's a reason they're disabled
hectorcaban
@hectorcaban
Jun 15 2018 17:01

private void CreateChildUserIfNotExists(int userId)
{
if (!_srdapclients.ContainsKey(userId))
{
IActorRef newChildActorRef =
Context.ActorOf(Props.Create(() => new SRDAPClient(userId)).WithRouter(FromConfig.Instance), "SRDAPClient" + 1);

            _srdapclients.Add(userId, newChildActorRef);

            ColorConsole.WriteLineYellow(string.Format("UserCoordinatorActor created new child UserActor for {0} (Total SRDAPClient: {1})", userId, _srdapclients.Count));
        }
    }

if I am trying to configure round-robin using Hokon.

/SRDAPClient {
router = round-robin-pool
nr-of-instances = 5
routees.paths = ["/SRDAPCoornator/SRDAPClient/*"]
}

Stephen Riley
@stephen-riley
Jun 15 2018 17:02
Hi gang, got a question about contexts (Contexts?) inside lambdas in Akka.net. I am trying to do a Tell() inside a ContinueWith( ...lambda... ) and the message always comes from deadLetters. However, when I put a self (closed over copy of Self) as the explicit sender in the Tell(), it works fine.
hectorcaban
@hectorcaban
Jun 15 2018 17:02
since the actors are created dynamically, how do I configure the Hokon ?
Stephen Riley
@stephen-riley
Jun 15 2018 17:02
So my question is, how does the Tell() work under normal circumstances when you don't give it an explicit sender?!
Code as follows:
Onur Gumus
@OnurGumus
Jun 15 2018 17:03
@stephen-riley It defaults to NoSender AFAIK.
but that depends on from where you invoke I think.
Stephen Riley
@stephen-riley
Jun 15 2018 17:04
var self = Self;

httpClient.GetAsync(req.Url).ContinueWith(responseTask =>
{
    var response = responseTask.Result;
    var duration = stopwatch.Elapsed.TotalMilliseconds;
    var msgResponse = new AkkaBlaster.Dto.WebResponse
    {
        StatusCode = response.StatusCode,
        Duration = duration
    };

    mylogger.Tell($"{(int)msgResponse.StatusCode} {msgResponse.Duration} - {req.Url}" /*, self */);        // <---
},
TaskContinuationOptions.AttachedToParent & TaskContinuationOptions.ExecuteSynchronously);
Onur Gumus
@OnurGumus
Jun 15 2018 17:04
@stephen-riley Self itself is a property
and it requires to access to current actor within the current synch context.
what I do is ``` var self = Self; //now I can use self anywhere ````
Stephen Riley
@stephen-riley
Jun 15 2018 17:05
within the current synch context
I think that's what I'm not getting.
Onur Gumus
@OnurGumus
Jun 15 2018 17:05
Inside the actor if you run another thread like Task.Run ( you can't access to Self any more.
because Self invokes code and requires you to be on the message queue thread of the actor.
Stephen Riley
@stephen-riley
Jun 15 2018 17:06
Yes, @OnurGumus , I have the var self = Self; thing, but I don't get why there's at least some Self defined inside the lambda I'm passing to ContinueWith().
because Self invokes code and requires you to be on the message queue thread of the actor.
OOOOOOOH! :-D
me-slove
@me-slove
Jun 15 2018 17:06
It sounds like the issue isn't that. It's a closure problem. Assign a local variable and pass that through. You are running a task which means things can change
Stephen Riley
@stephen-riley
Jun 15 2018 17:07
If Self is invoking code, I see the opportunity for what I'm seeing.
Okay.
Onur Gumus
@OnurGumus
Jun 15 2018 17:07
yes it is. That's why I said offload it by var self = Self;
then you can use it anywhere.
Stephen Riley
@stephen-riley
Jun 15 2018 17:08
I'm still not sure why my mylogger ActorSelection isn't carrying context with it, though.
var mylogger = Context.ActorSelection("/user/ConsoleLogger");
Why must I specify my closed-over self as the explicit sender in my call to mylogger.Tell()?
Onur Gumus
@OnurGumus
Jun 15 2018 17:09
you don't need.
I thought you were trying to access self.
Stephen Riley
@stephen-riley
Jun 15 2018 17:10
var mylogger = Context.ActorSelection("/user/ConsoleLogger");

mylogger.Tell("message");            // this does not work (always from deadLetters)

mylogger.Tell("message}", self);    // this works fine
Onur Gumus
@OnurGumus
Jun 15 2018 17:10
that's not normal.
Stephen Riley
@stephen-riley
Jun 15 2018 17:10
lol
Good, glad it's not just me. :smile:
Onur Gumus
@OnurGumus
Jun 15 2018 17:11
No it's just you.
Stephen Riley
@stephen-riley
Jun 15 2018 17:11
lol
Onur Gumus
@OnurGumus
Jun 15 2018 17:11
You are probably doing some thing wrong.
Stephen Riley
@stephen-riley
Jun 15 2018 17:11
Agreed. :wink:
Onur Gumus
@OnurGumus
Jun 15 2018 17:12
mylogger.Tell("message"); // this should just work
Stephen Riley
@stephen-riley
Jun 15 2018 17:12
Was hoping someone here would say "oh yeah, do x-y-z and you're fine". Guess I'll pull down source and deep-dive.
Onur Gumus
@OnurGumus
Jun 15 2018 17:12
instead try to simplify and isolate the case.
I am sure you will find.
Stephen Riley
@stephen-riley
Jun 15 2018 17:12
It totally did work until I put the code inside the lambda I'm passing to ContinueWith().
me-slove
@me-slove
Jun 15 2018 17:13
actorselection is probably a reference. in which case you'd be back to the closure problem
Stephen Riley
@stephen-riley
Jun 15 2018 17:13
I built the code first just using await httpClient.GetAsync()...
@me-slove , I've tried closing over it, too, and it still didn't work. Which is weird to me, cuz I figured if I'd closed over it, I'd get all the context linked to it and be fine.
me-slove
@me-slove
Jun 15 2018 17:14
inside the same code block it should work though. that seems a little odd
Stephen Riley
@stephen-riley
Jun 15 2018 17:15
Agreed, @me-slove , it is quite odd. I just re-tested that, still doesn't work.
var self = Self;
var context = Context;

httpClient.GetAsync(req.Url).ContinueWith(responseTask =>
{
    var mylogger = context.ActorSelection("/user/ConsoleLogger");
    var response = responseTask.Result;
    var duration = stopwatch.Elapsed.TotalMilliseconds;
    var msgResponse = new AkkaBlaster.Dto.WebResponse
    {
        StatusCode = response.StatusCode,
        Duration = duration
    };

    mylogger.Tell("message");
},
TaskContinuationOptions.AttachedToParent & TaskContinuationOptions.ExecuteSynchronously);
Onur Gumus
@OnurGumus
Jun 15 2018 17:17
@stephen-riley can you actually try to resolve the selection by calling Resolve ?
Stephen Riley
@stephen-riley
Jun 15 2018 17:17
The actor mylogger definitely receives the message, but it is from deadLetters, instead of from this httpclient actor.
@OnurGumus , I don't know about Resolve(), but I will try that!
Onur Gumus
@OnurGumus
Jun 15 2018 17:18
ActorSelection returns a selection , not an actor ref. You can get an actorRef by calling Resolve on the Selection.
Stephen Riley
@stephen-riley
Jun 15 2018 17:18
Do you mean ResolveOne()?
Onur Gumus
@OnurGumus
Jun 15 2018 17:18
which may fail if no such actor found.
yes that one
Stephen Riley
@stephen-riley
Jun 15 2018 17:18
k, let me try
Onur Gumus
@OnurGumus
Jun 15 2018 17:18
I would also move the resolution outside of your lambda.
there is no need to resolve it there. You can resolve before.
me-slove
@me-slove
Jun 15 2018 17:19
I haven't looked at the code for Context but what you are seeing for sure is that it is losing itself across the task boundary. It must be that it is derived instead of a variable
Stephen Riley
@stephen-riley
Jun 15 2018 17:22
It must be that it is derived instead of a variable
Yeah, @me-slove , looking that way.
@OnurGumus , interestingly, waiting 1 second on the ResolveOne() returned null. Waiting 10 seconds (totally arbitrary) resulted in a good reference.
Onur Gumus
@OnurGumus
Jun 15 2018 17:23
that's odd.
Stephen Riley
@stephen-riley
Jun 15 2018 17:23
however, still shows all messages as coming from deadLetters. :worried:
I verified with the Identify message that the path is fine.
I think I'm gonna just pull down source and start tracing in. Clearly I have more to understand about the inner workings of Akka.NET when using the TPL patterns. :smile:
me-slove
@me-slove
Jun 15 2018 17:27
protected static IActorContext Context
{
get
{
var context = InternalCurrentActorCellKeeper.Current;
if (context == null)
throw new NotSupportedException(
"There is no active ActorContext, this is most likely due to use of async operations from within this actor.");
            return context.ActorHasBeenCleared ? null : context;
        }
    }
it got screwy on the paste but it is definitely derived. here's the code https://github.com/akkadotnet/akka.net/blob/dev/src/core/Akka/Actor/ActorBase.cs
hectorcaban
@hectorcaban
Jun 15 2018 17:52
Since I am creating multiple child actors .. how do I do child actors with wildcard routes. ?
Stephen Riley
@stephen-riley
Jun 15 2018 18:35
@me-slove, after tracing into the code, I can confirm that InternalCurrentActorCellKeeper.Current is null when inside the ContinueWith() lambda.
So I guess it's just safe to assume that inside ContinueWith() (for this TPL-style IO handling), you have to be explicit because you simply don't have any current actor context for the calls to work with. shrugs
so that's why I have to explicitly specify a sender in Tell(), because of how the normal Tell() is implemented:
        public static void Tell(this IActorRef receiver, object message)
        {
            var sender = ActorCell.GetCurrentSelfOrNoSender();
            receiver.Tell(message, sender);
        }
It would be nice to solve this in the library, but short of making the "current self" concept a stack instead of a singleton, I don't see how to do that nicely. Oh well.
@me-slove and @OnurGumus, thanks for all your help! :smiley:
me-slove
@me-slove
Jun 15 2018 18:59
I using chaining a lot so I generally pass around the sender anyway so for me it works fine :)
Stephen Riley
@stephen-riley
Jun 15 2018 21:17
The more I think about it, @me-slove, I just wasn't thinking hard enough about how TPL works vis-a-vis the different threads your Task<T> might continue on, and how Akka won't know anything about that. Completely different runtime contexts.
I'm gonna have to think a lot more about this and how I would want this to work ideally so I had something like ContinueWith() that was Akka-aware. Anyway, thanks for the thoughts.
Aaron Stannard
@Aaronontheweb
Jun 15 2018 21:19
@stephen-riley we resolve Context by checking a thread-local variable
the value of Context is therefore, volatile
on top of that, the Context can change each time an actor processes a message
so it's a good practice to close over things like Sender and Self when you want to use them in continuations
Stephen Riley
@stephen-riley
Jun 15 2018 21:21
heh, glad you confirmed that for me, @Aaronontheweb , as looking into the thread-local storage aspect of it was next on my list. :smiley: This is quite fun digging into this all!
Aaron Stannard
@Aaronontheweb
Jun 15 2018 21:21
no problem
normally none of that stuff is an issue when you're working inside an actor
but yeah, when you want to re-use some of that state asynchronously
Stephen Riley
@stephen-riley
Jun 15 2018 21:21
This really all started from "why do I need to explicitly specify a sender in Tell() while inside a continuation?" Been quite a lot of fun digging in.
Aaron Stannard
@Aaronontheweb
Jun 15 2018 21:22
ah yeah
because our extension method that automatically supplies Self doesn't work outside the ActorCell
Context is basically the public API of the ActorCell
Stephen Riley
@stephen-riley
Jun 15 2018 21:22
I know I could/should use PipeTo() for what I'm doing to be a little more "proper" about things, but you know how it is: once you start pulling a thread, you gotta see what unravels. :smile:
Aaron Stannard
@Aaronontheweb
Jun 15 2018 21:22
I know how that feels
Stephen Riley
@stephen-riley
Jun 15 2018 21:22
Ah, okay. I need to read up on ActorCell, clearly.
Aaron Stannard
@Aaronontheweb
Jun 15 2018 21:23
ActorCell is what fits all of the different pieces of an actor together for user-defined actors
and most, but not all, built-in actors
connects the mailbox to the dispatcher to the actor implementation class
it's also what allows for safe restarting of actors too
there are some built-in actor types that operate without a cell, but they're special cases
router actors are one example
typically they're actors that don't need to obey the 1 message at a time guarantee
Stephen Riley
@stephen-riley
Jun 15 2018 21:24
Ah, okay. So it's really the central "actor infrastructure state" thing per thread, and encapsulates the context on which my actor code is running?
Aaron Stannard
@Aaronontheweb
Jun 15 2018 21:24
yep
the dispatching infrastructure in Akka.NET basically queues up groups of actors for processing
and can dispatch actors to work across an arbitrary number of threads
but one actor can only work on one thread at a time
if the actor still has unprocessed messages in its mailbox once it's finished
Stephen Riley
@stephen-riley
Jun 15 2018 21:25
So, hypothetically, if I wanted to create a library of continuation extension methods (eg. something like ContinueActorWith()), it's all about managing the ActorCell for the continuation code to run on?
Aaron Stannard
@Aaronontheweb
Jun 15 2018 21:25
it gets rescheduled back onto the dispatcher again for more processing
if you stick with what gets exposed via ActorContext
or whatever the Context interface is
that's all of the stable parts of the Cell API
and exposes everything you care about
most of what the ActorCell does internally is stuff like managing child actors
and handling deathwatch
etc
Stephen Riley
@stephen-riley
Jun 15 2018 21:26
Ah, okay.
Aaron Stannard
@Aaronontheweb
Jun 15 2018 21:27
there's some internal plumbing that might be interesting
albeit, it's unsafe
but it's public API
Stephen Riley
@stephen-riley
Jun 15 2018 21:27
roger that.
this is the ThreadStatic variable I mentioned earlier
we have a more safe way of exposing that somewhere
I don't remember where it is off the type of my head
but if you're curious about the internals, the ActorCell stuff is really at the heart of the actors
Stephen Riley
@stephen-riley
Jun 15 2018 21:29
No worries. I'll dig around.
Aaron Stannard
@Aaronontheweb
Jun 15 2018 21:29
that and the dispatching / mailbox system
Stephen Riley
@stephen-riley
Jun 15 2018 21:29
I'm a big fan of the Actor model, just wanted to see how it worked on .NET Core. This is pretty cool stuff.
Aaron Stannard
@Aaronontheweb
Jun 15 2018 21:30
welp, there's always lots of people in here answering questions
enjoy your stay and let us know what we can do to help you :p
Stephen Riley
@stephen-riley
Jun 15 2018 21:31
Thanks! And thanks for the help!