Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 在单个超时时处理未知数量的参与者结果_Scala_Akka_Actor - Fatal编程技术网

Scala 在单个超时时处理未知数量的参与者结果

Scala 在单个超时时处理未知数量的参与者结果,scala,akka,actor,Scala,Akka,Actor,我希望扩展以下代码以处理未知数量的actor ask请求 implicit val timeout = Timeout(100 millis) val sendRequestActor = context.actorOf(Props(new SendRequest(request)), "Send_Request_".concat(getActorNumber)) val sendRequestActor2 = context.actorOf(Props(new SendRequest(requ

我希望扩展以下代码以处理未知数量的actor ask请求

implicit val timeout = Timeout(100 millis)
val sendRequestActor = context.actorOf(Props(new SendRequest(request)), "Send_Request_".concat(getActorNumber))
val sendRequestActor2 = context.actorOf(Props(new SendRequest(request)), "Send_Request_".concat(getActorNumber))
val a1 = ask(sendRequestActor, Request).fallbackTo(Future.successful(RequestTimeout))
val a2 = ask(sendRequestActor2, Request).fallbackTo(Future.successful(RequestTimeout))
val result = for {
  r1 <- a1
  r2 <- a2
} yield(r1, r2)

val r = Await.result(result, 100 millis)
r match {
  case (b: SuccessResponse, b2: SuccessResponse) => {
    //Process Results
  }
  case (b: SuccessResponse, b2: RequestTimeout) => {
    //Process Results
  }
  case (b: RequestTimeout, b2: SuccessResponse) => {
    //Process Results
  }
  case (b: RequestTimeout, b2: RequestTimeout) => {
    //Process Results
  }
  case _ => {}
}
已更新的发送类:

case object GetResponses

def main(args: Array[String]) {

val route = {
  get {
    complete {
      //stuff
      val req_list = List(req1,req2,req3)
      val createRequestActor = system.actorOf(Props(new SendAll(req_list)), "Get_Response_Actor_" + getActorNumber)
      val request_future = ask(createRequestActor, GetResponses).mapTo[List[Any]]
      Thread.sleep(1000)
      println(request_future)
      //more stuff
    }
  }
}


Http().bindAndHandle(route, "localhost", 8080)
}
class SendAll(requests: List[Request]) extends Actor {
  import context.{become,dispatcher}
  var numProcessed = 0
  var results: List[Any] = List()
  requests.foreach(self ! _)

  implicit val timeout = Timeout(100 millis)
  def receive = {

    case r: RequestMsg =>
      val sendRequestActor = context.actorOf(Props(new SendRequest(r)), "Send_Request_".concat(getActorNumber))
      (sendRequestActor ? Request).pipeTo(self)

    case s: SuccessResponse =>
      println("Got Success")
      results = results :+ s
      println(results.size + " == " + requests.size)
      if(results.size == requests.size) {
        println("Before done")
        become(done)
      }

    case akka.actor.Status.Failure(f) =>
      println("Got Failed")
      results = results :+ RequestTimeout
      if(results.size == requests.size) {
        become(done)
      }

    case m => 
      println("Got Other")

  }

  def done: Receive = {
    case GetResponses =>
      println("Done")
      sender ! results
    case _ => {
      println("Done as well")
    }
  }
}
输出

Got Success
1 == 3
Got Success
2 == 3
Got Success
3 == 3
Before done
Future(<not completed>)

我会将请求列表传递给参与者,然后将子参与者的响应传递给self,而不是使用wait.result。例如:

class Handler(requests: List[RequestMsg]) extends Actor {
  import context.{become, dispatcher}
  var numProcessed = 0
  var results: List[Any] = List()
  requests.foreach(self ! _)

  implicit val timeout = Timeout(100.millis)

  def receive = {
    case r: RequestMsg =>
      val sendRequestActor = context.actorOf(Props(new SendRequest(r)), "Send_Request".concat(getActorNumber))
      (sendRequestActor ? Request).pipeTo(self)

    case s: SuccessResponse =>
      println(s"response: $s")
      results = results :+ s
      if (results.size == requests.size)
        become(done)

    case akka.actor.Status.Failure(f) =>
      println("a request failed or timed out")
      results = results :+ RequestTimeout
      if (results.size == requests.size)
        become(done)

    case m =>
      println(s"Unhandled message received while processing requests: $m")
      sender ! NotDone
  }

  def done: Receive = {
    case GetResponses =>
      println("sending responses")
      sender ! results
  }
}
您将为每个请求列表实例化一个参与者:

val requests1 = List(RequestMsg("one"), RequestMsg("two"), RequestMsg("three"))
val handler1 = system.actorOf(Props(new Handler(requests1)))

在本例中,根据参与者应具有明确、有限责任范围的原则,参与者只需协调请求和响应;它不会对收集的响应执行任何处理。其想法是,另一个参与者将向该参与者发送GetResponses消息,以获取响应并对其进行处理,或者该参与者将主动将结果发送给处理参与者。

最简单的解决方案是将所有参与者引用放入列表,将其映射到列表[未来],并用于获取未来[列表]


一个更好的解决方案是避免很多参与者的请求,准备一些响应Collector actor,它将发送您的所有消息。我建议您查看广播池并为自己安排一条消息,以停止等待并返回结果。

这看起来会满足我的要求。但是我对done函数有一个问题,它似乎根本没有被调用,也不一定是睡眠计时器。我以前让另一个参与者调用这个函数,并且将在这里进行处理。我更新了OP以包括我的呼叫类和我更新的发送类。有什么线索可以解释为什么我从来没有在我的“完成”类中看到任何打印内容以及我的未来没有完成?@Eumcoz:关于您的更新,有几点需要注意:1您的RequestHandler看起来很奇怪,因为它扩展了Actor并调用system.actorOf system.actorOf应该在主程序中调用,而不是从Actor内部调用。2您可能没有分配足够的时间来完成请求-响应处理。增加Thread.sleep或在将来使用onComplete回调。抱歉,我的错误,出于某种原因,我认为这是从其他地方调用的,在我的实际程序中,RequestHandler是我的主程序,是akka http处理程序。正在从http请求的指令调用SendAll。无论我睡眠多长时间,它都会失败,我的SendAll调用超时将生效:Failureakka.pattern.AskTimeoutException:Ask在[Actor]上超时[akka://HTTP_Actor_System/user/Get_Response_Actor_1-720534280]]在[10000毫秒]之后。发件人[null]已发送GetResponses$类型的邮件。在之前的测试中,我的响应处理大约需要5毫秒。
val route = {
  get {
    val listActorRefs = List(actorRef1, actorRef2, ...)
    val futureListResponses = Future.sequence(listActorRefs.map(_ ? Request))
    onComplete(futureListResponses) {
      case Success(listResponse) => ...
        complete(...)
      case Failure(exception) => ...
    }
  }
}