Asynchronous 如何在使用Plays Iteratee处理数据流时等待免费的Akka actor

Asynchronous 如何在使用Plays Iteratee处理数据流时等待免费的Akka actor,asynchronous,playframework,akka,actor,iterate,Asynchronous,Playframework,Akka,Actor,Iterate,我有一个无限流,消息表示为PlaysEnumerator,我对其应用了Iteratee。然后,每个消息由Akka参与者处理(参与者数量限制为10) 现在,我希望Iteratee中的代码在所有10个参与者都忙的情况下异步等待空闲参与者,并且不向他们发送另一条消息,这会导致异常Ask在…上超时 我如何实现这样的功能?有没有更好的方法来处理10个参与者的无限流,而不必等待呢? 我刚才提到的代码示例可能如下所示: val workers = context.actorOf(Props[MyWorker]

我有一个无限流,消息表示为Plays
Enumerator
,我对其应用了
Iteratee
。然后,每个消息由Akka参与者处理(参与者数量限制为10)

现在,我希望
Iteratee
中的代码在所有10个参与者都忙的情况下异步等待空闲参与者,并且不向他们发送另一条消息,这会导致异常
Ask在…
上超时

我如何实现这样的功能?有没有更好的方法来处理10个参与者的无限流,而不必等待
呢?

我刚才提到的代码示例可能如下所示:

val workers = context.actorOf(Props[MyWorker].withRouter(RoundRobinRouter(10)))
val it = Iteratee.foreach[Msg] { msg => 
  workers ? msg
}

msgEnumerator.apply(it)

Iteratee.foldM
与这里的actor-ask模式结合使用似乎是正确的方法。假设您不希望参与者建立大邮箱(如果您不关心大邮箱,只需使用
tell
Iteratee.foreach
而不是
ask
),这将需要一些专门的路由逻辑。由于定制akka路由器的api不支持异步,因此您需要一个定制的参与者来处理一次只向参与者池中的每个参与者分发一项工作的逻辑

我想象它的工作原理如下:

class WorkDistributor extends Actor {
  final val NUM_WORKERS = 10
  val workers = context.actorOf(Props[MyWorker].withRouter(RoundRobinRouter(NUM_WORKERS))) 

  var numActiveWorkers = 0
  var queuedWork: Option[Work] = None

  def receive = {
    case IterateeWork(work) if numActiveWorkers < NUM_WORKERS => workers ! work; numActiveWorkers += 1; sender ! SendMeMoreWork
    case IterateeWork(work) => queuedWork = Some(work)
    case ActorFinishedWork if queuedWork.isDefined => queuedWork.foreach(workers ! _); queuedWork = None
    case ActorFinishedWork => numActiveWorkers -= 1; sender ! SendMeMoreWork
  }
}
Iteratee.foldM[Work, SendMeMoreWork.type](SendMeMoreWork) {
  case (_, work) => workDistributor ? IterateeWork(work)
}