优雅的Iteratee - >播放器中的枚举器“转发”

时间:2014-05-05 23:07:33

标签: scala asynchronous playframework-2.0 akka iterate

我想在Play中编写应用程序!框架2.2.x作为异步方法和play.api.libs.iterattee包的练习。我想要做的是在其正文中获取一个带有大文件上传的POST请求,并按块发送它,作为下载到单独的请求。

" Play for Scala" book和this example引导我接收请求中的文件,我可以在自定义Iteratee中定义的任何BodyParser中累积或迭代。关于serving a chunked response,我需要为响应提供Enumerator - 例如Ok.chunked(enumerator),当枚举器提供新的块时,它将提供给客户端。

既然我想把它们放在一起,我似乎无法找到一种优雅且反应灵敏的方式来将新数据块从上传客户端异步传播到下载。对于"转发"似乎并不是一个好方法。由Iteratee(在这种情况下在BodyParser中)收到的数据到新的Enumerator(在这种情况下是向响应提供输出的数据)。

我想出了两种方法,但对我来说,它们似乎都不够好:

  • 使用play.api.libs.iteratee.Concurrent.boradcast生成ChannelEnumerator,并在我的BodyParser中将每个收到的块推送到ChannelChannels不具备Enumerator所拥有的属性 - 枚举器在应用Iteratee之前不会产生新值,直到Channel消耗旧值。 如果我这样做的话,如果上传者的互联网连接速度比下载器快,那么我会有一个"肿胀" Actor占用越来越多的内存,而不是一次处理一个块。

  • 创建一个代理akka Actor并将上传的文件chunk by chunk发送给它,只有在下一个文件被下载程序占用后才发送下一个文件。但在这种情况下,发送到下载程序的每个块的确认必须通过Iteratee代理,以便上传者Enumerator将另一个块发送到代理。这对我来说似乎是不必要的开销。

我想我的问题有两个:

  1. 是否有一种简单的方法来构建"转发" Iteratee生成{{1}}收到的值?
  2. 在我的用例中,使用Play和Scala的异步工具包实现我想到的场景的正确方法是什么?

1 个答案:

答案 0 :(得分:2)

您可以使用Concurrent.joined

val (iteratee, enumerator) = Concurrent.joined[Array[Byte]]