Акка и рисунок торта

Я смущен, как обеспечить, чтобы у моих Актеров были соответствующие зависимости, используя шаблон торта. Я все еще с этим справляюсь, и я нигде не могу найти примеров. Я в основном просто ищу учебник/ресурс для подражания.

Привет, Крис.

Ответ 1

Актеры как зависимость:

trait DBComponent {
   def db: ActorRef // no compile time guarantees

   type K
   type V

   object DBActor {
      case class Put(key: K, value: V)
      case class Get(key: K)
   }

   class DBActor {
      import DBActor._
      val db = scala.collection.mutable.Map.empty[K, V]
      def receive = {
         case Put(k, v) => db.put(k, v)
         case Get(k) => sender ! db.get(k)
      }
   }
}

trait ServiceComponent {
   this: DBComponent =>

   import DBActor._

   // you could be talking to deadLetters for all you know
   def put(k: K, v: V): Unit = db ! Put(k, v)
   def get(k: K): Option[V] = {
      implicit val timeout = Timeout(5 seconds)
      val future = ask(actor, Get(k)).mapTo[Option[V]]
      Await.result(future, timeout.duration)
   }
}

Актеры, имеющие зависимости (где нет ничего особенного):

trait DBComponent {
   def db: DB

   type K
   type V

   trait DB {
      def put(key: K, value: V): Unit
      def get(key: K): Option[V]
   }
}

trait ServiceComponent {
   this: DBComponent =>

   object ServiceActor {
      case class Put(key: K, value: V)
      case class Get(key: K)
   }

   class ServiceActor {
      import ServiceActor._
      def receive = {
         case Put(k, v) => db.put(k, v) // db is in scope
         case Get(k) => sender ! db.get(k)
      }
   }
}

Ответ 2

Еще одна дополнительная информация, о которой указывает Оуэн, заключается в том, что создание участников с использованием actorOf(Props[MyClass]) не будет работать для внутренних классов. Т.е.: не будет выполнено следующее:

trait MyComponent {
  class MyActor {
    def receive = ...
  }
}

new MyComponent {
  val myActorRef = system.actorOf( Props[MyActor] )
}

Согласно документации на http://doc.akka.io/docs/akka/snapshot/scala/actors.html,

если они не объявлены в объекте верхнего уровня, тогда экземпляров эта ссылка должна быть передана в качестве первого аргумента

Однако это, похоже, не поддерживается сигнатурами метода ретрансляции scaladoc. Единственным способом, который я нашел, было использование конструктора Props (actor: Actor), создающего экземпляр mysql и передачу его в реквизит.

val myActorRef = system.actorOf( Props( new MyActor(arg1, arg2) ) )

Было бы интересно узнать, есть ли лучший способ.