Akka Stream和HTTP Scala:如何从路由向Actor发送消息

时间:2015-09-12 20:35:36

标签: scala actor akka-stream akka-http

我正在玩akka-stream-and-http-experimental 1.0。到目前为止,我有一个可以接受和响应HTTP请求的用户服务。我也将有一个可以管理约会的预约服务。为了进行约会,必须是现有用户。如果用户存在,预约服务将检查用户服务。现在这显然可以通过HTTP完成,但我宁愿让约会服务向用户服务发送消息。作为新手,我不清楚如何使用actor(如akka-http摘要那样)来发送和接收消息。在doc中提到了ActorRefActorPublisher,但没有前者和后者的例子看起来像我的需要一样过分。 我的代码如下所示,位于Github

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来完成。这只会将消息发送到流中。我想做的是让路由处理程序类接收响应。这样,当我创建约会服务时,它的actor可以调用用户服务actor并以与我的示例中的用户路由处理程序相同的方式接收响应。 伪代码:

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
  }
}

1 个答案:

答案 0 :(得分:1)

我最终使用了$filter('pick')(data, function(elem){ return elem>2; }); 。简单。