[akka-user] Pleasure doing business with event processor
We are currently in the process of writing ES CQRS system using akka persistence. Lately one of the aspects of the akka persistence architecture became hotly debated topic of our design discussions - namely - where are the business rules supposed to be applied in PersistenActor handling of a command. Martin Krasser states in his blog that Event sourced processors do not persist commands. Instead they allow application code to derive events from a command and atomically persist these events. After persistence, they are applied to current state. It would help to get some clarification what does the event derivation process entail in general. Is it purely transforming incoming event to one or more events and perhaps tagging on some additional contextual information? Or, does this process also entail running necessary business logic to create the events, which will eventually update the state? Sample implementation of the PersistentActor included with akka persistence documentation (http://doc.akka.io/docs/akka/snapshot/scala/persistence.html) shows how the command handler could be implemented: 1. val receiveCommand: Receive = { 2. case Cmd(data) = 3. persist(Evt(s${data}-${numEvents}))(updateState) 4. persist(Evt(s${data}-${numEvents + 1})) { event = 5. updateState(event) 6. context.system.eventStream.publish(event) 7. } 8. case snap = saveSnapshot(state) 9. case print = println(state) 10. } This however is a very simplistic example, which does not answer my question: where are the business rules applied? updateState handler could be interpreted as such place. On the other hand perhaps it's the constructor of the event (Evt) that symbolizes application of business rules by creating an event from command content. Implications of either interpretation are important to us especially when taking into account state recovery process. Here is what the sample PersistenActor code has for state recovery: 1. val receiveRecover: Receive = { 2. case evt: Evt = updateState(evt) 3. case SnapshotOffer(_, snapshot: ExampleState) = state = snapshot 4. } 5. Is updateState handler's responsibility limited to making changes to state based on events, or is it to apply business rules to the state based on change event? In the latter case that would mean that business rules are also invoked during reply of events while state is being restored. Such interpretation would allow applying business logic fixes retroactively to state, but would also introduce code versioning issues. Any help with understanding of this aspect of the akka persistence architecture would be greatly appreciated. Thanks in advance! -- Read the docs: http://akka.io/docs/ Check the FAQ: http://doc.akka.io/docs/akka/current/additional/faq.html Search the archives: https://groups.google.com/group/akka-user --- You received this message because you are subscribed to the Google Groups Akka User List group. To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+unsubscr...@googlegroups.com. To post to this group, send email to akka-user@googlegroups.com. Visit this group at http://groups.google.com/group/akka-user. For more options, visit https://groups.google.com/d/optout.
Re: [akka-user] Pleasure doing business with event processor
Hi George! I’ll start with the infameous “it depends”, but let’s get into a more constructive answer :-) As updateState is not really something akka forces you to do - it’s simply a pattern we’ve found to be useful. The core of it is “a method which you can call from both `receiveCommand` and `receiveRecover`”. I’d split methods in terms of “does interactions with outside world and should not be triggered on recovery” and “does not trigger interactions with outside world”. But for example if you create child actors as part of your domain logic, you will want to trigger this during replay - to be ready for an incoming request which needs them etc. I for one would not put much logic into events. I tend to keep them as simple as markers that “stuff happened” - when actions need to be made, I’d use actors to do them. Putting a require() or two in there may be ok, but I wouldn’t put more complicated stuff into an event - it’s some actor that would “perform” the work. As for commenting Martin’s quote, by Command he means “incoming message” (as does our PersistentActor#receiveCommand), and by Event he means “the event that the Persistent Actor has persisted, as effect of that incoming command”. This means: command comes in, apply some logic to it, store “result” of that logic as event (SignedUp / UserNameTaken etc.), and act upon this event (once it’s persisted safely). So the logic leads to storing of events. I hope this helps, feel free to ask more or give examples of what you’d need :-) Happy hakking! -- Konrad 'ktoso' Malawski hAkker @ typesafe http://akka.io -- Read the docs: http://akka.io/docs/ Check the FAQ: http://doc.akka.io/docs/akka/current/additional/faq.html Search the archives: https://groups.google.com/group/akka-user --- You received this message because you are subscribed to the Google Groups Akka User List group. To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+unsubscr...@googlegroups.com. To post to this group, send email to akka-user@googlegroups.com. Visit this group at http://groups.google.com/group/akka-user. For more options, visit https://groups.google.com/d/optout.
Re: [akka-user] Pleasure doing business with event processor
I'll try to answer your questions with an example (omitting the updateState pattern): 1. val receiveCommand: Receive = { case ChargeCreditCard(payload) = { // Enforce business rules, constraints, etc. if (isNotEnough(payload.amount)) sender ! Can I haz more? // Some rule violations might trigger their own events if (looksFake(payload.creditCard)) { persist(PossibleFakeCardEncountered(...)) { _ = fraudSuspected = true} sender ! Please stay where you are, local authorities will be there any minute. } // If everything's okay do the actual work var charged = Try(paymentGateway ! charge(payload.creditCard, payload.amount, ...)) // Once the work is done, change state (if nesessary) and persist the event(s) charged match { case Success(_) = persist(CreditCardCharged(...)) { _ = paid = true } case Failure(e) = { persist(PaymentProviderMessedThingsUpAgain()) sender ! There was an issue, please send a check. } } } val receiveRecover: Receive = { case CreditCardCharged = paid = true case PaymentProviderMessedThingsUpAgain = // no state change needed case PossibleFakeCardEncountered = fraudSuspected = true } The important thing here is that the command handler (receiveCommand) guards against invalid input, checks business rules, enforces constraints, does the actual work and emits events. The event handler (receiveRecover) does nothing but change state according to the received events. You wouldn't want to charge a credit card every time you rehydrate the actor from the event store. Hope this helps, Dennis On Thu, Jul 31, 2014 at 9:19 PM, Konrad 'ktoso' Malawski konrad.malaw...@typesafe.com wrote: Hi George! I’ll start with the infameous “it depends”, but let’s get into a more constructive answer :-) As updateState is not really something akka forces you to do - it’s simply a pattern we’ve found to be useful. The core of it is “a method which you can call from both `receiveCommand` and `receiveRecover`”. I’d split methods in terms of “does interactions with outside world and should not be triggered on recovery” and “does not trigger interactions with outside world”. But for example if you create child actors as part of your domain logic, you will want to trigger this during replay - to be ready for an incoming request which needs them etc. I for one would not put much logic into events. I tend to keep them as simple as markers that “stuff happened” - when actions need to be made, I’d use actors to do them. Putting a require() or two in there may be ok, but I wouldn’t put more complicated stuff into an event - it’s some actor that would “perform” the work. As for commenting Martin’s quote, by Command he means “incoming message” (as does our PersistentActor#receiveCommand), and by Event he means “the event that the Persistent Actor has persisted, as effect of that incoming command”. This means: command comes in, apply some logic to it, store “result” of that logic as event (SignedUp / UserNameTaken etc.), and act upon this event (once it’s persisted safely). So the logic leads to storing of events. I hope this helps, feel free to ask more or give examples of what you’d need :-) Happy hakking! -- Konrad 'ktoso' Malawski hAkker @ typesafe http://akka.io -- Read the docs: http://akka.io/docs/ Check the FAQ: http://doc.akka.io/docs/akka/current/additional/faq.html Search the archives: https://groups.google.com/group/akka-user --- You received this message because you are subscribed to the Google Groups Akka User List group. To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+unsubscr...@googlegroups.com. To post to this group, send email to akka-user@googlegroups.com. Visit this group at http://groups.google.com/group/akka-user. For more options, visit https://groups.google.com/d/optout. -- Read the docs: http://akka.io/docs/ Check the FAQ: http://doc.akka.io/docs/akka/current/additional/faq.html Search the archives: https://groups.google.com/group/akka-user --- You received this message because you are subscribed to the Google Groups Akka User List group. To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+unsubscr...@googlegroups.com. To post to this group, send email to akka-user@googlegroups.com. Visit this group at http://groups.google.com/group/akka-user. For more options, visit https://groups.google.com/d/optout.