These are chat archives for akkadotnet/akka.net

19th
Oct 2016
Vagif Abilov
@object
Oct 19 2016 07:14

Hello, I continue my experiments with Akka Streams, and there's a workflow I can't figure out:

        Source
            .From(Enumerable.Range(1, 10))
            .Select(x => new[] {x + 10, x + 20, x + 30})
            .DoSomethingInParallelWithEachElementOfTheArrayFromTheStepAbove()
            .AggregateResultsOfThePreviousStep()
            .To(sink);

What happens is that each element of the steam source is converted into a collection, and the want to perform certain operations on each collection item and merge results back. I can't figure out how to express it in Akka Streams terms.

verilocation
@verilocation
Oct 19 2016 09:22
@peter-bannerflow Thanks, that looks good... Only issue with that (After playing around with it) is that if you deploy things remotely you can't get performance of entire cluster if remoting is used. The performance is gathered on a node by node basis rather than actorsystem basis.
Peter Bergman
@peter-bannerflow
Oct 19 2016 09:25
Hmm... right, but I guess you could send the data to some central service and analyze it there, like for example we plan to use Akka.Monitoring with windows Perfomance Counters and then gather data to Splunk (or similar).
Only thing is that right now there are some perfomance issues with using Perfomance Counters and Akka.Monitoring (petabridge/akka-monitoring#31)
verilocation
@verilocation
Oct 19 2016 09:27
Thanks Peter... Btw if it helps I found this the other day which provides some basic monitoring (but not message throughput unfortunately) https://github.com/cgstevens/Akka.Cluster.Monitor
Peter Bergman
@peter-bannerflow
Oct 19 2016 09:28
Right, I actually played around with that one a couple of days ago as well :)
verilocation
@verilocation
Oct 19 2016 09:28
I wonder how easy it'd be to implement your own monitor that simply gathers data and broadcasts it so that another actor or service can pick it up and deal with it
Gregorius Soedharmo
@Arkatufus
Oct 19 2016 09:34
@qwoz if you know your queries beforehand, you can do some sleight of hand, build the aggregate result in a different aggregate actor piece-meal while everything is running
that way it'll be a constant time query every time
Gregorius Soedharmo
@Arkatufus
Oct 19 2016 09:41
have an aggregating actor, say... MostBorrowedBooksActor, every time a book gets borrowed, it increment its internal borrowed counter then send a message to that actor (or you can use pub/sub), all that actor need to do it compare the number to the internal list it have, if its in the... say... top 1000, insert the new information, sort the list, discard the 1001 item, and bob's your uncle
verilocation
@verilocation
Oct 19 2016 09:45
@qwoz This kinda seems more complicated that it should be? If the BookManagerActor queries the db for 1000 books, would it not just return (or send on) that data as opposed to creating 1000 actors?
Gregorius Soedharmo
@Arkatufus
Oct 19 2016 09:58
i'm assuming that books are just an analogy, and the requirement is more complex than a library catalog server?
verilocation
@verilocation
Oct 19 2016 09:59
Just a quick related question.. presumably if I had a List of N records (say 100) to return to an API, I could simply Tell and it would work.. There is no message size limit that would affect modest amounts of data? If there any message size limit at all? Say for example I wanted to send a file, how would I do that?
Gregorius Soedharmo
@Arkatufus
Oct 19 2016 10:10
from actor to actor on the same machine?
verilocation
@verilocation
Oct 19 2016 10:10
from Actor to Actor, location unaware
Gregorius Soedharmo
@Arkatufus
Oct 19 2016 10:10
pass an uri?
verilocation
@verilocation
Oct 19 2016 10:11
Could do.. that would mean configuring access rights on machines when Akka.net promotes location transparency
Gregorius Soedharmo
@Arkatufus
Oct 19 2016 10:15
well, I don't know how the underlying socket implementation works in akka (helios is it?), but the file would get parceled into chunks any way, so it shouldn't be a problem
verilocation
@verilocation
Oct 19 2016 10:15
ok cool just checking :)
and yes its helios
Arsene T. Gandote
@Tochemey
Oct 19 2016 11:39
Hello does Akka support logary?
Bartosz Sypytkowski
@Horusiath
Oct 19 2016 12:23
@bannerflow-hassaan question: do you have mutliple instances of the same persistent actor id at the same time? I.e. on different nodes.
Syed Hassaan Ahmed
@bannerflow-hassaan
Oct 19 2016 12:25
@Horusiath No, we only have one instance of this actor.
Bartosz Sypytkowski
@Horusiath
Oct 19 2016 12:27
@object you can use SelectAsync or SelectAsyncUnordered to perform parallel operations, then SelectMany to flat map collections into single elements to the stream and then Aggregate, Sum or Scan to reduce results
Syed Hassaan Ahmed
@bannerflow-hassaan
Oct 19 2016 12:28
@Horusiath Also in the Journal, we can see "PersistenceId": "workerSupervisorActor", "SequenceNr": 1 .. However in error description it says "Persistence failure when replaying events for persistenceId [workerSupervisorActor]. Last known sequence number [0]"
Gregorius Soedharmo
@Arkatufus
Oct 19 2016 12:29
@verilocation regarding your ask/tell question on the 17th, i ran into the same problem yesterday and found that you can do myActorRef.Tell(message, Sender) so i don't have to polute my POCO with IActorRefs
verilocation
@verilocation
Oct 19 2016 12:30
@Arkatufus Thanks dude, I use that now actually. And I inject another Actor ref in the constructor when I create the actor so I can send the message to another actor too
Bartosz Sypytkowski
@Horusiath
Oct 19 2016 12:30
@bannerflow-hassaan and what the exception actually says?
verilocation
@verilocation
Oct 19 2016 12:30
In fact, through doing that, and some async improvements, and using pipeto, my system now works very fast
Syed Hassaan Ahmed
@bannerflow-hassaan
Oct 19 2016 12:31
@Horusiath "Persistence failure when replaying events for persistenceId [workerSupervisorActor]. Last known sequence number [0]"
Bartosz Sypytkowski
@Horusiath
Oct 19 2016 12:31
this is an error message, but not the actual exception
Syed Hassaan Ahmed
@bannerflow-hassaan
Oct 19 2016 12:32
That's the only thing we see in NLog
Bartosz Sypytkowski
@Horusiath
Oct 19 2016 12:32
_log.Error(reason, "Persistence failure when replaying events for persistenceId [{0}]. Last known sequence number [{1}]", PersistenceId, LastSequenceNr); - reason is the Exception which was thrown there
good to know
I would guess that the event journal is corrupted or not accessible, as it's most probably not able to retrieve the last known sequence nr
Syed Hassaan Ahmed
@bannerflow-hassaan
Oct 19 2016 12:37
Yes .. seems like it .. Where does it retrieve the last known sequence nr from?
Gregorius Soedharmo
@Arkatufus
Oct 19 2016 12:38
you could wrap the code in a try-catch and log the error the old fashion way?
that should give you more information than the vague generic error log
Bartosz Sypytkowski
@Horusiath
Oct 19 2016 12:38
this depends on the provider, if you have redis I'd look here
so probably in your case the key would be akka:persistence:journal:workerSupervisorActor.highestSequenceNr
Vagif Abilov
@object
Oct 19 2016 12:47
@Horusiath thanks! SelectAsync takes "Task asyncMapper" as a parameter so I supposed asyncMapper is executed as a plain method, not wrapped within an actor?
Syed Hassaan Ahmed
@bannerflow-hassaan
Oct 19 2016 12:48
@Horusiath Thanks .. looked into it and can see that highestSequenceNr in Redis is correctly set to 1 .. so call to ReadHighestSequenceNrAsync either fails or doesn't happen before events are replayed
Bartosz Sypytkowski
@Horusiath
Oct 19 2016 12:49
it's not 1 actor for 1 method invocation, but SelectAsync sets an async boundary, which means that the next transformation will be executed on another actor - this however should be only an implementation detail for you
@bannerflow-hassaan rather fails, it must be returned before events are replayed as they rely on that number
Vagif Abilov
@object
Oct 19 2016 12:52
@Horusiath so if my asyncMapper loops through a collection and calls an external service per each collection element, they will all be executed in the scope of that another actor? And what if I want to isolate each external service call and wrap into an actor?
John Nicholas
@MrTortoise
Oct 19 2016 12:53
@qwoz I have done it through actors. Its possible, but when you start getting what are effectivley joins then things rapidly start to lose joy. Things like where clauses are tricky. But it all depend son architecture tradeoffs. Given ideal id probably have an event store for the actor system and a rdb to pull denormalised views from.
Bartosz Sypytkowski
@Horusiath
Oct 19 2016 12:56
@object I think you're putting too much weight to actors when it comes to akka streams ;) they have their own fault handling semantics, so you can just call: source.SelectAsync(url => service.GetSomeCollectionAsync(url)).SelectMany(elements => elements)
if error will happen in Select async, it will be propagated down the stream (but as OnError message instead of usuall OnNext, so SelectMany won't be called for that error), then you can capture it using RecoverWith method which will be called each time exception was thrown
Vagif Abilov
@object
Oct 19 2016 13:02
@Horusiath thanks. Yes transition from plain actors to Akka streams take change of habits, and apparently my mind is still locked into "an actor per operation" way of thinking. Great explanation, I will think it through.
Gregorius Soedharmo
@Arkatufus
Oct 19 2016 14:45
i'm a bit perplexed here... i'm trying to use the Ask() pattern, webAPI calls var result = await actorA.Ask(request);, after actorA's done with its job, it passes the job over to ActorB using ActorB.tell(jobresult, Sender);, and after ActorB finished successfully, it calls Sender.Tell(finalResult);, but finalResult always ends up in the unhandled message pile...
verilocation
@verilocation
Oct 19 2016 14:46
where does B send the result to?
the first actor?
Gregorius Soedharmo
@Arkatufus
Oct 19 2016 14:46
the original sender that was in ActorA
verilocation
@verilocation
Oct 19 2016 14:46
how does the first actor know not to return to the ask? until it has the reply from b
Gregorius Soedharmo
@Arkatufus
Oct 19 2016 14:46
which, i think, is referencing the empty actor in the original Ask
verilocation
@verilocation
Oct 19 2016 14:47
You could use Forward within A to B, and then when B Tells itll have A marked as the sender... A will then receive its reply and all shall be well
  • WebAPI - Ask ActorA
  • ActorA - Forward message to B
  • ActorB - Tell sender (who is WebAPI) the response, completing the Ask
Marc Piechura
@marcpiechura
Oct 19 2016 14:48
Tell(msg,Sender) should be the same as forward
Gregorius Soedharmo
@Arkatufus
Oct 19 2016 14:48
its not a simple forward though, ActorA actually does some work first
verilocation
@verilocation
Oct 19 2016 14:49
@Silv3rcircl3 Of course, mb
Marc Piechura
@marcpiechura
Oct 19 2016 14:49
Is T in Ask<T> from the same type as the result Message?
verilocation
@verilocation
Oct 19 2016 14:49
You sure that B is responding with the correct Type? Else the WebAPI might ignore the response
Gregorius Soedharmo
@Arkatufus
Oct 19 2016 14:50
oh crud... that might be it...
can i do Ask<object>()? because the response might be one of two messages
Richard Tasker
@ritasker
Oct 19 2016 14:53
Hey everyone. I am wanting to write a PoC project using Akka on core clr. Is there a public nuget feed I can use to access the dot net core packages?
verilocation
@verilocation
Oct 19 2016 14:53
Personally I'd say that smells... no point in using Types if you're going to do that. Perhaps you need two API calls? Perhaps you need to make two requests to two actors, each typed? Perhaps the return type is wrong, and what you really need is something like this:
public class MessageResponse
{
  public MyClass Result1 { get; set; }
  public MyClass2 Result2 { get; set; }
}
Gregorius Soedharmo
@Arkatufus
Oct 19 2016 14:54
well, the result could be a success or an error
its an authentication call to the backend, and then gets forwarded to amazon cognito
verilocation
@verilocation
Oct 19 2016 14:55
So have an AuthenticationResponse with a property for UserInfo and one for Status which indicates success?
(Just thinking aloud here)
Gregorius Soedharmo
@Arkatufus
Oct 19 2016 14:56
i'll give that a go, thanks
Aaron Stannard
@Aaronontheweb
Oct 19 2016 15:08
@corneliutusnea had some requests during our Akka.Remote training last night for a websockets transport
mulling it over - if I recall correctly, this is something you'd need to run on Azure AppService too right?
Gregorius Soedharmo
@Arkatufus
Oct 19 2016 15:18
@verilocation nope, still ends up in the unhandled pile
[DEBUG][10/19/2016 3:29:05 PM][Thread 0008][akka://SolehWebService/user/$b/$a/$b] Unhandled message from akka://SolehWebService/user/$b : SolehServer.Messages.AuthResponse
Gregorius Soedharmo
@Arkatufus
Oct 19 2016 15:46

Web service:

AuthResponse result;
try {
    result = await Global.AuthActor.Ask<AuthResponse>(new RegisterUser(register), TimeSpan.FromSeconds(10));
} catch (TaskCanceledException e) {
} catch (Exception e) {
}

Auth actor:

Receive<RegisterUser>(msg => {
    MembershipCreateStatus result = _membership.CreateUser(msg.UserName, msg.Email, msg.Password);
    if (result == MembershipCreateStatus.Success) {
        _cognitoActor.Tell(new CognitoAuthRequest(msg.Email), Sender);
        return;
    }
    Sender.Tell(new AuthResponse(result));
});

Cognito actor:

Receive<CognitoAuthRequest>(msg => {
    GetOpenIdTokenForDeveloperIdentityResponse idResponse = null;
    try {
        idResponse = _identClient.GetOpenIdTokenForDeveloperIdentity(idRequest);
    } catch (Exception e) {
        Sender.Tell(new AuthResponse(MembershipCreateStatus.ProviderError));
        return;
    }
    Sender.Tell(new AuthResponse(idResponse.IdentityId, idResponse.Token));
});
so the web service module always gets the TaskCanceledException, the AuthResponse from the successful cognito call always ends up in unhandled
verilocation
@verilocation
Oct 19 2016 15:48
Interesting.. its not taking longer than 10s is it?
(youve not got breakpoints set either that would make it take longer than 10s)
Gregorius Soedharmo
@Arkatufus
Oct 19 2016 15:48
well, yeah, its taking more than 10s, because its not getting any response
verilocation
@verilocation
Oct 19 2016 15:49
But I mean, if you write out the time in the web api code block, and then again in the end of the receive cognitoauthrequest block.. the time difference is less than 10s?
Gregorius Soedharmo
@Arkatufus
Oct 19 2016 15:49
oh, well, the unhandled debug message always shows up before the exception was caught
Gregorius Soedharmo
@Arkatufus
Oct 19 2016 15:55
by 5-6 seconds
i actually logged everything, i just take them out from the code i've posted cause, i mean, they're just logs
Gregorius Soedharmo
@Arkatufus
Oct 19 2016 16:03
the Ask pattern should work even if the worker actors are behind a pool router, right?
verilocation
@verilocation
Oct 19 2016 16:04
Yup, ive used it in that manner
Cant think of what your problem could be though, have you tried using Forward instead of Tell. I know its meant to be the same thing, but there nothing obvious with your code hence me thinking of more obscure things :P
Gregorius Soedharmo
@Arkatufus
Oct 19 2016 16:06
i'll give it a go, won't hurt to try
nope
Gregorius Soedharmo
@Arkatufus
Oct 19 2016 16:19
how do akka handle IActorRef internally between Receive?
because I tried to store the IActorRef from ActorA inside the message, and then did a simple reference equality check in ActorB and they're not the same
verilocation
@verilocation
Oct 19 2016 16:21
I doubt they would be the same reference but I'd expect them to have equality.. although ive never actually dived into an IActorRef to check its contents
Gregorius Soedharmo
@Arkatufus
Oct 19 2016 16:37
yeah, that was the key
turns out it was my own stupid mistake, i forgot to forward the message in the router coordinator actor
Jeff
@jpierson
Oct 19 2016 18:30
A while back I noticed Waffle.io was being used to track work items for Akka.net. How well has it been working? Looking between waffle.io and zenhub myself at the moment.
qwoz
@qwoz
Oct 19 2016 19:19
@Arkatufus correct... books are just an analogy to help me wrap my head around a problem I'm modeling in a way that ought to be understandable by everybody without having to have me explain my problem domain.
@verilocation @MrTortoise thanks for the pointers... what I'm looking to do is get the benefits of actors (as in "the data is already loaded in-memory, it's fast!") but when you're dealing with lots of items, it seems that the model breaks down and you can no longer query that data in memory since the overhead of doing that and querying dozens, hundreds, or thousands of actors doesn't make much sense.
qwoz
@qwoz
Oct 19 2016 19:53
What I gather is that the benefits of keeping things persistent in an actor happens for performing operations ("commands", to use CQRS terminology). If the actor you're performing an operation on already exists, then it doesn't need to re-load its own data from the DB and can perform the operation in-memory and that's where speed comes from. However, if you're doing querying then the benefits of actors aren't as apparent. It might make sense (on a case-by-case basis) if you're retrieving information from a single actor, but if that single actor needs to collate information together from various other actors the returns start to diminish.
qwoz
@qwoz
Oct 19 2016 20:21
Using my library books example, getting a list of books might depend on whether or not the user's preferences are set to allow Large Print, Children, and Magazine items within results. Additionally, the user may not have permission to access Research Journals or Digital Copies. So it seems like anything beyond retrieving single items really can't benefit from have the data resident in an actor. It's only when you perform multiple operations over time on a single actor that you get the benefit of resident data for all but the first operation (which necessarily has to load it from some datastore).
John Nicholas
@MrTortoise
Oct 19 2016 20:56
@qwoz just curious what do you do? (my wife is a librarian)
John Nicholas
@MrTortoise
Oct 19 2016 21:12
@qwoz I disagree with can't. You are describing caching, the performance characteristic you are describing is also true of any database - or even anything. The first time will always be slow.
given non infinite ram - i think the actor system is especially well suited to the command part and DDD in general (but also orchestration of tasks in general), an event store of some kind backing it makes sense. Its then easy to output that into some kind of transactional database (probably an edge database) and then you might ahve a relational database being built off that for reporting. Ofc you may also go broke from licensing costs and time.
This message was deleted
qwoz
@qwoz
Oct 19 2016 21:26
@MrTortoise lol, I'm not a librarian if that's what you're asking, though I'm a huge fan of libraries and books in general. I have a boring business-level CRUD kind of app that I'm trying to model using actors and I've been finding cases where it does and doesn't make sense (to me anyways, I could be completely wrong) when I go through the thought exercise.
and you're right that my use of can't isn't technically correct. I should have said that you end up with significantly diminishing returns when querying beyond a single actor. Caching is good when what you're retrieving is expensive, but where a cached response is quick. But if you need to collect information from multiple actors then the sum total of the time taken to retrieve information from each actor will quickly exceed the time it takes to directly fetch from a database, particularly if some of those actors are "cold" and need to be started up, fetch their individual data first, and so on.
qwoz
@qwoz
Oct 19 2016 21:33

Basically, I'm dubious about how far one can go with the stateful approach: https://petabridge.com/blog/stateful-web-applications/ -- in particular, this part:

Actors can be stateful - and that means we no longer have to factor round-trip times to SQL Server, Redis, Cassandra, or whatever into the design of our applications. The application already has the state it needs to do its job by the time a request arrives!

John Nicholas
@MrTortoise
Oct 19 2016 21:36
but you can query in memory sooo much faster than hitting a database
crudley, its 2 network calls faster
but if you want to query a large cube, then rdb is goign to have far better results
also your actor system - or rather the event store behind it - is going to be your source of truth
everything else will lag
but all these things are scale, cant say ive ever had to balance and measure that kind of scale in prod
John Nicholas
@MrTortoise
Oct 19 2016 21:46
then you have sharding which adds another dimension and increases the minimum query time
qwoz
@qwoz
Oct 19 2016 21:56
right, so let's say I have a LibraryPatron actor and I send a message to it GetListOfBorrowedBooksand I expect back List<Book>. There seems to be two approaches I could take:
  1. Just get it from the database directly and return the results, eg: return Patron.BorrowedBooks.ToList<Book>; or some other join query or similar.
  2. If the patron already has a list of, for example, borrowed book IDs, then iterate over each one, asking that individual book actor for its information, then collate and return the results.
qwoz
@qwoz
Oct 19 2016 22:11
Option 2 would definitely work, but as each Book actor would need to lookup its own information (first time only) and the Patron would need to switch to a state where it's collecting messages from each book actor (potentially hundreds) that seems very complicated with a ton of overhead.
John Nicholas
@MrTortoise
Oct 19 2016 22:15
well in 2 if you query it once you are probably goign to query it again
imo dont get too hung up on the first time
really do it both ways, then measure and reflect ;p
qwoz
@qwoz
Oct 19 2016 22:22
Yep, I'll try prototyping both approaches and benchmark. Is there some sample code on firing off n messages to n actors and then collecting all the replies? I'm thinking if there are, for example, 100 books I can set some private variable int ExpectedBookResponses to 100 then Become(CollectBookReplies), decrement the counter with each Book object the actor receives, and when it reaches 0, return the accumulated List<Book> object. Or is there a better way?
John Nicholas
@MrTortoise
Oct 19 2016 22:32
This message was deleted
qwoz
@qwoz
Oct 19 2016 22:36
Aggregator pattern... thanks.