public async Task PlainPartitionedSource_Should_split_messages_by_partitions() { var topic = CreateTopic(1); var group = CreateGroup(1); var totalMessages = 100; var consumerSettings = CreateConsumerSettings <string>(group); var control = KafkaConsumer.PlainPartitionedSource(consumerSettings, Subscriptions.Topics(topic)) .SelectAsync(6, async tuple => { var(topicPartition, source) = tuple; Log.Info($"Sub-source for {topicPartition}"); var consumedPartitions = await source .Select(m => m.TopicPartition.Partition) .RunWith(Sink.Seq <Partition>(), Materializer); // Return flag that all messages in child source are from the same, expected partition return(consumedPartitions.All(partition => partition == topicPartition.Partition)); }) .As <Source <bool, IControl> >() .ToMaterialized(Sink.Aggregate <bool, bool>(true, (result, childSourceIsValid) => result && childSourceIsValid), Keep.Both) .MapMaterializedValue(tuple => DrainingControl <bool> .Create(tuple.Item1, tuple.Item2)) .Run(Materializer); await ProduceStrings(topic, Enumerable.Range(1, totalMessages), ProducerSettings); // Give it some time to consume all messages await Task.Delay(5000); var shutdown = control.DrainAndShutdown(); AwaitCondition(() => shutdown.IsCompleted, TimeSpan.FromSeconds(10)); shutdown.Result.Should().BeTrue(); }
public void A_Balance_must_balance_between_all_three_outputs() { this.AssertAllStagesStopped(() => { const int numElementsForSink = 10000; var outputs = Sink.Aggregate <int, int>(0, (sum, i) => sum + i); var t = RunnableGraph.FromGraph(GraphDsl.Create(outputs, outputs, outputs, Tuple.Create, (b, o1, o2, o3) => { var balance = b.Add(new Balance <int>(3, true)); var source = Source.Repeat(1) .Take(numElementsForSink * 3) .MapMaterializedValue <Tuple <Task <int>, Task <int>, Task <int> > >(_ => null); b.From(source).To(balance.In); b.From(balance.Out(0)).To(o1); b.From(balance.Out(1)).To(o2); b.From(balance.Out(2)).To(o3); return(ClosedShape.Instance); })).Run(Materializer); var task = Task.WhenAll(t.Item1, t.Item2, t.Item3); task.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue(); task.Result.Should().NotContain(0); task.Result.Sum().Should().Be(numElementsForSink * 3); }, Materializer); }
public void Outgoing_TCP_stream_must_properly_full_close_if_requested() { this.AssertAllStagesStopped(() => { var serverAddress = TestUtils.TemporaryServerAddress(); var writeButIgnoreRead = Flow.FromSinkAndSource(Sink.Ignore <ByteString>(), Source.Single(ByteString.FromString("Early response")), Keep.Right); var task = Sys.TcpStream() .Bind(serverAddress.Address.ToString(), serverAddress.Port, halfClose: false) .ToMaterialized( Sink.ForEach <Tcp.IncomingConnection>(conn => conn.Flow.Join(writeButIgnoreRead).Run(Materializer)), Keep.Left) .Run(Materializer); var binding = task.Result; var t = Source.Maybe <ByteString>() .Via(Sys.TcpStream().OutgoingConnection(serverAddress.Address.ToString(), serverAddress.Port)) .ToMaterialized(Sink.Aggregate <ByteString, ByteString>(ByteString.Empty, (s, s1) => s + s1), Keep.Both) .Run(Materializer); var promise = t.Item1; var result = t.Item2; result.Wait(TimeSpan.FromSeconds(5)).Should().BeTrue(); result.Result.ShouldBeEquivalentTo(ByteString.FromString("Early response")); promise.SetResult(null); // close client upstream, no more data binding.Unbind(); }, Materializer); }
//[Fact] public void BroadcastSource() { var countItems = Sink.Aggregate <int, int>(0, (agg, i) => agg + 1); var sumItems = Sink.Aggregate <int, int>(0, (agg, i) => agg + i); using (var system = ActorSystem.Create("system")) using (var materializer = system.Materializer()) { var items = new List <int> { 1, 2, 3 }; var g = GraphDsl.Create(countItems, sumItems, Keep.Both, (b, ci, si) => { var broadcast = b.Add(new Broadcast <int>(2)); var source = Source.From(items); //b.From(source).To(broadcast.In); b.From(broadcast.Out(0)) .To(countItems); b.From(broadcast.Out(1)) .Via(Flow.Create <int>().Select(it => it * 2)) .To(sumItems); return(ClosedShape.Instance); }); var rg = RunnableGraph.FromGraph(g); rg.Run(materializer); } }
private static void TestAsync() { Console.WriteLine("Start"); WithMaterializer(materializer => { Console.WriteLine( Source.From(Enumerable.Range(1, 100)) .Select(i => { Console.WriteLine($"A: {i}"); return(i); }) .Async() .Select(i => { Console.WriteLine($"B: {i}"); return(i); }) .Async() .Select(i => { Console.WriteLine($"C: {i}"); return(i); }) .Async() .RunWith(Sink.Aggregate <int, int>(0, (acc, i) => acc + i), materializer) .Result); Task.Delay(100).Wait(); }); }
private static void TestDifferentWaysToCreateSource() { var s0 = Source.From(Enumerable.Range(1, 10)); WithMaterializer(m => s0.RunForeach(Console.WriteLine, m).Wait()); var s1 = Source.FromTask(Task.FromResult(1)); WithMaterializer(m => s1.RunForeach(Console.WriteLine, m).Wait()); var s2 = Source.Single(2); WithMaterializer(m => s2.RunForeach(Console.WriteLine, m).Wait()); var s3 = Source.Empty <int>(); WithMaterializer(m => s3.RunForeach(Console.WriteLine, m).Wait()); WithMaterializer(m => Sink.First <int>().RunWith(s0, m)); var sink = Sink.Aggregate <int, int>(0, (sum, i) => sum + i); var res = WithMaterializer(m => s0.ToMaterialized(sink, Keep.Right).Run(m)).Result; Console.WriteLine(res); var sink2 = Sink.First <int>(); Console.WriteLine(WithMaterializer(m => s0.ToMaterialized(sink2, Keep.Right).Run(m)).Result); }
public void ShouldCreateSimpleClosedGraph() { var sink = Sink.Aggregate <int, int>(0, (acc, i) => acc + i); var g = RunnableGraph.FromGraph(GraphDsl.Create(sink, (b, s) => { var source = Source.From(Enumerable.Repeat(1, 100)).MapMaterializedValue <Task <int> >(_ => null); var broadcast = b.Add(new Broadcast <int>(2)); var merge = b.Add(new Merge <int>(2)); var f1 = Flow.Create <int>().Select(x => x + 1); var f2 = Flow.Create <int>().Select(x => x + 1); var f3 = Flow.Create <int>().Select(x => x + 1); var f4 = Flow.Create <int>().Select(x => x + 1); b.From(source).Via(f1).Via(broadcast).Via(f2).Via(merge).Via(f3).To(s); b.From(broadcast.Out(1)).Via(f4).To(merge); return(ClosedShape.Instance); })); var res = WithMaterializer(g.Run).Result; Assert.That(res, Is.EqualTo(800)); }
public void MaterializedValues() { // Materializes to TaskCompletionSource<int> (red) var source = Source.Maybe <int>(); // Materializes to NotUsed (black) var flow = Flow.Create <int>().Take(100); // Materializes to TaskCompletionSource<int> (red) var nestedSource = source.ViaMaterialized(flow, Keep.Left).Named("nestedSource"); // Materializes to NotUsed (orange) var flow1 = Flow.Create <int>().Select(x => ByteString.FromString(x.ToString())); // Materializes to Task<OutgoingConnection> (yellow) var flow2 = Sys.TcpStream().OutgoingConnection("localhost", 8080); // Materializes to Task<OutgoingConnection> (yellow) var nestedFlow = flow1.ViaMaterialized(flow2, Keep.Right).Named("nestedFlow"); // Materializes to Task<String> (green) var sink = Sink.Aggregate <ByteString, string>("", (agg, s) => agg + s.DecodeString()); // Materializes to (Task<OutgoingConnection>, Task<String>) (blue) var nestedSink = nestedFlow.ToMaterialized(sink, Keep.Both); // Materializes to Task<MyClass> (purple) var runnableGraph = nestedSource.ToMaterialized(nestedSink, (completion, rest) => { var connectionTask = rest.Item1; return(connectionTask.ContinueWith(task => new MyClass(completion, task.Result))); }); }
public void A_SubscriberSource_must_be_able_to_use_Subscribe_in_materialized_value_transformation() { var f = Source.AsSubscriber <int>() .MapMaterializedValue( s => Source.From(Enumerable.Range(1, 3)).RunWith(Sink.FromSubscriber(s), Materializer)) .RunWith(Sink.Aggregate <int, int>(0, (sum, i) => sum + i), Materializer); f.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue(); f.Result.Should().Be(6); }
public async Task PlainPartitionedSource_should_not_leave_gaps_when_subsource_failes() { var topic = CreateTopic(1); var group = CreateGroup(1); var totalMessages = 105; await ProduceStrings(topic, Enumerable.Range(1, totalMessages), ProducerSettings); var(queue, accumulatorTask) = Source.Queue <long>(8, OverflowStrategy.Backpressure) .Scan(0, (c, _) => c + 1) .TakeWhile(val => val < totalMessages) .ToMaterialized(Sink.Aggregate <int, int>(0, (c, _) => c + 1), Keep.Both) .Run(Materializer); var(killSwitch, consumerCompletion) = KafkaConsumer.PlainPartitionedSource(CreateConsumerSettings <string>(group), Subscriptions.Topics(topic)) .Log(topic, m => $"Consuming topic partition {m.Item1}") .ViaMaterialized(KillSwitches.Single <(TopicPartition, Source <ConsumeResult <Null, string>, NotUsed>)>(), Keep.Both) .ToMaterialized(Sink.ForEach <(TopicPartition, Source <ConsumeResult <Null, string>, NotUsed>)>(tuple => { var(topicPartition, source) = tuple; source .Log(topicPartition.ToString(), m => $"Consumed offset {m.Offset} (value: {m.Value})") .SelectAsync(1, async message => { await queue.OfferAsync(message.Offset); var value = int.Parse(message.Value); if (value % 10 == 0) { Log.Debug("Reached message to fail: {0}", value); throw new Exception("Stopping subsource"); } return(value); }) .Select(value => { if (value % 10 == 0) { Log.Debug("Reached message to fail: {0}", value); throw new Exception("Stopping subsource"); } return(value); }) .RunWith(Sink.Ignore <int>(), Materializer); }), Keep.Both) .Run(Materializer); AwaitCondition(() => accumulatorTask.IsCompleted, TimeSpan.FromSeconds(10)); accumulatorTask.Result.Should().Be(totalMessages); killSwitch.Item2.Shutdown(); AwaitCondition(() => consumerCompletion.IsCompleted, TimeSpan.FromSeconds(10)); }
public void CombiningSourcesWithSimplifiedApi() { var sourceOne = Source.Single(1); var sourceTwo = Source.Single(2); var merged = Source.Combine(sourceOne, sourceTwo, i => new Merge <int, int>(i)); var mergedResult = WithMaterializer(m => merged.RunWith(Sink.Aggregate <int, int>(0, (agg, i) => agg + i), m)); Assert.That(mergedResult.Result, Is.EqualTo(3)); }
private static void Test5() { var source = Source.From(Enumerable.Range(1, 10)); var sink = Sink.Aggregate <int, int>(0, (agg, i) => agg + i); var runnable = source.ToMaterialized(sink, Keep.Right); var x = WithMaterializer(runnable.Run).Result; Console.WriteLine(x); }
public void A_Log_on_Source_must_follow_supervision_strategy_when_Exception_thrown() { var ex = new TestException("test"); var future = Source.From(Enumerable.Range(1, 5)) .Log("hi", n => { throw ex; }) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Deciders.ResumingDecider)) .RunWith(Sink.Aggregate <int, int>(0, (i, i1) => i + i1), Materializer); future.Wait(TimeSpan.FromMilliseconds(500)).Should().BeTrue(); future.Result.Should().Be(0); }
public void A_LazySink_must_complete_when_there_was_no_elements_in_stream() { this.AssertAllStagesStopped(() => { var lazySink = Sink.LazySink((int _) => Task.FromResult(Sink.Aggregate(0, (int i, int i2) => i + i2)), () => Task.FromResult(0)); var taskProbe = Source.Empty <int>().RunWith(lazySink, Materializer); var taskResult = taskProbe.AwaitResult(RemainingOrDefault); taskResult.AwaitResult(RemainingOrDefault).ShouldBe(0); }, Materializer); }
public void FileSource_should_count_lines_in_a_real_file(int chunkSize, int readAhead) { var s = FileIO.FromFile(ManyLines(), chunkSize) .WithAttributes(Attributes.CreateInputBuffer(readAhead, readAhead)); var f = s.RunWith( Sink.Aggregate<ByteString, int>(0, (acc, l) => acc + l.DecodeString(Encoding.UTF8).Count(c => c == '\n')), _materializer); f.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue(); var lineCount = f.Result; lineCount.Should().Be(LinesCount); }
public void A_Sum_must_fail_on_Empty_stream_using_Flow_Sum() { this.AssertAllStagesStopped(() => { var result = Source.Empty <int>() .Via(SumFlow) .RunWith(Sink.Aggregate <int, int>(0, (i, i1) => i + i1), Materializer); result.Invoking(t => t.Wait(TimeSpan.FromSeconds(3))) .ShouldThrow <NoSuchElementException>() .And.Message.Should() .Contain("empty stream"); }, Materializer); }
public void A_Graph_with_materialized_value_must_work_also_when_the_sources_module_is_copied() { var foldFlow = Flow.FromGraph(GraphDsl.Create(Sink.Aggregate <int, int>(0, (sum, i) => sum + i), (b, fold) => { var o = b.From(b.MaterializedValue).Via(Flow.Create <Task <int> >().SelectAsync(4, x => x)); return(new FlowShape <int, int>(fold.Inlet, o.Out)); })); var t = Source.From(Enumerable.Range(1, 10)).Via(foldFlow).RunWith(Sink.First <int>(), Materializer); t.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue(); t.Result.Should().Be(55); }
public void A_LazySink_must_fail_task_when_zero_throws_exception() { this.AssertAllStagesStopped(() => { var lazySink = Sink.LazySink((int _) => Task.FromResult(Sink.Aggregate <int, int>(0, (i, i1) => i + i1)), () => { throw Ex; }); var taskProbe = Source.Empty <int>().RunWith(lazySink, Materializer); taskProbe.Invoking(t => t.Wait(TimeSpan.FromMilliseconds(300))).ShouldThrow <TestException>(); }, Materializer); }
public void A_stream_via_LastElement_should_materialize_to_the_last_element_emitted_by_a_source_before_it_failed() { var t = Source.UnfoldInfinite(1, n => n >= 3 ? throw new Exception() : (n + 1, n + 1)) .ViaMaterialized(new LastElement <int>(), Keep.Right) .ToMaterialized(Sink.Aggregate <int, Option <int> >(Option <int> .None, (_, o) => new Option <int>(o)), Keep.Both) .Run(Sys.Materializer()); var lastElement = t.Item1; var lastEmitted = t.Item2; lastElement.Wait(TimeSpan.FromSeconds(1)).Should().BeTrue(); lastEmitted.Wait(TimeSpan.FromSeconds(1)).Should().BeTrue(); lastElement.Result.Should().Be(lastEmitted.Result); }
static Task <int> Stream() { // 1秒ごとに下流に各要素を放出する Source Source <int, NotUsed> source = Source.From(Enumerable.Range(1, 100)); // 上流から流れてきた要素を足し合わせる Sink Sink <int, Task <int> > sink = Sink.Aggregate <int, int>(0, (l, r) => l + r); // Stream を正常(もしくはキャンセル扱いで)に停止させるための KillSwitch Flow <int, int, UniqueKillSwitch> killSwitch = Flow.Create <int>().ViaMaterialized(KillSwitches.Single <int>(), Keep.Right); // Stream(の特定の部分)を通過する要素の流量を制御するための Throttle Flow <int, int, NotUsed> throttle = Flow.Create <int>().Throttle(1, TimeSpan.FromSeconds(1), 1, ThrottleMode.Shaping); // Stream を動作させる Actor をホストする ActorSystem ActorSystem system = ActorSystem.Create("akkanet"); // ActorSystem を使用して Stream をマテリアル化するマテリアライザ ActorMaterializer materializer = ActorMaterializer.Create(system); // Source、Sink、Throttle、KillSwitch を使用して RunnableGraph(実行可能なグラフ)を組み立てる IRunnableGraph <Tuple <UniqueKillSwitch, Task <int> > > runnable = source .Via(throttle) .ViaMaterialized(killSwitch, Keep.Right) .ToMaterialized(sink, Keep.Both); // RunnableGraph をマテリアライズして Stream を作動させる var(ks, mat) = runnable.Run(materializer); // 10秒後に KillSwitch を使用して Stream を途中で停止させる(完了扱い) ICancelable canceller = materializer.ScheduleOnce(TimeSpan.FromSeconds(10), () => { Console.WriteLine("Stream is cancelled"); ks.Shutdown(); }); // Stream 完了後に ActorSystem と ActorMaterializer を破棄する return(mat.ContinueWith(prev => { canceller.Cancel(); materializer.Dispose(); system.Dispose(); return prev.Result; })); }
public void CombiningSinksWithSimplifiedApi() { var actor = CreateTestProbe(); var sendRemotely = Sink.ActorRef <int>(actor.Ref, "Done"); var localProcessing = Sink.Aggregate <int, int>(0, (acc, i) => acc + i) .MapMaterializedValue(_ => NotUsed.Instance); var sink = Sink.Combine(i => new Broadcast <int>(i), sendRemotely, localProcessing); WithMaterializer(m => { Source.From(new[] { 0, 1, 2 }).RunWith(sink, m); var received = actor.ReceiveN(3); Assert.That(received, Is.EquivalentTo(new[] { 0, 1, 2 })); }); }
public void Maybe_Source_must_allow_external_triggering_of_empty_completion() { this.AssertAllStagesStopped(() => { var neverSource = Source.Maybe <int>().Where(_ => false); var counterSink = Sink.Aggregate <int, int>(0, (acc, _) => acc + 1); var t = neverSource.ToMaterialized(counterSink, Keep.Both).Run(Materializer); var neverPromise = t.Item1; var counterFuture = t.Item2; //external cancellation neverPromise.TrySetResult(0).Should().BeTrue(); counterFuture.AwaitResult().Should().Be(0); }, Materializer); }
public void GraphDSLs_Partial_must_be_able_to_build_and_reuse_complex_materializing_partial_graphs() { var summer = Sink.Aggregate <int, int>(0, (i, i1) => i + i1); var doubler = GraphDsl.Create(summer, summer, Tuple.Create, (b, s1, s2) => { var broadcast = b.Add(new Broadcast <int>(3)); var broadcast2 = b.Add(new Broadcast <int>(2)); var zip = b.Add(ZipWith.Apply((int i, int i1) => i + i1)); b.From(broadcast.Out(0)).To(zip.In0); b.From(broadcast.Out(1)).To(zip.In1); b.From(broadcast.Out(2)).To(s1.Inlet); b.From(zip.Out).To(broadcast2.In); b.From(broadcast2.Out(0)).To(s2.Inlet); return(new FlowShape <int, int>(broadcast.In, broadcast2.Out(1))); }); var t = RunnableGraph.FromGraph(GraphDsl.Create(doubler, doubler, Sink.First <IEnumerable <int> >(), Tuple.Create, (b, d1, d2, sink) => { var source = Source.From(Enumerable.Range(1, 3)) .MapMaterializedValue <Tuple <Tuple <Task <int>, Task <int> >, Tuple <Task <int>, Task <int> >, Task <IEnumerable <int> > > >(_ => null); b.From(source).To(d1.Inlet); b.From(d1.Outlet).To(d2.Inlet); b.From(d2.Outlet).Via(Flow.Create <int>().Grouped(100)).To(sink.Inlet); return(ClosedShape.Instance); })).Run(Materializer); var task = Task.WhenAll(t.Item1.Item1, t.Item1.Item2, t.Item2.Item1, t.Item2.Item2); task.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue(); task.Result.ShouldAllBeEquivalentTo(new[] { 6, 12, 12, 24 }); t.Item3.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue(); t.Item3.Result.ShouldAllBeEquivalentTo(new [] { 4, 8, 12 }); }
public void A_Aggregate_must_resume_and_reset_the_state_when_the_aggregating_funtion_throws_and_the_supervisor_strategy_decides_to_restart() { this.AssertAllStagesStopped(() => { var error = new Exception("boom"); var aggregate = Sink.Aggregate(0, (int x, int y) => { if (y == 50) { throw error; } return(x + y); }); var task = InputSource.RunWith( aggregate.WithAttributes(ActorAttributes.CreateSupervisionStrategy(Deciders.RestartingDecider)), Materializer); task.AwaitResult().Should().Be(Enumerable.Range(51, 50).Sum()); }, 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 override ISubscriber <int?> CreateSubscriber() => Flow.Create <int?>() .To(Sink.Aggregate <int?, int?>(0, (agg, i) => agg + i)) .RunWith(Source.AsSubscriber <int?>(), Materializer);
private async Task <ProcessingResult> StartProcessingAsync() { this.DistributionSw.Reset(); this.TotalSw.Reset(); await this.WaitForLoadbalancerUpStateTCS.Task.ConfigureAwait(false); var reassemblerNodes = this.Cluster.State.Members .Where(member => member.HasRole(CaptureControllerActor.ReassemblerClusterRoleName) && member.Status == MemberStatus.Up).ToList(); if (!reassemblerNodes.Any()) { this.Log.Error("No Up reassemblers"); return(new ProcessingResult { Success = false, }); } this.MaxNumberOfShards = reassemblerNodes.Count * this.Settings.ShardsPerEntity; this.Log.Info($"{reassemblerNodes.Count} Up reassemblers: [{String.Join(", ", reassemblerNodes.Select(member => member.Address.ToString()))}]"); var packetSource = this.CreatePacketSource(this.CaptureInfo.Uri); var pipeline = this.CreatePipeline(packetSource, reassemblerNodes.Count); if (pipeline == null) { throw new Exception("Failed to initialize the pipeline"); } var materializerSettings = ActorMaterializerSettings.Create(Context.System).WithInputBuffer(1024, 1024); UInt64 processedPackets; using (var materializer = Context.System.Materializer(materializerSettings)) { this.TotalSw.Start(); processedPackets = await pipeline.RunWith(Sink.Aggregate <UInt64, UInt64>(0, (sum, n) => sum + n), materializer) .ConfigureAwait(false); } var distributionTime = this.DistributionSw.Elapsed; this.Log.Info("Finalizing ..."); await this.SendCaptureTrackingCompleteToReassemblersAsync().ConfigureAwait(false); var totalTime = this.TotalSw.Elapsed; this.Log.Info("Leaving cluster ..."); await this.Cluster.LeaveAsync().ConfigureAwait(false); return(new ProcessingResult { Success = true, ProcessedPackets = processedPackets, DistributionTime = distributionTime, TotalTime = totalTime, CaptureSize = this.PcapLoader.CaptureSize }); }