38

Akkaでは、RPCスタイルのプログラミングモデルを使用する「型付きアクター」APIを使用する以外に、アクターへのメッセージを特定の静的タイプに制限する方法はありますか?

アクターの境界で静的型の安全性を捨てることなく、Akkaでメッセージパッシングスタイルを使用できますか?

たとえば、次のようなコードを使用したいと思います。

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など)を許可するような構造を持たなければならないでしょう。

4

4 に答える 4

27

次に、メッセージタイプをActor refにエンコードする必要があります。これにより、ActorRegistryのような値が大幅に減少します。

また、「become」(アクターモデルの基本)のような強力なメカニズムでは、メッセージを入力する価値は低くなります。

メッセージが現在の動作と一致しない場合、Akkaはメモリをリークしないため、「間違った」メッセージを「間違った」アクターに送信するリスクは同じではありません。

また、アクターは本質的に動的であるため、静的にしたい場合は、TypedActor(RPCではなく、通常のアクターと同じRPC、voidメソッドは!呼び出し、Future return typeは!!!、その他のreturn type)を使用します。に基づいています!!)

一般的な方法は、アクターが受信できるメッセージをアクターのコンパニオンオブジェクトで宣言することです。これにより、アクターが受信できるメッセージを非常に簡単に知ることができます。

それは役に立ちますか?

于 2011-04-05T11:24:51.913 に答える
23

Scala stdlibには、基本的なアクターを型なしにするための言い訳がありました(これは、私が覚えているように、ネストされた受信をサポートしていないため、Akkaには適用されません)。次に、Liftは、入力されたアクターをすぐにサポートします。

ただし、チャネルを使用すると、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;

}
于 2011-04-05T08:19:25.780 に答える
2

実際には、アクターを入力として単一のタイプのみを持つように制限することはあまり役に立ちません。私の心にもっと役立つのは、厳密に型指定された方法で可能な入力をリストすることです。

アクターの厳密に型指定された入力に対するアプローチがあります(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(...)
}

明らかに、互換性のないタイプでSignalを構築することはできません。したがって、コンパイル時のチェックがあります。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
于 2013-08-09T16:25:54.530 に答える
1

AkkaのAkkaのTypedChannelサポートがこれに対処していたようですが、(コメントによると、 バージョン2.3でAkkaからすでに削除されています)。

Akka 2.2.3のドキュメントには、タイプされたメッセージの送信と応答のサポートの難しさを説明 する優れた「設計の背景」セクションがあります。

Roland KuhnによるNEScalaの優れた講演、Akka Typed Channels:Implementing Type Calculations as Macros[YouTube] / [Slides])もあり、型付きチャネルの実装について説明しています。

于 2014-06-20T17:44:12.940 に答える