我有无限的流,其中的消息表示为我应用{{1}}的播放select countrylanguage.language, country.code, sum(country.population*countrylanguage.percentage/100)
from countrylanguage
join country on countrylanguage.countrycode = country.code
group by countrylanguage.language, country.code
order by sum(country.population*countrylanguage.percentage) desc ;
。然后每个消息由Akka actor处理(actor的数量限制为10)。
现在我希望Enumerator
中的代码异步等待自由演员如果所有10个演员都忙,而不是向他们发送另一个导致异常Iteratee
的消息。
如何实现此类功能?有没有更好的方法来处理10个没有Iteratee
的演员的无限流?
我所谈论的代码示例可能如下所示:
Ask timed out on ...
答案 0 :(得分:0)
使用Iteratee.foldM
与你在这里的演员问问模式似乎是正确的方法。假设您不希望您的演员建立大型邮箱(如果您不关心大邮箱,请使用tell
和Iteratee.foreach
代替ask
)将需要一些专门的路由逻辑。由于用于制作自定义akka路由器的api不支持异步,因此您需要一个自定义actor来处理一次将一件作品分配给actor池中每个actor的逻辑。
我想它的工作方式如下:
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
}
}
迭代者发送IterateeWork
消息,并且演员池中的actor发送ActorFinishedWork
消息。
看看我写的这个东西,应该重写这个以使用become
来改变演员池满时的行为(而不是每个案例的if
过滤器,但我把它留作为读者锻炼。
然后您的Iteratee
看起来像
Iteratee.foldM[Work, SendMeMoreWork.type](SendMeMoreWork) {
case (_, work) => workDistributor ? IterateeWork(work)
}