!str #17090 add AsyncStage
This commit is contained in:
parent
ad3829cd74
commit
4c623fade7
66 changed files with 981 additions and 787 deletions
|
|
@ -20,14 +20,14 @@ class RecipeByteStrings extends RecipeSpec {
|
|||
class Chunker(val chunkSize: Int) extends PushPullStage[ByteString, ByteString] {
|
||||
private var buffer = ByteString.empty
|
||||
|
||||
override def onPush(elem: ByteString, ctx: Context[ByteString]): Directive = {
|
||||
override def onPush(elem: ByteString, ctx: Context[ByteString]): SyncDirective = {
|
||||
buffer ++= elem
|
||||
emitChunkOrPull(ctx)
|
||||
}
|
||||
|
||||
override def onPull(ctx: Context[ByteString]): Directive = emitChunkOrPull(ctx)
|
||||
override def onPull(ctx: Context[ByteString]): SyncDirective = emitChunkOrPull(ctx)
|
||||
|
||||
private def emitChunkOrPull(ctx: Context[ByteString]): Directive = {
|
||||
private def emitChunkOrPull(ctx: Context[ByteString]): SyncDirective = {
|
||||
if (buffer.isEmpty) ctx.pull()
|
||||
else {
|
||||
val (emit, nextBuffer) = buffer.splitAt(chunkSize)
|
||||
|
|
@ -57,7 +57,7 @@ class RecipeByteStrings extends RecipeSpec {
|
|||
class ByteLimiter(val maximumBytes: Long) extends PushStage[ByteString, ByteString] {
|
||||
private var count = 0
|
||||
|
||||
override def onPush(chunk: ByteString, ctx: Context[ByteString]): Directive = {
|
||||
override def onPush(chunk: ByteString, ctx: Context[ByteString]): SyncDirective = {
|
||||
count += chunk.size
|
||||
if (count > maximumBytes) ctx.fail(new IllegalStateException("Too much bytes"))
|
||||
else ctx.push(chunk)
|
||||
|
|
|
|||
|
|
@ -23,12 +23,12 @@ class RecipeDigest extends RecipeSpec {
|
|||
def digestCalculator(algorithm: String) = new PushPullStage[ByteString, ByteString] {
|
||||
val digest = MessageDigest.getInstance(algorithm)
|
||||
|
||||
override def onPush(chunk: ByteString, ctx: Context[ByteString]): Directive = {
|
||||
override def onPush(chunk: ByteString, ctx: Context[ByteString]): SyncDirective = {
|
||||
digest.update(chunk.toArray)
|
||||
ctx.pull()
|
||||
}
|
||||
|
||||
override def onPull(ctx: Context[ByteString]): Directive = {
|
||||
override def onPull(ctx: Context[ByteString]): SyncDirective = {
|
||||
if (ctx.isFinishing) ctx.pushAndFinish(ByteString(digest.digest()))
|
||||
else ctx.pull()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,12 +79,12 @@ class RecipeGlobalRateLimit extends RecipeSpec {
|
|||
def limitGlobal[T](limiter: ActorRef, maxAllowedWait: FiniteDuration): Flow[T, T, Unit] = {
|
||||
import akka.pattern.ask
|
||||
import akka.util.Timeout
|
||||
Flow[T].mapAsync { (element: T) =>
|
||||
Flow[T].mapAsync(4, (element: T) => {
|
||||
import system.dispatcher
|
||||
implicit val triggerTimeout = Timeout(maxAllowedWait)
|
||||
val limiterTriggerFuture = limiter ? Limiter.WantToPass
|
||||
limiterTriggerFuture.map((_) => element)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
//#global-limiter-flow
|
||||
|
|
|
|||
|
|
@ -33,12 +33,12 @@ object HoldOps {
|
|||
override def onPush(elem: T, ctx: DetachedContext[T]): UpstreamDirective = {
|
||||
currentValue = elem
|
||||
waitingFirstValue = false
|
||||
if (ctx.isHolding) ctx.pushAndPull(currentValue)
|
||||
if (ctx.isHoldingDownstream) ctx.pushAndPull(currentValue)
|
||||
else ctx.pull()
|
||||
}
|
||||
|
||||
override def onPull(ctx: DetachedContext[T]): DownstreamDirective = {
|
||||
if (waitingFirstValue) ctx.hold()
|
||||
if (waitingFirstValue) ctx.holdDownstream()
|
||||
else ctx.push(currentValue)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class RecipeLoggingElements extends RecipeSpec {
|
|||
class LoggingStage[T] extends PushStage[T, T] {
|
||||
private val log = Logging(system, "loggingName")
|
||||
|
||||
override def onPush(elem: T, ctx: Context[T]): Directive = {
|
||||
override def onPush(elem: T, ctx: Context[T]): SyncDirective = {
|
||||
log.debug("Element flowing through: {}", elem)
|
||||
ctx.push(elem)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ class RecipeMultiGroupBy extends RecipeSpec {
|
|||
|
||||
val result = multiGroups.map {
|
||||
case (topic, topicMessages) => topicMessages.grouped(10).map(topic.name + _.mkString("[", ", ", "]")).runWith(Sink.head)
|
||||
}.mapAsync(identity).grouped(10).runWith(Sink.head)
|
||||
}.mapAsync(4, identity).grouped(10).runWith(Sink.head)
|
||||
|
||||
Await.result(result, 3.seconds).toSet should be(Set(
|
||||
"1[1: a, 1: b, all: c, all: d, 1: e]",
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ object RecipeParseLines {
|
|||
private var nextPossibleMatch = 0
|
||||
|
||||
def initial = new State {
|
||||
override def onPush(chunk: ByteString, ctx: Context[String]): Directive = {
|
||||
override def onPush(chunk: ByteString, ctx: Context[String]): SyncDirective = {
|
||||
buffer ++= chunk
|
||||
if (buffer.size > maximumLineBytes)
|
||||
ctx.fail(new IllegalStateException(s"Read ${buffer.size} bytes " +
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class RecipeReduceByKey extends RecipeSpec {
|
|||
val counts: Source[(String, Int), Unit] =
|
||||
countedWords
|
||||
.buffer(MaximumDistinctWords, OverflowStrategy.fail)
|
||||
.mapAsync(identity)
|
||||
.mapAsync(4, identity)
|
||||
//#word-count
|
||||
|
||||
Await.result(counts.grouped(10).runWith(Sink.head), 3.seconds).toSet should be(Set(
|
||||
|
|
@ -62,7 +62,7 @@ class RecipeReduceByKey extends RecipeSpec {
|
|||
}
|
||||
}
|
||||
|
||||
reducedValues.buffer(maximumGroupSize, OverflowStrategy.fail).mapAsync(identity)
|
||||
reducedValues.buffer(maximumGroupSize, OverflowStrategy.fail).mapAsync(4, identity)
|
||||
}
|
||||
|
||||
val wordCounts = words.via(reduceByKey(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue