Akka Streams:验证正在流式传输的元素

时间:2017-06-11 10:59:56

标签: scala akka akka-stream

我是Akka Streams的新手,我想知道如何实现某种中流验证。例如:

FileIO
  .fromPath(file)
  .via(Framing.delimiter(...)
  .map(_.utf8String)
  .map(_.split("\t", -1))
  .validate(arr => arr.length == 10) // or similar
  ...

我认为这种情况非常普遍,必须有一个预定义的功能来动态验证流。但是,我无法找到任何相关信息。我在错误的轨道上,验证是不应该在Akka Streams 这样的事情吗?

在我的特定场景中,我逐行处理文件。如果只有一行是无效的,则继续没有意义,应该中止处理。

3 个答案:

答案 0 :(得分:3)

我可能会创建一个表示约束的类型,然后你可以在创建该类型的实例时执行断言,并知道下游已经应用了哪些约束。

示例:

{{1}}

答案 1 :(得分:2)

您可以使用.takeWhile。这将处理无效项目之前的所有元素,而不处理其后的任何项目。

FileIO
  .fromPath(file)
  .via(Framing.delimiter(...)
  .map(_.utf8String)
  .map(_.split("\t", -1))
  .takeWhile(arr => arr.length == 10)
  ...

答案 2 :(得分:1)

我同意@Stephen takeWhile是你需要的。如果希望将失败的元素传递到下游,可以将inclusive标志设置为true来使用它。

此外,如果您想使您的信息流最具表现力,您可以让验证流产生Either[ValidationError, String]

下面的例子有点笨重,我更喜欢使用graphDSL和partition,但希望你能得到这个想法。

  val errorSink: Sink[TooManyElements, _] = ???
  val sink: Sink[Array[String], _] = ???

  FileIO
    .fromPath(file)
    .via(Framing.delimiter(...))
    .map(_.utf8String.split("\t", -1))
    .map{
      case arr if arr.length > 10 ⇒ Left(TooManyElements(arr.length))
      case arr                    ⇒ Right(arr)
    }
    .takeWhile(_.isRight, inclusive = true)
    .alsoTo(Flow[Either[TooManyElements, Array[String]]].filter(_.isLeft).to(errorSink)
    .filter(_.isRight)
    .to(sink)