These are chat archives for petabridge/akka-bootcamp

25th
Jun 2015
Jens Pettersson
@jenspettersson
Jun 25 2015 06:08
Hello. Are there any good examples on Persistence with Akka.net? I'm struggling to wrap my head around using Akka.net in a DDD:ish way with Aggregate roots (as actors?) and how to persist (and retreive) everything. Like in this example from @rogeralsing http://rogeralsing.com/2014/11/10/akka-net-concurrency-control/ - how are the Bank Accounts stored and later retreived to be used? Are all persisted actors (in this case, bank accounts) always loaded and "active" inside the Actor System? What is responsible for loading them in that case?
Thomas Lazar
@thomaslazar
Jun 25 2015 06:12
i guess the question is what kind of persistence you're talking about. do you want to persist some entities in a db. or do you want to persist the state and message queue of your actors.
Jens Pettersson
@jenspettersson
Jun 25 2015 06:15
Persist some entities in a db, probably just to try to resemble a "traditional" way of doing things to see if I can start migrating parts of my system to use actors but still use the same persistence method. This might be the wrong approach, but I need to wrap my head around these things =)
Bartosz Sypytkowski
@Horusiath
Jun 25 2015 06:17
@jenspettersson I've never finished this example, but it shows some concepts to start with (don't look at 2-phase transactions part, it's not a good fit there ;) )
Bartosz Sypytkowski
@Horusiath
Jun 25 2015 06:28
In akka.net, currently I've found 2 ways of dealing with loading/harvesing persistent actors.
  1. you have some aggregate coordinator, which you request for your aggregates. If has internal collection of children aggregates - if they are already loaded, they are returned immediately. If not it will create them and return. In my example there is a limit of allowed children buffer, so that you won't overuse the memory. If limit is passed it will harvest X actors to free part the buffer. Coordinator is a proxy for messages send to aggregates - it also buffers messages waiting for aggregates to being recreated.
  2. Same think - aggregate coordinator returns aggregates on demand. But here each aggregate uses Context.SetReceiveTimeout method to identify if it's not used for some period of time. If so, it will receive ReceiveTimeout message. Then it should send some kind of Passivate message back to coordinator and stop itself. Passivate is necessary so that coordinator knows not to send any messages to the dying aggregate. If there are some messages pending, coordinator caches them, then recreates an aggregate and finally sends waiting messages back to it.
Difference between 1 and 2 is that first defines some pool of actors, that you won't exceed, but you won't know if actor is not used for a longer period of time and be able to automatically free the aggregate pool. In second you don't have a pool, but each actor knows, for how long it has not been used and it's able to "recycle" itself if no longer needed. Cons is that you could possibly have more actors at the moment, than your memory is allowed to fit. Ofc you can create a hybrid of both approaches.
Bartosz Sypytkowski
@Horusiath
Jun 25 2015 06:39
I think that general advice in case of the akka is: You have a problem? Try to move it to separate actor
Thomas Lazar
@thomaslazar
Jun 25 2015 06:40
that`s good advice
ups. sorry
Jens Pettersson
@jenspettersson
Jun 25 2015 06:41
Thanks @Horusiath, great explanation and it seems to make sense ;) Will try this approach on a small scale example domain...
Nripendra Nath Newa
@nripendra
Jun 25 2015 17:13
I have following strategy: return new OneForOneStrategy(
maxNrOfRetries: MAX_DOWNLOAD_RETRIES,
withinTimeRange: TimeSpan.FromSeconds(30),
localOnlyDecider: x =>
{
if (x is ActorInitializationException) return Directive.Stop;
if (x is ActorKilledException) return Directive.Stop;
if (x is HttpRequestException) return Directive.Resume;
return Directive.Restart;
});
Now, I want to do something after all retries fails, is it possible?
Roger Johansson
@rogeralsing
Jun 25 2015 17:15
yes, in local only decider you can do additional logic, but a cleaner way might be to override one of the actor lifecycle methods
Nripendra Nath Newa
@nripendra
Jun 25 2015 17:16
How to know all retries has failed for the child actor, at the supervisor level?
Roger Johansson
@rogeralsing
Jun 25 2015 17:27
poststop will be called on termination, but that will also be called on normal termination, eg. if someone manually stops the actor, so that might or might not work for you
in the supervisor strategy, there is no good way to check if it is the last retry.. you could possibly hack that in the lambda using a dictionary or something, but nothing supported
Nripendra Nath Newa
@nripendra
Jun 25 2015 17:28
Hmm, poststop occurs at the child level right?
Roger Johansson
@rogeralsing
Jun 25 2015 17:29
yes
at the actual actor that is stopped
Nripendra Nath Newa
@nripendra
Jun 25 2015 17:31
So, is it good idea to put a counter to the message that is causing the actor to fail? I'll catch exception, increment counter in message and throw exception again?
Another question arises can I access that message at PostStop? Probably via stash?
Roger Johansson
@rogeralsing
Jun 25 2015 17:33
you could have a counter inside the actor that counts how many times it has retried the same message, but dont put the counter in the message itself, because if you send the same message to more than one actor, you will get concurrency issues
messages should always be immutable
Its a simple example showing how you can do this. Not saying its the way. But this gives you a good idea.
Roger Johansson
@rogeralsing
Jun 25 2015 17:35
btw. there is another way to deal with the poststop thing. the supervisorstrategy actually have an overridable method HandleChildTerminated that is called after the last retry, so if you create a custom supervisor strategy, you could have special logic there too
Nripendra Nath Newa
@nripendra
Jun 25 2015 17:36
Hmm, so.. you mean inheriting OneForOneStrategy?
Arjen Smits
@Danthar
Jun 25 2015 17:36
hmm @rogeralsing correct me if im wrong. but cant you also do that with Deathwatch and the Terminating message ?
Roger Johansson
@rogeralsing
Jun 25 2015 17:37
@Danthar yepp
Arjen Smits
@Danthar
Jun 25 2015 17:37
:+1:
Roger Johansson
@rogeralsing
Jun 25 2015 17:37
but the same applies for that as for PostStop, you dont know if it was caused by an exception or by manual termination
Arjen Smits
@Danthar
Jun 25 2015 17:37
true
Nripendra Nath Newa
@nripendra
Jun 25 2015 17:38
What about HandleChildTerminated ? Is it called due to exception?
Roger Johansson
@rogeralsing
Jun 25 2015 17:39
yes only on excepton (or as a result of an excepton terminating a parent)
Nripendra Nath Newa
@nripendra
Jun 25 2015 17:41
Ok, that sounds like would solve my problem. I'll check.
Nripendra Nath Newa
@nripendra
Jun 25 2015 18:16
Thanks, looks like it solves exactly what I'm trying to do.