在实践中用Scala演员编写应用程序II

oxb*_*kes 4 scala actor

因为我的第一个问题太长了,我要问这是一个单独的问题.这是关于基于actor的应用程序的体系结构的另一个问题.

通过应用程序跟踪消息路径

我们来看一段Java代码:

public void deleteTrades(User user, Date date) {
    PermissionSet ps = permissionService.findPermissions(user)
    if (ps.hasPermission("delete")) {
        Set<Trade> ts = peristence.findTrades(date);
        reportService.sendCancelReports(ts);
        positionService.updateWithDeletedTrades(ts);
    }
}
Run Code Online (Sandbox Code Playgroud)

在这段代码中,我有4个独立的组件,并且程序所需的它们之间的交互deleteTrades是明确定义的.它完全包含在方法中deleteTrades.

使用Actors对其进行建模并用4个独立的actor替换我的4个组件,如何跟踪(在我看来)过程涉及的内容?特别是如果我避免使用!?运算符,那么我很可能会ConditionalDelete向我PermissionActor发送一条消息,它将GetTradesAndDelete向我发送消息,PersistenceActor然后发送更多消息等等.处理删除的代码将被散布跨我的应用程序.

这也意味着几乎每个actor都需要处理其他每个actor(为了转发消息).

正如我之前的问题,人们如何处理这个问题?有没有一个很好的建模工具,可以让你跟踪所有这些?人们使用!?我是否将太多组件转换为Actors?

Dan*_*ral 6

你肯定使用5个组件.有演员处理特定任务,还有一个协调者.

当然,你必须具备的问题是如何异步地链接这个问题.嗯,它实际上有点简单,但它可以掩盖代码.基本上,您向每个组件发送您想要的回复.

react {
  case DeleteTrades(user,dates) => 
    PermissionService ! FindPermissions(user, DeleteTradesPermissions(dates) _)
  case DeleteTradesPermissions(dates)(ps) =>
    if (ps hasPermission "delete")
      Persistence ! FindTrades(date, DeleteTradesTradeSet _)
  case DeleteTradesTradeSet(ts) =>
    ReportService ! SendCancelReports(ts)
    PositionService ! UpdateWithDeletedTrades(ts)
}
Run Code Online (Sandbox Code Playgroud)

在这里,我们使用currying在第一个返回的答案中传递"日期".如果有很多与交互相关的参数,那么最好将所有正在进行的事务的信息保存在本地HashSet中,并且只传递一个令牌,用于在收到答案时找到该信息.

请注意,此单个actor可以处理多个并发操作.在这种特殊情况下,只需删除事务,但您可以添加任意数量的不同操作来处理.当一个操作所需的数据准备就绪时,该操作将继续.

编辑

这是一个如何定义这些类的工作示例:

class Date
class User
class PermissionSet

abstract class Message
case class DeleteTradesPermission(date: Date)(ps: PermissionSet) extends Message
case class FindPermissions(u: User, r: (PermissionSet) => Message) extends Message

FindPermissions(new User, DeleteTradesPermission(new Date) _)
Run Code Online (Sandbox Code Playgroud)

关于currying和功能的一些解释.课程DeleteTradesPermission是curry,你可以传递Date它,并有一些其他功能完成它与一个PermissionSet.这将是答案消息的模式.

现在,该类FindPermissions接收一个函数作为第二个参数.接收此消息的actor将返回值传递给此函数,并将接收Message要作为答案发送的a .在这个例子中,消息将包含Date调用actor发送的消息,以及PermissionSet应答者提供的消息.

如果没有预期的答案,例如DeleteTrades,SendCancelReports并且UpdateWithDeletedTrades出于本示例的目的,那么您不需要传递返回消息的函数.

由于我们期望一个函数返回一个Message作为那些需要答案的消息的参数,我们可以定义这样的特征:

trait MessageResponse1[-T1] extends Function1[T1, Message]
trait MessageResponse2[-T1, -T2] extends Function2[T1, T2, Message]
...
Run Code Online (Sandbox Code Playgroud)