2012-12-19 34 views
22

我正在使用Play!编写一个用Scala编写的Web应用程序!框架和Akka。代码基本上是这样组织的:播放控制器向Akka演员发送消息。演员反过来与一个持久层交谈,该层抽象数据库访问。在应用这些部件的使用的一个典型的例子:在CRUD Web应用程序中使用Akka actors

class OrderController(orderActor: ActorRef) extends Controller { 
    def showOrders(customerId: Long) = { 
    implicit request => Async { 
     val futureOrders = orderActor ? FindOrdersByCustomerId(id) 

     // Handle the result, showing the orders list to the user or showing an error message. 
    } 
    } 
} 

object OrderActor extends Actor { 
    def receive = { 
    case FindOrdersByCustomerId(id) => 
     sender ! OrderRepository.findByCustomerId(id) 
    case InsertOrder(order) => 
     sender ! OrderRepository.insert(order) 
     //Trigger some notification, like sending an email. Maybe calling another actor. 
    } 
} 

object OrderRepository { 
    def findByCustomerId(id: Long): Try[List[Order]] = ??? 
    def insert(order: Order): Try[Long] = ??? 
} 

正如你所看到的,这是基本的CRUD模式,就像你会在其他语言和框架看。查询会传递到下面的图层,并且当应用程序从数据库中获取结果时,该结果会返回到用户界面。唯一相关的区别是使用actor和异步调用。

现在,我对演员的概念很陌生,所以我还没有完全理解它。但是,从我读过的,这不是演员应该如何使用。但是,请注意,在某些情况下(例如,在插入订单时发送电子邮件),我们确实需要真正的异步消息传递。

所以,我的问题是:以这种方式使用演员是一个好主意吗?利用Futures和Akka的其他并发功能,在Scala中编写CRUD应用程序有哪些选择?

+1

看看键入的频道 - 他们出来后,你张贴这个。他们有一些有趣的消息流特性,所以你可以做一些事情,比如通过几个角色传递消息:OrderRepository.insert(order) - ! - > sender - ? - > sendEmail - ? - > displayResult。 –

回答

5

尽管基于角色的并发与开箱即用的事务操作不相符,但如果与持久层良好地配合,则不会阻止您使用actor。如果你可以保证插入(写)是原子,那么你可以安全地让一群演员为你做。通常数据库有一个线程安全读取所以找到也应该按预期工作。除此之外,如果插入不是线程安全的,则可以将一个WriteActor专门用于写入操作,并且顺序处理消息将确保您的原子性。

2

有一点需要注意的是,一个角色一次处理一条消息,在这种情况下这将是相当有限的。您可以使用routers来使用一组演员。

您的示例根据数据库驱动程序定义存储库的阻止API,这可能是唯一可以执行的操作。如果可能的话,你也应该在那里寻找一个异步API,例如返回期货。在演员中,您将接着发送未来的结果pipe

+0

是的,控制器依赖于一个'ActorRef',它可以是一个简单的角色以及一个路由器。 –