akka-stream-and-http-experimental
1.0で遊んでいます。これまでのところ、HTTP 要求を受け入れて応答できるユーザー サービスができました。また、アポイントメントを管理できるアポイントメントサービスも予定しています。予約するには、既存のユーザーである必要があります。予約サービスは、ユーザーが存在するかどうかをユーザー サービスに確認します。これは明らかに HTTP 経由で実行できますが、予約サービスがユーザー サービスにメッセージを送信するようにしたいと考えています。akka-http
これに慣れていないので、メッセージを送受信するためにアクターを (抽象化として) 使用する方法が明確ではありません。ドキュメントにはActorRef
andについての言及がありますが、前者と後者の例はありません。私のコードは次のようになり、Githubにあります。ActorPublisher
trait UserReadResource extends ActorPlumbing {
val userService: UserService
val readRoute = {
// route stuff
}
}
trait ActorPlumbing {
implicit val system: ActorSystem
implicit def executor: ExecutionContextExecutor
implicit val materializer: Materializer
def config: Config
val logger: LoggingAdapter
}
trait UserService { // Implemented by Slick and MongoDB in the backend
def findByFirstName(firstName: String): Future[immutable.Seq[User]]
}
object UserApp extends App with UserReadResource with UserWriteResource with ActorPlumbing {
override implicit val system = ActorSystem()
override implicit def executor = system.dispatcher
override implicit val materializer = ActorMaterializer()
override def config = ConfigFactory.load()
override val logger = Logging(system, getClass)
private val collection = newCollection("users")
val userRepository = new MongoDBUserRepository(collection)
val userService: UserService = new MongoDBUserRepositoryAdapter(userRepository) with UserBusinessDelegate {
// implicitly finds the executor in scope. Ain't that cute?
override implicit def executor = implicitly
}
Http().bindAndHandle(readRoute ~ writeRoute, config.getString("http.interface"), config.getInt("http.port"))
}
編集:メッセージを送信する方法を見つけました。これは、を使用して実行できますSource.actorRef
。これは、メッセージをストリームに送信するだけです。私がやりたいのは、ルート ハンドラー クラスが応答を受け取ることです。そうすれば、予約サービスを作成するときに、そのアクターはユーザー サービス アクターを呼び出して、例のユーザー ルート ハンドラーと同じ方法で応答を受け取ることができます。擬似コード:
val src = Source.single(name) \\ How to send this to an actor and get the response
編集2:@yardenaの回答に基づいて、次のことを思いつきましたが、最後の行はコンパイルされません。私のアクター パブリッシャーは、でラップされ、 としてルート ハンドラーに配信されるとFuture
推測している を返します。Promise
Future
get {
parameters("firstName".?, "lastName".?).as(FindByNameRequest) { name =>
type FindResponse = Future[FindByNameResponse]
val src: Source[FindResponse, Unit] = Source.actorPublisher[FindResponse](businessDelegateProps).mapMaterializedValue {
_ ! name
}
val emptyResponse = Future.apply(FindByNameResponse(OK, Seq.empty))
val sink = Sink.fold(emptyResponse)((_, response: FindResponse) => response)
complete(src.runWith(sink)) // doesn't compile
}
}