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); }
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)); }
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); })); }
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); }
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);
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); }
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); }
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)); }
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); }
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); }
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); }
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); }
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(); } }
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); }
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); }
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); }
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); }
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); }
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); } }
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)); }
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); }
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); }
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); }
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); }
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 }
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(); }
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); }
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); }
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); }