migrating Doubler, KeepGoing to GraphStage
This commit is contained in:
parent
a1423b6e7d
commit
16ac832b14
2 changed files with 64 additions and 36 deletions
|
|
@ -132,7 +132,7 @@ class HttpServerExampleSpec extends WordSpec with Matchers
|
||||||
"connection-stream-failure-handling" in compileOnlySpec {
|
"connection-stream-failure-handling" in compileOnlySpec {
|
||||||
import akka.actor.ActorSystem
|
import akka.actor.ActorSystem
|
||||||
import akka.http.scaladsl.Http
|
import akka.http.scaladsl.Http
|
||||||
import akka.http.scaladsl.model.{ContentTypes, HttpEntity}
|
import akka.http.scaladsl.model.{ ContentTypes, HttpEntity }
|
||||||
import akka.stream.ActorMaterializer
|
import akka.stream.ActorMaterializer
|
||||||
|
|
||||||
implicit val system = ActorSystem()
|
implicit val system = ActorSystem()
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import akka.stream.stage._
|
||||||
import akka.testkit.AkkaSpec
|
import akka.testkit.AkkaSpec
|
||||||
import akka.testkit.EventFilter
|
import akka.testkit.EventFilter
|
||||||
|
|
||||||
import akka.stream.Supervision
|
import akka.stream._
|
||||||
|
|
||||||
class InterpreterSpec extends AkkaSpec with GraphInterpreterSpecKit {
|
class InterpreterSpec extends AkkaSpec with GraphInterpreterSpecKit {
|
||||||
import Supervision.stoppingDecider
|
import Supervision.stoppingDecider
|
||||||
|
|
@ -80,7 +80,7 @@ class InterpreterSpec extends AkkaSpec with GraphInterpreterSpecKit {
|
||||||
}
|
}
|
||||||
|
|
||||||
"implement one-to-many many-to-one chain correctly" in new OneBoundedSetup[Int](
|
"implement one-to-many many-to-one chain correctly" in new OneBoundedSetup[Int](
|
||||||
Doubler().toGS,
|
Doubler(),
|
||||||
Filter((x: Int) ⇒ x != 0)) {
|
Filter((x: Int) ⇒ x != 0)) {
|
||||||
|
|
||||||
lastEvents() should be(Set.empty)
|
lastEvents() should be(Set.empty)
|
||||||
|
|
@ -106,7 +106,7 @@ class InterpreterSpec extends AkkaSpec with GraphInterpreterSpecKit {
|
||||||
|
|
||||||
"implement many-to-one one-to-many chain correctly" in new OneBoundedSetup[Int](
|
"implement many-to-one one-to-many chain correctly" in new OneBoundedSetup[Int](
|
||||||
Filter((x: Int) ⇒ x != 0),
|
Filter((x: Int) ⇒ x != 0),
|
||||||
Doubler().toGS) {
|
Doubler()) {
|
||||||
|
|
||||||
lastEvents() should be(Set.empty)
|
lastEvents() should be(Set.empty)
|
||||||
|
|
||||||
|
|
@ -412,7 +412,7 @@ class InterpreterSpec extends AkkaSpec with GraphInterpreterSpecKit {
|
||||||
}
|
}
|
||||||
|
|
||||||
"implement doubler-conflate (doubler-batch)" in new OneBoundedSetup[Int](
|
"implement doubler-conflate (doubler-batch)" in new OneBoundedSetup[Int](
|
||||||
Doubler().toGS,
|
Doubler(),
|
||||||
Batch(
|
Batch(
|
||||||
1L,
|
1L,
|
||||||
ConstantFun.zeroLong,
|
ConstantFun.zeroLong,
|
||||||
|
|
@ -432,12 +432,12 @@ class InterpreterSpec extends AkkaSpec with GraphInterpreterSpecKit {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note, the new interpreter has no jumpback table, still did not want to remove the test
|
// Note, the new interpreter has no jumpback table, still did not want to remove the test
|
||||||
"work with jumpback table and completed elements" in new OneBoundedSetup[Int](Seq(
|
"work with jumpback table and completed elements" in new OneBoundedSetup[Int](
|
||||||
Map((x: Int) ⇒ x, stoppingDecider),
|
Map((x: Int) ⇒ x, stoppingDecider).toGS,
|
||||||
Map((x: Int) ⇒ x, stoppingDecider),
|
Map((x: Int) ⇒ x, stoppingDecider).toGS,
|
||||||
KeepGoing(),
|
KeepGoing(),
|
||||||
Map((x: Int) ⇒ x, stoppingDecider),
|
Map((x: Int) ⇒ x, stoppingDecider).toGS,
|
||||||
Map((x: Int) ⇒ x, stoppingDecider))) {
|
Map((x: Int) ⇒ x, stoppingDecider).toGS) {
|
||||||
|
|
||||||
lastEvents() should be(Set.empty)
|
lastEvents() should be(Set.empty)
|
||||||
|
|
||||||
|
|
@ -569,39 +569,67 @@ class InterpreterSpec extends AkkaSpec with GraphInterpreterSpecKit {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private[akka] case class Doubler[T]() extends PushPullStage[T, T] {
|
private[akka] final case class Doubler[T]() extends GraphStage[FlowShape[T, T]] {
|
||||||
var oneMore: Boolean = false
|
val out: Outlet[T] = Outlet("Doubler.out")
|
||||||
var lastElem: T = _
|
val in: Inlet[T] = Inlet("Doubler.in")
|
||||||
|
|
||||||
override def onPush(elem: T, ctx: Context[T]): SyncDirective = {
|
override def createLogic(inheritedAttributes: Attributes): GraphStageLogic =
|
||||||
lastElem = elem
|
new GraphStageLogic(shape) with InHandler with OutHandler {
|
||||||
oneMore = true
|
var latest: T = _
|
||||||
ctx.push(elem)
|
var oneMore = false
|
||||||
}
|
|
||||||
|
|
||||||
override def onPull(ctx: Context[T]): SyncDirective = {
|
override def onPush(): Unit = {
|
||||||
if (oneMore) {
|
latest = grab(in)
|
||||||
oneMore = false
|
oneMore = true
|
||||||
ctx.push(lastElem)
|
push(out, latest)
|
||||||
} else ctx.pull()
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* Called when the output port has received a pull, and therefore ready to emit an element, i.e. [[GraphStageLogic.push()]]
|
||||||
|
* is now allowed to be called on this port.
|
||||||
|
*/
|
||||||
|
override def onPull(): Unit = {
|
||||||
|
if (oneMore) {
|
||||||
|
push(out, latest)
|
||||||
|
oneMore = false
|
||||||
|
} else {
|
||||||
|
pull(in)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setHandlers(in, out, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val shape: FlowShape[T, T] = FlowShape(in, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
private[akka] case class KeepGoing[T]() extends PushPullStage[T, T] {
|
private[akka] final case class KeepGoing[T]() extends GraphStage[FlowShape[T, T]] {
|
||||||
var lastElem: T = _
|
val in = Inlet[T]("KeepGoing.in")
|
||||||
|
val out = Outlet[T]("KeepGoing.out")
|
||||||
|
|
||||||
override def onPush(elem: T, ctx: Context[T]): SyncDirective = {
|
override def createLogic(inheritedAttributes: Attributes): GraphStageLogic =
|
||||||
lastElem = elem
|
new GraphStageLogic(shape) with InHandler with OutHandler {
|
||||||
ctx.push(elem)
|
var lastElem: T = _
|
||||||
}
|
|
||||||
|
|
||||||
override def onPull(ctx: Context[T]): SyncDirective = {
|
override def onPush(): Unit = {
|
||||||
if (ctx.isFinishing) {
|
lastElem = grab(in)
|
||||||
ctx.push(lastElem)
|
push(out, lastElem)
|
||||||
} else ctx.pull()
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override def onUpstreamFinish(ctx: Context[T]): TerminationDirective = ctx.absorbTermination()
|
override def onPull(): Unit = {
|
||||||
|
if (isClosed(in)) {
|
||||||
|
push(out, lastElem)
|
||||||
|
} else {
|
||||||
|
pull(in)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override def onUpstreamFinish(): Unit = {}
|
||||||
|
|
||||||
|
setHandlers(in, out, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val shape: FlowShape[T, T] = FlowShape(in, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This test is related to issue #17351
|
// This test is related to issue #17351
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue