@Test public void reusingComponents() throws Exception { final Source<Integer, NotUsed> nestedSource = Source.single(0) // An atomic source .map(i -> i + 1) // an atomic processing stage .named("nestedSource"); // wraps up the current Source and gives it a name final Flow<Integer, Integer, NotUsed> nestedFlow = Flow.of(Integer.class) .filter(i -> i != 0) // an atomic processing stage .map(i -> i - 2) // another atomic processing stage .named("nestedFlow"); // wraps up the Flow, and gives it a name final Sink<Integer, NotUsed> nestedSink = nestedFlow .to(Sink.fold(0, (acc, i) -> acc + i)) // wire an atomic sink to the nestedFlow .named("nestedSink"); // wrap it up // #reuse // Create a RunnableGraph from our components final RunnableGraph<NotUsed> runnableGraph = nestedSource.to(nestedSink); // Usage is uniform, no matter if modules are composite or atomic final RunnableGraph<NotUsed> runnableGraph2 = Source.single(0).to(Sink.fold(0, (acc, i) -> acc + i)); // #reuse }
@Test public void nonNestedFlow() throws Exception { // #non-nested-flow Source.single(0) .map(i -> i + 1) .filter(i -> i != 0) .map(i -> i - 2) .to(Sink.fold(0, (acc, i) -> acc + i)); // ... where is the nesting? // #non-nested-flow }
@Test public void demonstrateChainingOfGraphStages() throws Exception { Graph<SinkShape<Integer>, CompletionStage<String>> sink = Sink.fold("", (acc, n) -> acc + n.toString()); // #graph-stage-chain CompletionStage<String> resultFuture = Source.from(Arrays.asList(1, 2, 3, 4, 5)) .via(new Filter<Integer>((n) -> n % 2 == 0)) .via(new Duplicator<Integer>()) .via(new Map<Integer, Integer>((n) -> n / 2)) .runWith(sink, mat); // #graph-stage-chain assertEquals("1122", resultFuture.toCompletableFuture().get(3, TimeUnit.SECONDS)); }
@Test public void materializedValues() throws Exception { // #mat-combine-1 // Materializes to Promise<BoxedUnit> (red) final Source<Integer, CompletableFuture<Optional<Integer>>> source = Source.<Integer>maybe(); // Materializes to BoxedUnit (black) final Flow<Integer, Integer, NotUsed> flow1 = Flow.of(Integer.class).take(100); // Materializes to Promise<Option<>> (red) final Source<Integer, CompletableFuture<Optional<Integer>>> nestedSource = source.viaMat(flow1, Keep.left()).named("nestedSource"); // #mat-combine-1 // #mat-combine-2 // Materializes to BoxedUnit (orange) final Flow<Integer, ByteString, NotUsed> flow2 = Flow.of(Integer.class).map(i -> ByteString.fromString(i.toString())); // Materializes to Future<OutgoingConnection> (yellow) final Flow<ByteString, ByteString, CompletionStage<OutgoingConnection>> flow3 = Tcp.get(system).outgoingConnection("localhost", 8080); // Materializes to Future<OutgoingConnection> (yellow) final Flow<Integer, ByteString, CompletionStage<OutgoingConnection>> nestedFlow = flow2.viaMat(flow3, Keep.right()).named("nestedFlow"); // #mat-combine-2 // #mat-combine-3 // Materializes to Future<String> (green) final Sink<ByteString, CompletionStage<String>> sink = Sink.<String, ByteString>fold("", (acc, i) -> acc + i.utf8String()); // Materializes to Pair<Future<OutgoingConnection>, Future<String>> (blue) final Sink<Integer, Pair<CompletionStage<OutgoingConnection>, CompletionStage<String>>> nestedSink = nestedFlow.toMat(sink, Keep.both()); // #mat-combine-3 // #mat-combine-4b // Materializes to Future<MyClass> (purple) final RunnableGraph<CompletionStage<MyClass>> runnableGraph = nestedSource.toMat(nestedSink, Combiner::f); // #mat-combine-4b }
@Test public void demonstrateMaterializeMultipleTimes() { final Source<Tweet, NotUsed> tweetsInMinuteFromNow = tweets; // not really in second, just acting as if // #tweets-runnable-flow-materialized-twice final Sink<Integer, CompletionStage<Integer>> sumSink = Sink.<Integer, Integer>fold(0, (acc, elem) -> acc + elem); final RunnableGraph<CompletionStage<Integer>> counterRunnableGraph = tweetsInMinuteFromNow .filter(t -> t.hashtags().contains(AKKA)) .map(t -> 1) .toMat(sumSink, Keep.right()); // materialize the stream once in the morning final CompletionStage<Integer> morningTweetsCount = counterRunnableGraph.run(mat); // and once in the evening, reusing the blueprint final CompletionStage<Integer> eveningTweetsCount = counterRunnableGraph.run(mat); // #tweets-runnable-flow-materialized-twice }
@Test public void demonstrateCountOnFiniteStream() { // #tweets-fold-count final Sink<Integer, CompletionStage<Integer>> sumSink = Sink.<Integer, Integer>fold(0, (acc, elem) -> acc + elem); final RunnableGraph<CompletionStage<Integer>> counter = tweets.map(t -> 1).toMat(sumSink, Keep.right()); final CompletionStage<Integer> sum = counter.run(mat); sum.thenAcceptAsync( c -> System.out.println("Total tweets processed: " + c), system.dispatcher()); // #tweets-fold-count new Object() { // #tweets-fold-count-oneline final CompletionStage<Integer> sum = tweets.map(t -> 1).runWith(sumSink, mat); // #tweets-fold-count-oneline }; }
@Test public void attributes() throws Exception { // #attributes-inheritance final Source<Integer, NotUsed> nestedSource = Source.single(0).map(i -> i + 1).named("nestedSource"); // Wrap, no inputBuffer set final Flow<Integer, Integer, NotUsed> nestedFlow = Flow.of(Integer.class) .filter(i -> i != 0) .via( Flow.of(Integer.class) .map(i -> i - 2) .withAttributes(Attributes.inputBuffer(4, 4))) // override .named("nestedFlow"); // Wrap, no inputBuffer set final Sink<Integer, NotUsed> nestedSink = nestedFlow .to(Sink.fold(0, (acc, i) -> acc + i)) // wire an atomic sink to the nestedFlow .withAttributes( Attributes.name("nestedSink").and(Attributes.inputBuffer(3, 3))); // override // #attributes-inheritance }
@Test public void nestedFlow() throws Exception { // #nested-flow final Source<Integer, NotUsed> nestedSource = Source.single(0) // An atomic source .map(i -> i + 1) // an atomic processing stage .named("nestedSource"); // wraps up the current Source and gives it a name final Flow<Integer, Integer, NotUsed> nestedFlow = Flow.of(Integer.class) .filter(i -> i != 0) // an atomic processing stage .map(i -> i - 2) // another atomic processing stage .named("nestedFlow"); // wraps up the Flow, and gives it a name final Sink<Integer, NotUsed> nestedSink = nestedFlow .to(Sink.fold(0, (acc, i) -> acc + i)) // wire an atomic sink to the nestedFlow .named("nestedSink"); // wrap it up // Create a RunnableGraph final RunnableGraph<NotUsed> runnableGraph = nestedSource.to(nestedSink); // #nested-flow }