蛋糕模式w/akka:为多个层提供隐式actor系统

maa*_*asg 7 scala akka cake-pattern

我正在烘焙我的第一个蛋糕图案,所以请耐心等待.

我拿了我的工作单片应用程序,并将其切割成功能层.剪切看起来很干净,但导致两个依赖于隐式ActorSystem的层.

我尝试像这样解决这种依赖:

trait LayerA {
  this: ActorSystemProvider =>
  private implicit val implicitActorSystem = actorSystem
  import implicitActorSystem.dispatcher // implicit execution ctx
  ...
}
Run Code Online (Sandbox Code Playgroud)

......和LayerX类似

我的汇编类看起来像:

class Assembly extends LayerA with LayerB with LayerX with ActorSystemProvider
Run Code Online (Sandbox Code Playgroud)

其中ActorSystemProvider只是实例化actor系统.

这不起作用,因为ActorSystem当依赖关系被解析并且val被实例化时不存在,从而导致NPE.这看起来也很丑陋,我确信必须有一个更好/更简单的方法来处理它.

在使用蛋糕模式时,我应该如何处理图层之间的共享隐式依赖关系,就像ActorSystem在这种情况下一样?

谢谢

4le*_*x1v 11

自我类型不是构建结构化体系结构的必要条件,实际上我只在特征是图层组件的情况下使用自我类型.所以当我需要将一些隐含的东西放入范围时(例如Spray Client的ActorRefFactory)我只是混合了一个特征:

trait ActorSystemProvider {
  implicit def actorSystem: ActorSystem
}
Run Code Online (Sandbox Code Playgroud)

在最低层(所谓的"世界末日"),我有以下代码结构:

trait ServiceStack
  extends SomeModule
     with SomeModule2
     with SomeModule3 
     with ActorSystemProvider 

object ServiceLauncher extends App with ServiceStack {
  val actorSystem = ActorSystem("ServiceName")
}
Run Code Online (Sandbox Code Playgroud)

这是一个过于简单的例子(如果你想要一个基于Cake Pattern的真实系统构建的一个很好的例子,那么你一定要看看Precog系统,不同模块/层连接的例子),但不是你可以混合隐式ActorSystem什么时候需要它.


Ven*_*ama 5

如果你可以懒惰而不是急切地实例化val,你可以使implicitActorSystem成为一个懒惰的val而不是val.所以它只在第一次访问时执行.我认为这应该解决NPE的问题.(@ViktorKlang FYI发布的另一个鲜为人知的有趣事实:如果lazy val的初始化抛出异常,它将尝试在下次访问时重新初始化val.)

另一种方法是使每个需要执行上下文的方法都接受一个隐式的executionContext,如:

trait LayerA {
  def getUser(id: Int)(implicit ec: ExecutionContext) = {
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)