Akka Stream 的 Keep right/left/both 如何导致不同的输出? [英] How does Akka Stream's Keep right/left/both result in a different output?

查看:21
本文介绍了Akka Stream 的 Keep right/left/both 如何导致不同的输出?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试了解 Keep 在 Akka 流中的工作方式.阅读 保持在 akka 流中意味着什么 中的答案,我明白它有助于控制我们从具体化器的左侧/右侧/两侧获得结果.但是,我仍然无法构建一个示例,因为我可以更改左/右的值并获得不同的结果.

I am trying to wrap my head around how Keep works in Akka streams. Reading answers in What does Keep in akka stream mean, I understand that it helps to control we get the result from the left/right/both sides of the materializer. However, I still can't build an example were I can change the value of left/right and get different results.

例如

implicit val system: ActorSystem = ActorSystem("Playground")
implicit val materializer: ActorMaterializer = ActorMaterializer()

val sentenceSource = Source(List(
  "Materialized values are confusing me",
  "I love streams",
  "Left foo right bar"
))

val wordCounter = Flow[String].fold[Int](0)((currentWords, newSentence) => currentWords + newSentence.split(" ").length)
val result = sentenceSource.viaMat(wordCounter)(Keep.left).toMat(Sink.head)(Keep.right).run()

val res = Await.result(result, 2 second)
println(res)

在这个例子中,如果我将值从保持左移到保持右移,我仍然得到相同的结果.有人可以向我提供一个基本示例,其中将 keep 更改为左/右/两个值会导致不同的结果吗?

In this example if I change values from keep left to keep right, I still get the same result. Can someone provide me with a basic example where changing keep to left/right/both values results in a different outcome?

推荐答案

在你的例子中,因为:

sentenceSource: akka.stream.scaladsl.Source[String,akka.NotUsed] = ???
wordCounter: akka.stream.scaladsl.Flow[String,Int,akka.NotUsed] = ???

两者都有 NotUsed 作为它们的具体化(表明它们没有有用的具体化),

both have NotUsed as their materialization (indicating that they don't have a useful materialization),

sentenceSource.viaMat(wordCounter)(Keep.right)
sentenceSource.viaMat(wordCounter)(Keep.left)

具有相同的物化.但是,由于 Sink.head[T] 实现了 Future[T],因此更改组合器显然会产生影响

have the same materialization. However, since Sink.head[T] materializes to Future[T], changing the combiner clearly has an impact

val intSource = sentenceSource.viaMat(wordCounter)(Keep.right)

val notUsed = intSource.toMat(Sink.head)(Keep.left)
// akka.stream.scaladsl.RunnableGraph[akka.NotUsed]

val intFut = intSource.toMat(Sink.head)(Keep.right)
// akka.stream.scaladsl.RunnableGraph[scala.concurrent.Future[Int]]

notUsed.run    // akka.NotUsed

intFut.run     // Future(Success(12))

Source 中的大部分源代码都实现了 NotUsed 并且几乎所有常见的 Flow 操作符也实现了,所以 toMat(someSink)(Keep.right)(或等效的 .runWith(someSink))比使用 Keep.leftKeep 更普遍.both.源/流物化最常见的用例是提供某种控制平面,例如:

Most of the sources in Source materialize to NotUsed and nearly all of the common Flow operators do as well, so toMat(someSink)(Keep.right) (or the equivalent .runWith(someSink)) is far more prevalent than using Keep.left or Keep.both. The most common usecases for source/flow materialization are to provide some sort of control plane, such as:

import akka.Done
import akka.stream.{ CompletionStrategy, OverflowStrategy }

import system.dispatcher

val completionMatcher: PartialFunction[Any, CompletionStrategy] = { case Done => CompletionStrategy.draining }
val failureMatcher: PartialFunction[Any, Throwable] = { case 666 => new Exception("""m/""") }

val sentenceSource = Source.actorRef[String](completionMatcher = completionMatcher, failureMatcher = failureMatcher, bufferSize = 100, overflowStrategy = OverflowStrategy.dropNew)

// same wordCounter as before
val stream = sentenceSource.viaMat(wordCounter)(Keep.left).toMat(Sink.head)(Keep.both)    // akka.stream.scaladsl.RunnableGraph[(akka.actor.ActorRef, scala.concurrent.Future[Int])]

val (sourceRef, intFut) = stream.run()

sourceRef ! "Materialized values are confusing me"
sourceRef ! "I love streams"
sourceRef ! "Left foo right bar"
sourceRef ! Done

intFut.foreach { result =>
  println(result)
  system.terminate()
}

在这种情况下,我们使用 Keep.left 来传递 sentenceSource 的物化值,然后使用 Keep.both 来获得两者物化值和 Sink.head.

In this case, we use Keep.left to pass through sentenceSource's materialized value and then Keep.both to get both that materialized value and that of Sink.head.

这篇关于Akka Stream 的 Keep right/left/both 如何导致不同的输出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆