Translating business logic into Akka Actors

544 views
Skip to first unread message

Robin

unread,
May 1, 2012, 4:13:36 PM5/1/12
to Akka User List
Hi,

I am new to Akka (Java) and am struggling to figure out how to apply
business rules in the Akka Actor world. I am used to a Java system
being made up of various services, which can be called, and the result
acted upon. I am not sure how to translate these business rules and
workflow into the Akka Actor module.

A simple example could be the purchasing of an item. The workflow for
this would be:
- Check the user is authorised to purchase.
- Look up product info.
- Debit product amount from user's account.

public int purchase(String userId, String productId, int quantity) {

if (authService.canPurchase(userId)) {
Product product = productService.get(productId);
transactionService.debitUsersAccount(userId, product.getPrice());
...
// carry on with purchase
return 0;
}
else {
// User cannot purchase
return -1;
}
}

How would this requirement translate into the asynchronous world of
Actors? I know that I can ask() ActorRefs, but my (limited)
understanding is that I should be using calling tell() asynchronously.

Can someone explain how I could translate the above business logic
into Akka's asynchronous method?

Thanks

Björn Antonsson

unread,
May 2, 2012, 5:12:52 AM5/2/12
to akka...@googlegroups.com
Hi Robin,

Really great that you call this a workflow, since that is exactly how you would think of it in actor terms.

You could model all your services as actors that you send your questions to, and they then send you back replies. But instead of asking (as in blocking on the send and waiting for the reply), you could model your workflow as a finite state machine.


In your example the PurchaseActor is a finite state machine that is created only to perform all the steps in a purchase, and then be discarded when it is no longer needed. In each step it validates the message it got from a service and sends a new message to another service, or to the originator of the purchase request.

Hope this gives you an idea of where to start.

B/

Can someone explain how I could translate the above business logic
into Akka's asynchronous method?

Thanks

--
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To post to this group, send email to akka...@googlegroups.com.
To unsubscribe from this group, send email to akka-user+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/akka-user?hl=en.
-- 
Björn Antonsson
Typesafe - The software stack for applications that scale

andy

unread,
May 2, 2012, 2:12:52 PM5/2/12
to akka...@googlegroups.com
Just wanted to offer my two cents. 

If you're business logic is more than trivial I suggest writing your business objects as you would normally and then put that object in an actor. I find that for handling complex state code there are generally two types of states and transitions -- business and runtime. I think this works perfectly with the actor model. Put your business code in normal scala classes( even better if you use the GOF state pattern and keep those objects immutable ) and then put your runtime logic in the actor that contains the business object. I have used the FSM actor and I still use it for some simple use cases. I ended up doing a big refactor away from the FSM because the code became way too hard to maintain because of the mixing of the two types of state logic in one class.

Here is a simple example for a piece of inventory

Business States: Available, Carted, Sold
Runtime States: Uninitialized ( not containing business object ) , Running ( pass on calls to business object ), Paused ( buffer requests for X amount of time ), OnHold ( Answer requests for current state but do not pass on requests that could mutate state )

trait InventoryState {
  def sell : ( InventoryEvent, InventoryState )
  def refund : ( InventoryEvent, InventoryState )
  def cart : ( InventoryEvent, InventoryState )
  def release :( InventoryEvent, InventoryState )
}

class AvailableState extends InventoryState { / * code */ }
class CartedState extend InventoryState{ /* code */ }
class SoldState extends InventoryState{ /* code */ } 

class InventoryStateKeeper( inventoryId :String ) extends Actor {
  
  var state :InventoryState = _

   def available :Receive = {
     case req :CartInventory =>
       val ( event, newState ) = state.cart // assuming success but you should check
       state = newState
       sender ! event
       context.system.scheduler.scheduleOnce( /* schedule a cart timeout message if carting was successful ) */ )
       context.become( carted )
   }

  def receive :Receive = {
     case StartWith( invState ) if state == null && invState.id == inventoryId =>
       state = invState
       context.become( available )
  }
  // yada yada
}


If you need to have state transitions that occur based on the results from calls to other actors or services, create in intermediate state in your business object and a runtime state called something like Await that will wait for a specific response for some amount of time before reverting to a previous runtime state.

So far this approach has helped us write maintainable code for our complex state transitions.

All the best,
Andy 
To unsubscribe from this group, send email to akka-user+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/akka-user?hl=en.

Roland Kuhn

unread,
May 2, 2012, 2:18:06 PM5/2/12
to akka...@googlegroups.com
Hi Andy,

On May 2, 2012, at 20:12 , andy wrote:

Just wanted to offer my two cents. 

If you're business logic is more than trivial I suggest writing your business objects as you would normally and then put that object in an actor. I find that for handling complex state code there are generally two types of states and transitions -- business and runtime. I think this works perfectly with the actor model. Put your business code in normal scala classes( even better if you use the GOF state pattern and keep those objects immutable ) and then put your runtime logic in the actor that contains the business object. I have used the FSM actor and I still use it for some simple use cases. I ended up doing a big refactor away from the FSM because the code became way too hard to maintain because of the mixing of the two types of state logic in one class.

I’d be very much interested in seeing an example of where FSM fails you, if you can share (off-list, if you prefer). I’m always looking for feedback and possible enhancements.

Regards,

Roland Kuhn
Typesafe – The software stack for applications that scale.
twitter: @rolandkuhn


Robin

unread,
May 3, 2012, 5:10:30 AM5/3/12
to akka...@googlegroups.com
Thanks to both of you for your suggestions. I will give the FSM idea a try.
Reply all
Reply to author
Forward
0 new messages