示例#1
0
 public void A_Flow_must_be_covariant()
 {
     Source <IFruit, NotUsed> f1 = Source.From <IFruit>(Apples());
     IPublisher <IFruit>      p1 = Source.From <IFruit>(Apples()).RunWith(Sink.AsPublisher <IFruit>(false), Materializer);
     SubFlow <IFruit, NotUsed, IRunnableGraph <NotUsed> > f2 =
         Source.From <IFruit>(Apples()).SplitWhen(_ => true);
     SubFlow <IFruit, NotUsed, IRunnableGraph <NotUsed> > f3 =
         Source.From <IFruit>(Apples()).GroupBy(2, _ => true);
     Source <(IImmutableList <IFruit>, Source <IFruit, NotUsed>), NotUsed> f4 =
         Source.From <IFruit>(Apples()).PrefixAndTail(1);
     SubFlow <IFruit, NotUsed, Sink <string, NotUsed> > d1 =
         Flow.Create <string>()
         .Select <string, string, IFruit, NotUsed>(_ => new Apple())
         .SplitWhen(_ => true);
     SubFlow <IFruit, NotUsed, Sink <string, NotUsed> > d2 =
         Flow.Create <string>()
         .Select <string, string, IFruit, NotUsed>(_ => new Apple())
         .GroupBy(-1, _ => 2);
     Flow <string, (IImmutableList <IFruit>, Source <IFruit, NotUsed>), NotUsed> d3 =
         Flow.Create <string>().Select <string, string, IFruit, NotUsed>(_ => new Apple()).PrefixAndTail(1);
 }
示例#2
0
        public void A_Flow_must_be_possible_to_convert_to_a_processor_and_should_be_able_to_take_a_Processor()
        {
            var identity1 = Flow.Create <int>().ToProcessor();
            var identity2 = Flow.FromProcessor(() => identity1.Run(Materializer));
            var task      = Source.From(Enumerable.Range(1, 10))
                            .Via(identity2)
                            .Limit(100)
                            .RunWith(Sink.Seq <int>(), Materializer);

            task.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue();
            task.Result.ShouldAllBeEquivalentTo(Enumerable.Range(1, 10));

            // Reusable:
            task = Source.From(Enumerable.Range(1, 10))
                   .Via(identity2)
                   .Limit(100)
                   .RunWith(Sink.Seq <int>(), Materializer);

            task.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue();
            task.Result.ShouldAllBeEquivalentTo(Enumerable.Range(1, 10));
        }
示例#3
0
        private static IGraph <FlowShape <int, string>, NotUsed> PartialGraph()
        {
            return(GraphDsl.Create(b =>
            {
                var source2 = Source.From(Enumerable.Range(4, 6));
                var source3 = Source.Empty <int>();
                var source4 = Source.Empty <string>();

                var inMerge = b.Add(new Merge <int>(2));
                var outMerge = b.Add(new Merge <string>(2));
                var m2 = b.Add(new Merge <int>(2));

                b.From(inMerge.Out).Via(Flow.Create <int>().Select(x => x * 2)).To(m2.In(0));
                b.From(m2.Out).Via(Flow.Create <int>().Select(x => x / 2).Select(i => (i + 1).ToString())).To(outMerge.In(0));

                b.From(source2).To(inMerge.In(0));
                b.From(source3).To(m2.In(1));
                b.From(source4).To(outMerge.In(1));
                return new FlowShape <int, string>(inMerge.In(1), outMerge.Out);
            }));
        }
示例#4
0
        public void Throttle_for_single_cost_elements_must_()
        {
            var sharedThrottle = Flow.Create <int>().Throttle(1, TimeSpan.FromDays(1), 1, ThrottleMode.Enforcing);

            // If there is accidental shared state then we would not be able to pass through the single element
            var t = Source.Single(1)
                    .Via(sharedThrottle)
                    .Via(sharedThrottle)
                    .RunWith(Sink.First <int>(), Materializer);

            t.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue();
            t.Result.Should().Be(1);

            // It works with a new stream, too
            t = Source.Single(2)
                .Via(sharedThrottle)
                .Via(sharedThrottle)
                .RunWith(Sink.First <int>(), Materializer);
            t.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue();
            t.Result.Should().Be(2);
        }
示例#5
0
        public void GraphDSLs_when_turned_into_sources_should_be_reusable_multiple_times()
        {
            var probe = this.CreateManualSubscriberProbe <int>();

            var source =
                Source.FromGraph(GraphDsl.Create(Source.From(Enumerable.Range(1, 5)),
                                                 (b, s) =>
            {
                var o = b.From(s.Outlet).Via(Flow.Create <int>().Select(x => x * 2));
                return(new SourceShape <int>(o.Out));
            }));

            RunnableGraph.FromGraph(GraphDsl.Create(source, source, Keep.Both, (b, s1, s2) =>
            {
                var merge = b.Add(new Merge <int>(2));
                b.From(s1.Outlet).To(merge.In(0));
                b.From(merge.Out)
                .To(Sink.FromSubscriber(probe).MapMaterializedValue(_ => (NotUsed.Instance, NotUsed.Instance)));
                b.From(s2.Outlet).Via(Flow.Create <int>().Select(x => x * 10)).To(merge.In(1));
                return(ClosedShape.Instance);
            })).Run(Materializer);
示例#6
0
        public void A_Graph_with_materialized_value_must_expose_the_materialized_value_as_source()
        {
            var sub = TestSubscriber.CreateManualProbe <int>(this);
            var f   = RunnableGraph.FromGraph(GraphDsl.Create(FoldSink, (b, fold) =>
            {
                var source = Source.From(Enumerable.Range(1, 10)).MapMaterializedValue(_ => Task.FromResult(0));
                b.From(source).To(fold);
                b.From(b.MaterializedValue)
                .Via(Flow.Create <Task <int> >().SelectAsync(4, x => x))
                .To(Sink.FromSubscriber(sub).MapMaterializedValue(_ => Task.FromResult(0)));
                return(ClosedShape.Instance);
            })).Run(Materializer);

            f.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue();
            var r1 = f.Result;

            sub.ExpectSubscription().Request(1);
            var r2 = sub.ExpectNext();

            r1.Should().Be(r2);
        }
示例#7
0
        public void A_Partition_must_cancel_upstream_when_downstreams_cancel()
        {
            this.AssertAllStagesStopped(() =>
            {
                var p1 = this.CreatePublisherProbe <int>();
                var c1 = this.CreateSubscriberProbe <int>();
                var c2 = this.CreateSubscriberProbe <int>();

                RunnableGraph.FromGraph(GraphDsl.Create(b =>
                {
                    var partition = b.Add(new Partition <int>(2, i => i < 6 ? 0 : 1));
                    var source    = Source.FromPublisher(p1.Publisher);

                    b.From(source).To(partition.In);
                    b.From(partition.Out(0))
                    .Via(Flow.Create <int>().Buffer(16, OverflowStrategy.Backpressure))
                    .To(Sink.FromSubscriber(c1));
                    b.From(partition.Out(1))
                    .Via(Flow.Create <int>().Buffer(16, OverflowStrategy.Backpressure))
                    .To(Sink.FromSubscriber(c2));

                    return(ClosedShape.Instance);
                })).Run(Materializer);

                var p1Sub = p1.ExpectSubscription();
                var sub1  = c1.ExpectSubscription();
                var sub2  = c2.ExpectSubscription();
                sub1.Request(3);
                sub2.Request(3);
                p1Sub.SendNext(1);
                p1Sub.SendNext(8);
                c1.ExpectNext(1);
                c2.ExpectNext(8);
                p1Sub.SendNext(2);
                c1.ExpectNext(2);
                sub1.Cancel();
                sub2.Cancel();
                p1Sub.ExpectCancellation();
            }, Materializer);
        }
示例#8
0
        public void A_Merge_must_work_in_the_happy_case()
        {
            this.AssertAllStagesStopped(() =>
            {
                // Different input sizes(4 and 6)
                var source1 = Source.From(Enumerable.Range(0, 4));
                var source2 = Source.From(Enumerable.Range(4, 6));
                var source3 = Source.From(new List <int>());
                var probe   = this.CreateManualSubscriberProbe <int>();

                RunnableGraph.FromGraph(GraphDsl.Create(b =>
                {
                    var m1   = b.Add(new Merge <int>(2));
                    var m2   = b.Add(new Merge <int>(2));
                    var sink = Sink.FromSubscriber(probe);

                    b.From(source1).To(m1.In(0));
                    b.From(m1.Out).Via(Flow.Create <int>().Select(x => x * 2)).To(m2.In(0));
                    b.From(m2.Out).Via(Flow.Create <int>().Select(x => x / 2).Select(x => x + 1)).To(sink);
                    b.From(source2).To(m1.In(1));
                    b.From(source3).To(m2.In(1));

                    return(ClosedShape.Instance);
                })).Run(Materializer);

                var subscription = probe.ExpectSubscription();
                var collected    = new List <int>();
                for (var i = 1; i <= 10; i++)
                {
                    subscription.Request(1);
                    collected.Add(probe.ExpectNext());
                }

                collected.Where(i => i <= 4).ShouldOnlyContainInOrder(1, 2, 3, 4);
                collected.Where(i => i >= 5).ShouldOnlyContainInOrder(5, 6, 7, 8, 9, 10);

                collected.Should().BeEquivalentTo(Enumerable.Range(1, 10).ToArray());
                probe.ExpectComplete();
            }, Materializer);
        }
        CreateRunnableWeatherWithThrottleGraph <TMat>(Source <ITweet, TMat> tweetSource)
        {
            var formatUser = Flow.Create <IUser>()
                             .Select(Utils.FormatUser);
            var formatCoordinates = Flow.Create <ICoordinates>()
                                    .Select(Utils.FormatCoordinates);
            var formatTemperature = Flow.Create <decimal>()
                                    .Select(Utils.FormatTemperature);
            var writeSink = Sink.ForEach <string>(Console.WriteLine);

            // 1- Throttle at the same rate (Throttle(10))
            // 2- Throttle at different rate (Throttle(1))
            //     only 1 message because we have 1 stream source & broadcast = 2 channel with 1 request with 10 msg per second and 1 request with 1 msg per second... but we have only 1 stream source, so it cannot send messages to a different rate thus it sattisfy the lowest requirement.
            //
            // adjust parallelism degree
            var graph = GraphDsl.Create(b =>
            {
                var broadcast = b.Add(new Broadcast <ITweet>(2));
                var merge     = b.Add(new Merge <string>(2));
                b.From(broadcast.Out(0))
                .Via(Flow.Create <ITweet>().Select(tweet => tweet.CreatedBy)
                     .Throttle(10, TimeSpan.FromSeconds(1), 1, ThrottleMode.Shaping))
                .Via(formatUser)
                .To(merge.In(0));

                b.From(broadcast.Out(1))
                .Via(Flow.Create <ITweet>().Select(tweet => tweet.Coordinates)
                     //.Buffer(10, OverflowStrategy.DropNew)
                     .Throttle(10, TimeSpan.FromSeconds(1), 1, ThrottleMode.Shaping))
                .Via(Flow.Create <ICoordinates>().SelectAsync(5, Utils.GetWeatherAsync))
                .Via(formatTemperature)
                .To(merge.In(1));

                return(new FlowShape <ITweet, string>(broadcast.In, merge.Out));
            });

            return(tweetSource.Where(x => x.Coordinates != null)
                   .Via(graph).To(writeSink));
        }
示例#10
0
        public void A_Concat_for_Flow_must_work_with_Flow_DSL()
        {
            this.AssertAllStagesStopped(() =>
            {
                var testFlow = Flow.Create <int>()
                               .ConcatMaterialized(Source.From(Enumerable.Range(6, 5)), Keep.Both)
                               .Grouped(1000);
                var task = Source.From(Enumerable.Range(1, 5))
                           .ViaMaterialized(testFlow, Keep.Both)
                           .RunWith(Sink.First <IEnumerable <int> >(), Materializer);
                task.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue();
                task.Result.ShouldAllBeEquivalentTo(Enumerable.Range(1, 10));

                var runnable =
                    Source.From(Enumerable.Range(1, 5))
                    .ViaMaterialized(testFlow, Keep.Both)
                    .To(Sink.Ignore <IEnumerable <int> >());
                runnable.Invoking(r => r.Run(Materializer)).ShouldNotThrow();

                runnable.MapMaterializedValue(_ => "boo").Run(Materializer).Should().Be("boo");
            }, Materializer);
        }
示例#11
0
        public void A_restart_with_backoff_flow_should_run_normally()
        {
            this.AssertAllStagesStopped(() =>
            {
                var created = new AtomicCounter(0);
                var tuple   = this.SourceProbe <string>().ViaMaterialized(RestartFlow.WithBackoff(() =>
                {
                    created.IncrementAndGet();
                    return(Flow.Create <string>());;
                }, TimeSpan.FromMilliseconds(10), TimeSpan.FromMilliseconds(20), 0), Keep.Left).ToMaterialized(this.SinkProbe <string>(), Keep.Both).Run(Materializer);
                var source = tuple.Item1;
                var sink   = tuple.Item2;

                source.SendNext("a");
                sink.RequestNext("a");
                source.SendNext("b");
                sink.RequestNext("b");

                created.Current.Should().Be(1);
                source.SendComplete();
            }, Materializer);
        }
示例#12
0
        public async Task ElementsShouldBeDroppedAtDivideByZeroEx()
        {
            Streams.Supervision.Decider decider =
                cause => cause is DivideByZeroException
                    ? Streams.Supervision.Directive.Resume
                    : Streams.Supervision.Directive.Stop;

            Flow <int, int, string> flow = Flow.Create <int>()
                                           .Where(x => 100 / x < 50)
                                           .Select(x => 100 / (5 - x))
                                           .MapMaterializedValue(_ => "materialization test")
                                           .WithAttributes(ActorAttributes.CreateSupervisionStrategy(decider));
            Source <int, float> source = Source.From(Enumerable.Range(0, 6))
                                         .MapMaterializedValue(_ => 2f);      // Meaningless mapping just for test
            Sink <int, Task <int> >          sink = Sink.Aggregate <int, int>(0, (sum, i) => sum + i);
            IRunnableGraph <(float, string)> materializationTestRunnableGraph = source.Via(flow).ViaMaterialized(flow, Keep.Both).To(sink);
            var rg = source.Via(flow).ToMaterialized(sink, Keep.Right);

            int result = await rg.Run(_materializer);

            Assert.Equal(150, result);
        }
示例#13
0
        public void A_Broadcast_must_cancel_upstream_when_downstreams_cancel()
        {
            this.AssertAllStagesStopped(() =>
            {
                var p1 = this.CreateManualPublisherProbe <int>();
                var c1 = this.CreateManualSubscriberProbe <int>();
                var c2 = this.CreateManualSubscriberProbe <int>();
                RunnableGraph.FromGraph(GraphDsl.Create(b =>
                {
                    var broadcast = b.Add(new Broadcast <int>(2));
                    var source    = Source.FromPublisher(p1.Publisher);
                    b.From(source).To(broadcast.In);
                    b.From(broadcast.Out(0))
                    .Via(Flow.Create <int>())
                    .To(Sink.FromSubscriber(c1));
                    b.From(broadcast.Out(1))
                    .Via(Flow.Create <int>())
                    .To(Sink.FromSubscriber(c2));
                    return(ClosedShape.Instance);
                })).Run(Materializer);

                var bSub = p1.ExpectSubscription();
                var sub1 = c1.ExpectSubscription();
                var sub2 = c2.ExpectSubscription();

                sub1.Request(3);
                sub2.Request(3);
                p1.ExpectRequest(bSub, 16);
                bSub.SendNext(1);
                c1.ExpectNext(1);
                c2.ExpectNext(1);
                bSub.SendNext(2);
                c1.ExpectNext(2);
                c2.ExpectNext(2);
                sub1.Cancel();
                sub2.Cancel();
                bSub.ExpectCancellation();
            }, Materializer);
        }
示例#14
0
        static void Main(string[] args)
        {
            Log.Logger = LoggerFactory.Logger;

            var logSwitch = LoggerFactory.LoggingSwitch;

            var config = ConfigurationFactory.ParseString(File.ReadAllText("config.hocon"));

            logSwitch.MinimumLevel = LogEventLevel.Debug;

            using (var system = ActorSystem.Create("System", config))
                using (var materialiser = system.Materializer())
                {
                    Log.Information("System Started");
                    // Create actors.

                    var loggingActor = system.ActorOf <LoggingActor>("Logger");

                    // Create streams.
                    var generator = Source.From <ISyncData>(GenerateData());

                    var decimator = new SpatialDecimator <ISyncData>(300, 1);

                    var flow = Flow.Create <ISyncData>().Via(decimator);

                    var sink = Sink.ActorRef <ISyncData>(loggingActor, PoisonPill.Instance);

                    var queue = generator.Via(flow).RunWith(sink, materialiser);

                    // Close system logic.
                    Console.CancelKeyPress += (obj, a) =>
                    {
                        system.Terminate().Wait(TimeSpan.FromSeconds(3));
                    };
                    system.WhenTerminated.Wait();
                    Log.Information("System Stopped");
                    Log.CloseAndFlush();
                }
        }
示例#15
0
        public void A_GraphStageLogic_must_emit_all_things_before_completing_with_three_fused_stages()
        {
            this.AssertAllStagesStopped(() =>
            {
                var flow = Flow.Create <int>().Via(new Emit1234()).Via(new PassThrough()).Via(new Emit5678());
                var g    = Streams.Implementation.Fusing.Fusing.Aggressive(flow);

                Source.Empty <int>()
                .Via(g)
                .RunWith(this.SinkProbe <int>(), Materializer)
                .Request(9)
                .ExpectNext(1)
                //emitting with callback gives nondeterminism whether 2 or 3 will be pushed first
                .ExpectNextUnordered(2, 3)
                .ExpectNext(4)
                .ExpectNext(5)
                //emitting with callback gives nondeterminism whether 6 or 7 will be pushed first
                .ExpectNextUnordered(6, 7)
                .ExpectNext(8)
                .ExpectComplete();
            }, Materializer);
        }
示例#16
0
        public void A_Flow_using_Join_must_allow_for_cycles()
        {
            this.AssertAllStagesStopped(() =>
            {
                const int end = 47;
                var t         = Enumerable.Range(0, end + 1).GroupBy(i => i % 2 == 0).ToList();
                var even      = t.First(x => x.Key).ToList();
                var odd       = t.First(x => !x.Key).ToList();
                var source    = Source.From(Enumerable.Range(0, end + 1));
                var result    = even.Concat(odd).Concat(odd.Select(x => x * 10));
                var probe     = this.CreateManualSubscriberProbe <IEnumerable <int> >();

                var flow1 = Flow.FromGraph(GraphDsl.Create(b =>
                {
                    var merge     = b.Add(new Merge <int>(2));
                    var broadcast = b.Add(new Broadcast <int>(2));
                    b.From(source).To(merge.In(0));
                    b.From(merge.Out).To(broadcast.In);
                    b.From(broadcast.Out(0))
                    .Via(Flow.Create <int>().Grouped(1000))
                    .To(Sink.FromSubscriber(probe));
                    return(new FlowShape <int, int>(merge.In(1), broadcast.Out(1)));
                }));

                var flow2 =
                    Flow.Create <int>()
                    .Where(x => x % 2 == 1)
                    .Select(x => x * 10)
                    .Buffer((end + 1) / 2, OverflowStrategy.Backpressure)
                    .Take((end + 1) / 2);

                flow1.Join(flow2).Run(Materializer);

                var sub = probe.ExpectSubscription();
                sub.Request(1);
                probe.ExpectNext().ShouldAllBeEquivalentTo(result);
                sub.Cancel();
            }, Materializer);
        }
示例#17
0
        public void Flow_should_append_Flow()
        {
            var     open1    = Flow.Create <int>().Select(x => x.ToString());
            var     open2    = Flow.Create <string>().Select(x => x.GetHashCode());
            dynamic open3    = open1.Via(open2);
            Action  compiler = () => open3.Run(Materializer);

            compiler.ShouldThrow <RuntimeBinderException>();

            dynamic closedSource = IntSeq.Via(open3);

            compiler = () => closedSource.Run(Materializer);
            compiler.ShouldThrow <RuntimeBinderException>();

            dynamic closedSink = open3.To(Sink.AsPublisher <int>(false));

            compiler = () => closedSink.Run(Materializer);
            compiler.ShouldThrow <RuntimeBinderException>();

            closedSource.To(Sink.AsPublisher <int>(false)).Run(Materializer);
            IntSeq.To(closedSink).Run(Materializer);
        }
示例#18
0
        public void Tcp_listen_stream_must_not_shut_down_connections_after_the_connection_stream_cacelled()
        {
            this.AssertAllStagesStopped(() =>
            {
                var serverAddress = TestUtils.TemporaryServerAddress();
                Sys.TcpStream()
                .Bind(serverAddress.Address.ToString(), serverAddress.Port)
                .Take(1).RunForeach(c =>
                {
                    Thread.Sleep(1000);
                    c.Flow.Join(Flow.Create <ByteString>()).Run(Materializer);
                }, Materializer);

                var total = Source.From(
                    Enumerable.Range(0, 1000).Select(_ => ByteString.Create(new byte[] { 0 })))
                            .Via(Sys.TcpStream().OutgoingConnection(serverAddress))
                            .RunAggregate(0, (i, s) => i + s.Count, Materializer);

                total.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue();
                total.Result.Should().Be(1000);
            }, Materializer);
        }
示例#19
0
        public void FlowGraphs_when_turned_into_sinks_should_be_transformable_with_a_Pipe()
        {
            var probe = TestSubscriber.CreateManualProbe <int>(this);

            var sink =
                Sink.FromGraph(GraphDsl.Create(PartialGraph(), Flow.Create <string>().Select(int.Parse), Keep.Both,
                                               (b, partial, flow) =>
            {
                var s = Sink.FromSubscriber(probe)
                        .MapMaterializedValue(_ => Tuple.Create(NotUsed.Instance, NotUsed.Instance));

                b.From(flow.Outlet).To(partial.Inlet);
                b.From(partial.Outlet).Via(Flow.Create <string>().Select(int.Parse)).To(s);
                return(new SinkShape <string>(flow.Inlet));
            }));

            var iSink = Flow.Create <int>().Select(i => i.ToString()).To(sink);

            Source1.To(iSink).Run(Materializer);

            ValidateProbe(probe, StandardRequests, StandardResult);
        }
示例#20
0
        private void Execute(ActorMaterializer actorMaterializer, int numberOfSelectOps, bool useGraphStageIdentity)
        {
            var syncTestPublisher = new SyncTestPublisher();

            var flow = MakeSelects(Source.FromPublisher(syncTestPublisher), numberOfSelectOps, () =>
            {
                if (useGraphStageIdentity)
                {
                    return(GraphStages.Identity <int>());
                }
                return(Flow.Create <int>().Select(x => x));
            });

            var l = new AtomicBoolean();

            flow.RunWith(Sink.OnComplete <int>(() => l.Value = true, _ => { }), actorMaterializer);

            while (!l.Value)
            {
                Thread.Sleep(10);
            }
        }
示例#21
0
        public void PreferredMerge_must_eventually_pas_through_all_elements()
        {
            Func <int, int, Source <int, Task <IEnumerable <int> > > > source = (from, count) =>
                                                                                Source.From(Enumerable.Range(from, count))
                                                                                .MapMaterializedValue <Task <IEnumerable <int> > >(_ => null);

            var result = RunnableGraph.FromGraph(GraphDsl.Create(Sink.First <IEnumerable <int> >(), (b, sink) =>
            {
                var merge = b.Add(new MergePreferred <int>(3));

                b.From(source(1, 100)).To(merge.Preferred);
                b.From(merge.Out).Via(Flow.Create <int>().Grouped(500)).To(sink.Inlet);
                b.From(source(101, 100)).To(merge.In(0));
                b.From(source(201, 100)).To(merge.In(1));
                b.From(source(301, 100)).To(merge.In(2));

                return(ClosedShape.Instance);
            })).Run(Materializer);

            result.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue();
            result.Result.ShouldAllBeEquivalentTo(Enumerable.Range(1, 400));
        }
示例#22
0
        public void A_restart_with_backoff_sink_should_reset_maxRestarts_when_sink_runs_for_at_least_minimum_backoff_without_completing()
        {
            this.AssertAllStagesStopped(() =>
            {
                var created           = new AtomicCounter(0);
                var(queue, sinkProbe) = this.SourceProbe <string>().ToMaterialized(this.SinkProbe <string>(), Keep.Both).Run(Materializer);
                var probe             = this.SourceProbe <string>()
                                        .ToMaterialized(RestartSink.WithBackoff(() =>
                {
                    created.IncrementAndGet();
                    return(Flow.Create <string>().TakeWhile(c => c != "cancel", inclusive: true).To(Sink.ForEach <string>(c => queue.SendNext(c))));
                }, _restartSettings.WithMaxRestarts(2, _minBackoff)), Keep.Left)
                                        .Run(Materializer);

                probe.SendNext("cancel");
                sinkProbe.RequestNext("cancel");
                // There should be a minBackoff delay
                probe.SendNext("cancel");
                sinkProbe.RequestNext("cancel");
                // The probe should now be backing off for 2 * minBackoff

                // Now wait for the 2 * minBackoff delay to pass, then it will start the new source, we also want to wait for the
                // subsequent minBackoff to pass, so it resets the restart count
                Thread.Sleep(_minBackoff + TimeSpan.FromTicks(_minBackoff.Ticks * 2) + _minBackoff + TimeSpan.FromMilliseconds(500));

                probe.SendNext("cancel");
                sinkProbe.RequestNext("cancel");

                // We now are able to trigger the third restart, since enough time has elapsed to reset the counter
                probe.SendNext("cancel");
                sinkProbe.RequestNext("cancel");

                created.Current.Should().Be(4);

                sinkProbe.Cancel();
                probe.SendComplete();
            }, Materializer);
        }
示例#23
0
        public void A_BidiFlow_must_combine_materialization_values()
        {
            this.AssertAllStagesStopped(() =>
            {
                var left = Flow.FromGraph(GraphDsl.Create(Sink.First <int>(), (b, sink) =>
                {
                    var broadcast = b.Add(new Broadcast <int>(2));
                    var merge     = b.Add(new Merge <int>(2));
                    var flow      = b.Add(Flow.Create <string>().Select(int.Parse));
                    b.From(broadcast).To(sink);
                    b.From(Source.Single(1).MapMaterializedValue(_ => Task.FromResult(0))).Via(broadcast).To(merge);
                    b.From(flow).To(merge);
                    return(new FlowShape <string, int>(flow.Inlet, merge.Out));
                }));

                var right = Flow.FromGraph(GraphDsl.Create(Sink.First <List <long> >(), (b, sink) =>
                {
                    var flow   = b.Add(Flow.Create <long>().Grouped(10));
                    var source = b.Add(Source.Single(ByteString.FromString("10")));
                    b.From(flow).To(sink);

                    return(new FlowShape <long, ByteString>(flow.Inlet, source.Outlet));
                }));

                var tt = left.JoinMaterialized(BidiMaterialized(), Keep.Both)
                         .JoinMaterialized(right, Keep.Both)
                         .Run(Materializer);
                var t = tt.Item1;
                var l = t.Item1;
                var m = t.Item2;
                var r = tt.Item2;

                Task.WhenAll(l, m, r).Wait(TimeSpan.FromSeconds(3)).Should().BeTrue();
                l.Result.Should().Be(1);
                m.Result.Should().Be(42);
                r.Result.ShouldAllBeEquivalentTo(new [] { 3L, 12L });
            }, Materializer);
        }
示例#24
0
        public void A_Flow_using_Join_must_allow_for_merge_cycle()
        {
            this.AssertAllStagesStopped(() =>
            {
                var source =
                    Source.Single("lonely traveler").MapMaterializedValue(_ => Task.FromResult(""));

                var flow1 = Flow.FromGraph(GraphDsl.Create(Sink.First <string>(), (b, sink) =>
                {
                    var merge     = b.Add(new Merge <string>(2));
                    var broadcast = b.Add(new Broadcast <string>(2, true));

                    b.From(source).To(merge.In(0));
                    b.From(merge.Out).To(broadcast.In);
                    b.From(broadcast.Out(0)).To(sink);
                    return(new FlowShape <string, string>(merge.In(1), broadcast.Out(1)));
                }));

                var t = flow1.Join(Flow.Create <string>()).Run(Materializer);
                t.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue();
                t.Result.Should().Be("lonely traveler");
            }, Materializer);
        }
示例#25
0
        public void A_BidiFlow_must_materialize_its_value()
        {
            var f = RunnableGraph.FromGraph(GraphDsl.Create(BidiMaterialized(), (b, bidi) =>
            {
                var flow1 = b.Add(Flow.Create <string>().Select(int.Parse).MapMaterializedValue(_ => Task.FromResult(0)));
                var flow2 =
                    b.Add(
                        Flow.Create <long>()
                        .Select(x => ByteString.FromString($"Hello {x}"))
                        .MapMaterializedValue(_ => Task.FromResult(0)));

                b.AddEdge(flow1.Outlet, bidi.Inlet1);
                b.AddEdge(bidi.Outlet2, flow1.Inlet);

                b.AddEdge(bidi.Outlet1, flow2.Inlet);
                b.AddEdge(flow2.Outlet, bidi.Inlet2);

                return(ClosedShape.Instance);
            })).Run(Materializer);

            f.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue();
            f.Result.Should().Be(42);
        }
示例#26
0
        public void Simple_server_connection_must_handle_connection()
        {
            #region echo-server-simple-handle
            Source <Tcp.IncomingConnection, Task <Tcp.ServerBinding> > connections =
                Sys.TcpStream().Bind("127.0.0.1", 8888);

            connections.RunForeach(connection =>
            {
                Console.WriteLine($"New connection from: {connection.RemoteAddress}");

                var echo = Flow.Create <ByteString>()
                           .Via(Framing.Delimiter(
                                    ByteString.FromString("\n"),
                                    maximumFrameLength: 256,
                                    allowTruncation: true))
                           .Select(c => c.ToString())
                           .Select(c => c + "!!!\n")
                           .Select(ByteString.FromString);

                connection.HandleWith(echo, Materializer);
            }, Materializer);
            #endregion
        }
示例#27
0
        public void A_Flow_must_materialize_into_Publisher_Subscriber()
        {
            var flow    = Flow.Create <string>();
            var t       = MaterializeIntoSubscriberAndPublisher(flow, Materializer);
            var flowIn  = t.Item1;
            var flowOut = t.Item2;

            var c1 = this.CreateManualSubscriberProbe <string>();

            flowOut.Subscribe(c1);

            var source = Source.From(new[] { "1", "2", "3" }).RunWith(Sink.AsPublisher <string>(false), Materializer);

            source.Subscribe(flowIn);

            var sub1 = c1.ExpectSubscription();

            sub1.Request(3);
            c1.ExpectNext("1");
            c1.ExpectNext("2");
            c1.ExpectNext("3");
            c1.ExpectComplete();
        }
示例#28
0
        public void Timed_Flow_must_measure_time_it_takes_between_elements_matching_a_predicate()
        {
            this.AssertAllStagesStopped(() =>
            {
                var probe = CreateTestProbe();

                var flow =
                    Flow.Create <int>().Select(x => (long)x).TimedIntervalBetween(i => i % 2 == 1, d => probe.Tell(d));

                var c1 = this.CreateManualSubscriberProbe <long>();
                Source.From(Enumerable.Range(1, 3)).Via(flow).RunWith(Sink.FromSubscriber(c1), Materializer);

                var s = c1.ExpectSubscription();
                s.Request(100);
                c1.ExpectNext(1L);
                c1.ExpectNext(2L);
                c1.ExpectNext(3L);
                c1.ExpectComplete();

                var duration = probe.ExpectMsg <TimeSpan>();
                _helper.WriteLine($"Got duration (first): {duration}");
            }, Materializer);
        }
示例#29
0
        public void A_Graph_should_build_unzip_zip()
        {
            RunnableGraph.FromGraph(GraphDsl.Create(b =>
            {
                var zip    = b.Add(new Zip <int, string>());
                var unzip  = b.Add(new UnZip <int, string>());
                var sink   = Sink.AsPublisher <Tuple <int, string> >(false).MapMaterializedValue(_ => NotUsed.Instance);
                var source =
                    Source.From(new[]
                {
                    new KeyValuePair <int, string>(1, "a"), new KeyValuePair <int, string>(2, "b"),
                    new KeyValuePair <int, string>(3, "c")
                });


                b.From(source).To(unzip.In);
                b.From(unzip.Out0).Via(Flow.Create <int>().Select(x => x * 2)).To(zip.In0);
                b.From(unzip.Out1).To(zip.In1);
                b.From(zip.Out).To(sink);

                return(ClosedShape.Instance);
            })).Run(Materializer);
        }
示例#30
0
        public void PreferredMerge_must_prefer_selected_input_more_than_others()
        {
            const int numElements = 10000;
            var       preferred   =
                Source.From(Enumerable.Range(1, numElements).Select(_ => 1))
                .MapMaterializedValue <Task <IEnumerable <int> > >(_ => null);
            var aux = Source.From(Enumerable.Range(1, numElements).Select(_ => 2))
                      .MapMaterializedValue <Task <IEnumerable <int> > >(_ => null);

            var result = RunnableGraph.FromGraph(GraphDsl.Create(Sink.First <IEnumerable <int> >(), (b, sink) =>
            {
                var merge = b.Add(new MergePreferred <int>(3));
                b.From(preferred).To(merge.Preferred);
                b.From(merge.Out).Via(Flow.Create <int>().Grouped(numElements * 2)).To(sink.Inlet);
                b.From(aux).To(merge.In(0));
                b.From(aux).To(merge.In(1));
                b.From(aux).To(merge.In(2));
                return(ClosedShape.Instance);
            })).Run(Materializer);

            result.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue();
            result.Result.Count(x => x == 1).Should().Be(numElements);
        }