Implements actorRef source variant with backpressure #17610 (#26633)

* Implements actorRef source variant with backpressure #17610

* Small improvements to documentation and source #17610

* Small improvements to test #17610

* Small improvements to implementation and tests #17610

* Adds API for akka-typed #17610

* Adds ack sender and java api for typed #17610
This commit is contained in:
Nicolas Vollmar 2019-05-20 12:19:44 +02:00 committed by Patrik Nordwall
parent a9f4f2dd96
commit f37f41574d
14 changed files with 472 additions and 6 deletions

View file

@ -7,8 +7,8 @@ package akka.stream.typed.javadsl
import java.util.function.Predicate
import akka.actor.typed._
import akka.stream.OverflowStrategy
import akka.stream.javadsl._
import akka.stream.{ CompletionStrategy, OverflowStrategy }
/**
* Collection of Sources aimed at integrating with typed Actors.
@ -60,4 +60,31 @@ object ActorSource {
overflowStrategy)
.asJava
}
/**
* Creates a `Source` that is materialized as an [[akka.actor.ActorRef]].
* Messages sent to this actor will be emitted to the stream if there is demand from downstream,
* and a new message will only be accepted after the previous messages has been consumed and acknowledged back.
* The stream will complete with failure if a message is sent before the acknowledgement has been replied back.
*
* The stream can be completed with failure by sending a message that is matched by `failureMatcher`. The extracted
* [[Throwable]] will be used to fail the stream. In case the Actor is still draining its internal buffer (after having received
* a message matched by `completionMatcher`) before signaling completion and it receives a message matched by `failureMatcher`,
* the failure will be signaled downstream immediately (instead of the completion signal).
*
* The actor will be stopped when the stream is completed, failed or canceled from downstream,
* i.e. you can watch it to get notified when that happens.
*/
def actorRefWithAck[T, Ack](
ackTo: ActorRef[Ack],
ackMessage: Ack,
completionMatcher: PartialFunction[T, CompletionStrategy],
failureMatcher: PartialFunction[T, Throwable]): Source[T, ActorRef[T]] =
akka.stream.typed.scaladsl.ActorSource
.actorRefWithAck[T, Ack](
ackTo,
ackMessage,
completionMatcher.asInstanceOf[PartialFunction[Any, CompletionStrategy]],
failureMatcher.asInstanceOf[PartialFunction[Any, Throwable]])
.asJava
}

View file

@ -5,8 +5,8 @@
package akka.stream.typed.scaladsl
import akka.actor.typed._
import akka.stream.{ CompletionStrategy, OverflowStrategy }
import akka.stream.scaladsl._
import akka.stream.{ CompletionStrategy, OverflowStrategy }
/**
* Collection of Sources aimed at integrating with typed Actors.
@ -59,4 +59,31 @@ object ActorSource {
bufferSize,
overflowStrategy)
.mapMaterializedValue(actorRefAdapter)
/**
* Creates a `Source` that is materialized as an [[akka.actor.ActorRef]].
* Messages sent to this actor will be emitted to the stream if there is demand from downstream,
* and a new message will only be accepted after the previous messages has been consumed and acknowledged back.
* The stream will complete with failure if a message is sent before the acknowledgement has been replied back.
*
* The stream can be completed with failure by sending a message that is matched by `failureMatcher`. The extracted
* [[Throwable]] will be used to fail the stream. In case the Actor is still draining its internal buffer (after having received
* a message matched by `completionMatcher`) before signaling completion and it receives a message matched by `failureMatcher`,
* the failure will be signaled downstream immediately (instead of the completion signal).
*
* The actor will be stopped when the stream is completed, failed or canceled from downstream,
* i.e. you can watch it to get notified when that happens.
*/
def actorRefWithAck[T, Ack](
ackTo: ActorRef[Ack],
ackMessage: Ack,
completionMatcher: PartialFunction[T, CompletionStrategy],
failureMatcher: PartialFunction[T, Throwable]): Source[T, ActorRef[T]] =
Source
.actorRefWithAck[T](
Some(ackTo.toUntyped),
ackMessage,
completionMatcher.asInstanceOf[PartialFunction[Any, CompletionStrategy]],
failureMatcher.asInstanceOf[PartialFunction[Any, Throwable]])
.mapMaterializedValue(actorRefAdapter)
}

View file

@ -6,7 +6,7 @@ package akka.stream.typed.scaladsl
import akka.actor.typed.ActorRef
import akka.actor.typed.scaladsl.Behaviors
import akka.stream.OverflowStrategy
import akka.stream.{ CompletionStrategy, OverflowStrategy }
import akka.stream.scaladsl.Keep
import akka.stream.scaladsl.Sink
import akka.stream.scaladsl.Source
@ -107,6 +107,25 @@ class ActorSourceSinkSpec extends ScalaTestWithActorTestKit with WordSpecLike {
out.failed.futureValue.getCause.getMessage shouldBe "boom!"
}
}
"send message and ack" in {
val p = TestProbe[String]()
val (in, out) = ActorSource
.actorRefWithAck[String, String](
p.ref,
"ack", { case "complete" => CompletionStrategy.draining },
PartialFunction.empty)
.toMat(Sink.seq)(Keep.both)
.run()
in ! "one"
p.expectMessage("ack")
in ! "two"
p.expectMessage("ack")
in ! "complete"
out.futureValue should contain theSameElementsAs Seq("one", "two")
}
}
}