Got it
Thanks a lot!

El sábado, 9 de septiembre de 2017, 3:34:26 (UTC-3), Patrik Nordwall 
escribió:
>
> Hi Sebastian,
> Validation should be done before persist, and your code is correct.
> Exceptions from validation should not be thrown, your conclusion is 
> correct.
>
> Regarding unforeseen bugs, NPE, it can be better in a production system to 
> survive also that by restarting (perhaps it was just a corner case). What 
> would the alternative be? Exit the JVM? The bug should of course be fixed, 
> but that can be done on Monday if the exception was thrown during the 
> weekend.
>
> /Patrick
>
> On Sep 5, 2017, at 16:09, Sebastian Oliveri <[email protected] 
> <javascript:>> wrote:
>
>
> I am going to describe a concrete scenario I have: "*an item can be 
> removed from the menu*"
>
> class MenuActor extends PersistentActor {
>
>
> var state: Option[Menu] = None
>
>
> override def receiveCommand: Receive = {
>
>  
>
> case remove: RemoveItem =>
>
>   persist(MenuItemRemoved(remove.itemId)) {
>
>     event =>
>
>       state = state.map(_.remove(event.itemId))
>
>       sender ! state.get
>
>   }
>
> // ... other handlers 
>
> } 
>
> } 
>
> The Menu aggregate root raises a *BusinessException("$itemId does not 
> exist") *if obviously the item identified by the given ID does not exist 
> in the Menu.
>
> In the concrete case of an HTTP client this error would be map to a 400 
> status code containing the descriptive message as any other "breaking 
> aggregate invariant" scenario.
>
> What I am doing right now is this:
>
> class MenuActor extends PersistentActor {
>
> var state: Option[Menu] = None
>
>
> override def receiveCommand: Receive = {
>
> case remove: RemoveItem =>
>
> try {
>
>   val newState = state.map(_.remove(remove.itemId)) *// -> 1*
>
>   persist(MenuItemRemoved(remove.categoryId)) {
>
>     event =>
>
>       state = newState *// -> 2*
>
>       sender ! state.get
>
>   }
>
> } catch {
>
>   case businessException: BusinessException => sender() ! 
> Failure(businessException) *// -> 3*
>
> } 
>
> // ... other handlers  
>
> }
>
> }
>
>
> 1 -> I mutate the actor state before persisting the event since that is 
> the aggregate mutating behaviour that raise an exception when an invariant 
> is violated. 
> All the samples I saw mutates the internal actor state in the event 
> handler closure after persisting the event but if the aggregate consistency 
> is violated and it throws a business exception then we would have an 
> inconsistent state of the journal containing an event that should not be 
> there.
>
> 2 -> In order to prevent what I mentioned in the previous point I just 
> assign the actor state to be the new state (aggregate mutation before 
> persist)
>
> 3 -> If the aggregate raises an exception we don´t save the event in the 
> journal, instead we send back a Failure message that maps to a 
> Future.failed in the client who asked this actor and so we can give 
> feedback to any client source about this business exception.
>
>
> A )Is this OK? If not... how is handled?
>
> I´ve seen in the docs that after sending back the *Failure* message, the 
> exception is re-thrown so supervision takes place:
>
> } catch {
>
> case businessException: BusinessException => {  
>
> sender() ! Failure(businessException) 
>
> throw businessException // supervision take places 
>
> } 
>
> } 
>
> Why to do that? The default supervision strategy will Restart the actor, 
> but I don´t need the actor to be restarted, resumed would be OK, however... 
> I just leave the actor as it is since the code above prevented the state to 
> be mutated and the client who asked this actor is notified about the 
> business exception.
>
> B) Should I throw the businessException after sending back the Failure to 
> the sender? Why? Why to restart the actor?
>
> C) Last question, I´ve seen examples of supervision expecting 
> NullPointerException, arithmeticException and so on... those sound bugs to 
> me, unexpected exceptions other than network failures and so shouldn't´t be 
> supervised but fixed. I understand the situation where a Backoff supervisor 
> sounds reasonable to deal with network failures but I don´t see why to 
> supervise exceptions that are caused because of bugs like the ones 
> mentioned before (matching doc examples)
>
>
> Thanks,
> Sebastian
>
>
>
>
> -- 
> >>>>>>>>>> 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 [email protected] <javascript:>.
> To post to this group, send email to [email protected] 
> <javascript:>.
> Visit this group at https://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 [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.

Reply via email to