pekko/akka-docs/rst/scala/code/docs/stream/cookbook/RecipeHold.scala

147 lines
3.4 KiB
Scala
Raw Normal View History

2014-12-08 17:29:40 +01:00
package docs.stream.cookbook
import akka.stream.Attributes
2014-12-08 17:29:40 +01:00
import akka.stream.scaladsl.{ Sink, Source }
2015-04-24 11:45:03 +03:00
import akka.stream.testkit._
2014-12-08 17:29:40 +01:00
import scala.concurrent.duration._
object HoldOps {
//#hold-version-1
import akka.stream._
2014-12-08 17:29:40 +01:00
import akka.stream.stage._
final class HoldWithInitial[T](initial: T) extends GraphStage[FlowShape[T, T]] {
val in = Inlet[T]("HoldWithInitial.in")
val out = Outlet[T]("HoldWithInitial.out")
2014-12-08 17:29:40 +01:00
override val shape = FlowShape.of(in, out)
override def createLogic(inheritedAttributes: Attributes): GraphStageLogic = new GraphStageLogic(shape) {
private var currentValue: T = initial
setHandlers(in, out, new InHandler with OutHandler {
override def onPush(): Unit = {
currentValue = grab(in)
pull(in)
}
override def onPull(): Unit = {
push(out, currentValue)
}
})
2014-12-08 17:29:40 +01:00
override def preStart(): Unit = {
pull(in)
}
2014-12-08 17:29:40 +01:00
}
}
//#hold-version-1
//#hold-version-2
import akka.stream._
2014-12-08 17:29:40 +01:00
import akka.stream.stage._
final class HoldWithWait[T] extends GraphStage[FlowShape[T, T]] {
val in = Inlet[T]("HoldWithWait.in")
val out = Outlet[T]("HoldWithWait.out")
override val shape = FlowShape.of(in, out)
override def createLogic(inheritedAttributes: Attributes): GraphStageLogic = new GraphStageLogic(shape) {
private var currentValue: T = _
private var waitingFirstValue = true
setHandlers(in, out, new InHandler with OutHandler {
override def onPush(): Unit = {
currentValue = grab(in)
if (waitingFirstValue) {
waitingFirstValue = false
if (isAvailable(out)) push(out, currentValue)
}
pull(in)
}
override def onPull(): Unit = {
if (!waitingFirstValue) push(out, currentValue)
}
})
override def preStart(): Unit = {
pull(in)
}
2014-12-08 17:29:40 +01:00
}
}
//#hold-version-2
}
class RecipeHold extends RecipeSpec {
import HoldOps._
"Recipe for creating a holding element" must {
"work for version 1" in {
2015-04-24 11:45:03 +03:00
val pub = TestPublisher.probe[Int]()
val sub = TestSubscriber.manualProbe[Int]()
val source = Source.fromPublisher(pub)
val sink = Sink.fromSubscriber(sub)
2014-12-08 17:29:40 +01:00
source.via(new HoldWithInitial(0)).to(sink)
.withAttributes(Attributes.inputBuffer(1, 1))
.run()
2014-12-08 17:29:40 +01:00
val subscription = sub.expectSubscription()
sub.expectNoMsg(100.millis)
subscription.request(1)
sub.expectNext(0)
subscription.request(1)
sub.expectNext(0)
2015-04-24 11:45:03 +03:00
pub.sendNext(1)
pub.sendNext(2)
2014-12-08 17:29:40 +01:00
subscription.request(2)
sub.expectNext(2)
sub.expectNext(2)
2015-04-24 11:45:03 +03:00
pub.sendComplete()
2014-12-08 17:29:40 +01:00
subscription.request(1)
sub.expectComplete()
}
"work for version 2" in {
2015-04-24 11:45:03 +03:00
val pub = TestPublisher.probe[Int]()
val sub = TestSubscriber.manualProbe[Int]()
val source = Source.fromPublisher(pub)
val sink = Sink.fromSubscriber(sub)
2014-12-08 17:29:40 +01:00
source.via(new HoldWithWait).to(sink).run()
2014-12-08 17:29:40 +01:00
val subscription = sub.expectSubscription()
sub.expectNoMsg(100.millis)
subscription.request(1)
sub.expectNoMsg(100.millis)
2015-04-24 11:45:03 +03:00
pub.sendNext(1)
2014-12-08 17:29:40 +01:00
sub.expectNext(1)
2015-04-24 11:45:03 +03:00
pub.sendNext(2)
pub.sendNext(3)
2014-12-08 17:29:40 +01:00
subscription.request(2)
sub.expectNext(3)
sub.expectNext(3)
2015-04-24 11:45:03 +03:00
pub.sendComplete()
2014-12-08 17:29:40 +01:00
subscription.request(1)
sub.expectComplete()
}
}
}