出乎意料的是,我遇到了Iteratees和Error处理方面的一些问题。
问题;
从InputStream
读取一些字节(来自网络,必须是InputStream),在此InputStream上进行一些分块/填充(用于工作分配),然后进行转换以将其转换为{{1}用于发送给actors(Array [Bytes]转换为CompactByteString)。
流程;
case class DataBlock(blockNum: Int, data: ByteString)
代码;
InputStream.read -- bytes --> Group -- 1000 byte blocks --> Transform -- DataBlock --> Actors
问题;
我目前的Iteratee代码效果很好。但是,我希望能够处理任何一方的失败;
class IterateeTest {
val actor: ActorRef = myDataBlockRxActor(...)
val is = new IntputStream(fromBytes...)
val source = Enumerator.fromStream(is)
val chunker = Traversable.takeUpTo[Array[Byte]](1000)
val transform:Iteratee[Array[Byte], Int] = Iteratee.fold[Array[Byte],Int](0) {
(bNum, bytes) => DataBlock(bNum, CompactByteString(bytes)); bNum + 1
}
val fut = source &> chunker |>> transform
}
case class DataBlock(blockNum: Int, data: CompactByteString)
方法失败时 - 我想知道有多少
已成功处理字节/块并继续读取
从那一点开始流。当在Enumerator中读取时抛出一个错误,read
只返回异常,没有状态,所以我不知道我要去哪个块,除非我将它传递给rxing actor(我不想这样做) )我该怎么做?
我怎么能/更好地使用反应流/ Akka-stream(实验)或scalaz迭代来尝试使用Play的迭代,因为我需要定义错误处理?
答案 0 :(得分:2)
(1)可以使用Enumeratee
实现。
val (counter, getCount) = {
var count = 0
(Enumeratee.map { x => count += 1; x },
() => count)
}
val fut = source &> counter &> chunker |>> transform
然后,您可以getCount
内的recover
使用fut
。
Play Iteratees免费获得(2)。在Iteratee
准备好接收更多数据之前不会再进行读取,如果失败则不会再发生读取。 InputStream
完成时Enumerator
会自动关闭,无论是失败还是正常终止。