Подтвердить что ты не робот

Как ограничить сообщения актера конкретными типами?

В Akka существует ли способ ограничить сообщения субъектами конкретным статическим типом, отличным от использования API-интерфейсов "Типированный актер", которые используют Модель программирования стиля RPC?

Могу ли я использовать стиль передачи сообщений с Аккой, не отбрасывая безопасность статического типа на границах актера?

Например, я хотел бы использовать такой код:

sealed abstract class FooMessage
case object Foo extends FooMessage
case object Bar extends FooMessage

class FooActor extends Actor[FooMessage] {
  def receive = {
    case Foo => () // OK

    // Would raise a compiler error:
    // case s: String => error("Can't happen, String is not a subtype of FooMessage") 

  }
}

val fooActor = actorOf[FooActor]
fooActor ! Foo // OK

// Won't compile:
fooActor ! "Hello"

Возможно, нужно было бы расширить базовый признак или создать конструкцию типа Either для сообщения системного уровня (Exit и т.д.).

4b9b3361

Ответ 1

Затем вам нужно будет закодировать тип сообщения в реферере Actor, что резко снизит значение чего-то вроде ActorRegistry.

Кроме того, с мощной механикой, такой как "стать" (что является фундаментальным для модели актера), ввод сообщений менее ценен.

Так как Akka не утечка памяти, когда сообщение не соответствует текущему поведению, не существует такого же риска отправки "неправильных" сообщений "неправильному" актеру.

Кроме того, актеры по своей природе динамичны, поэтому, если вы хотите сделать их статичными, используйте TypedActor (который не является RPC, он так же, как RPC, как обычные участники, void methods are! calls, Future return type is!!! and другие типы возврата основаны на!)

Обычная практика заключается в том, чтобы объявить, какие сообщения может получить Актер в сопутствующем объекте Актера, что значительно облегчает понимание того, что он может получить.

Помогает ли это?

Ответ 2

В Scala stdlib было оправдание для того, чтобы сделать основных участников нетипизированными (что не применимо к Akka, потому что оно не поддерживает вложенные запросы, так как я запомнить). Подъем, в свою очередь, поддерживает типизированных актеров из коробки.

Однако, используя каналы, все же можно создать сильно типизированных актеров с помощью stdlib:

object TypedActor {

  def apply[A](fun: PartialFunction[A, Any]): OutputChannel[A] = {
    val sink = new SyncVar[Channel[A]]
    actor {
      val in = new Channel[A](self)
      sink set in
      loop {
        in react { case any => reply(fun(any)) }
      }
    }
    sink.get
  }

}

sealed abstract class FooMessage
case object Foo extends FooMessage
case object Bar extends FooMessage

object Test {

  val fooActor = TypedActor[FooMessage]{
    case Foo => println("OK")
  }

  fooActor ! Foo 
  fooActor ! "Hello!" // doesn't compile -> Type mismatch; found: String("Hello!"); required: FooMessage;

}

Ответ 3

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

Существует подход для строго типизированных материалов участников (SynapseGrid):

case class Contact[T](...)
case class Signal[T](contact:Contact[T], data:T)

В вашем случае интерфейс состоит из одного входного контакта:

val FooInput = contact[FooMessage]("FooInput")

В рамках платформы SynapseGrid обработка сигналов определяется с помощью Builder:

class FooActorBuilder extends SystemBuilder {
  inputs(FooInput, OtherInput)
  FooInput.foreach(fooMessage => () //OK
  )
  OtherInput.foreach(...)
}

Очевидно, нельзя построить Сигнал с несовместимыми типами. Таким образом, мы проверяем время компиляции. В SynapseGrid есть DSL для работы с сигналами и контактами. Например, чтобы отправить Foo или Bar извне:

val SomeOtherContact = contact[Boolean]("SomeOtherContact")
SomeOtherContact.map(flag => if(flag) Foo else Bar) >> FooInput

Конечно, можно просто отправить сообщение:

val inputMessage = Signal(FooInput, Foo)
actor ! inputMessage

Ответ 4

Звучит как Akka поддержка Akka Typed Channel, чтобы решить эту проблему, но (согласно комментарий уже был удален из Akka в версии 2.3).

В документации для Akka 2.2.3 есть хороший "background background" , в котором обсуждаются трудности с поддержкой типизированных сообщений и ответы.

Там также хороший разговор NEScala от Roland Kuhn, Akka Typed Channels: реализация вычислений типов как макросы ([YouTube]/[Слайды]), в котором обсуждается реализация типизированных каналов.