[akka-user] Pleasure doing business with event processor

2014-07-31 Thread George Wilk
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

2014-07-31 Thread Konrad 'ktoso' Malawski
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

2014-07-31 Thread Dennis Traub
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.