Esempio n. 1
0
        public void RetryConcat_tolerate_killswitch_terminations_inside_the_flow_after_start()
        {
            var innerFlow = RetryFlow <int>().ViaMaterialized(KillSwitches.Single <Tuple <Result <int>, int> >(), Keep.Right);

            var t = this.SourceProbe <int>()
                    .Select(i => Tuple.Create(i, i * i))
                    .ViaMaterialized(Retry.Concat(100, innerFlow, x =>
            {
                if (x % 4 == 0)
                {
                    return new[] { Tuple.Create(x / 2, x / 4) }
                }
                ;
                var sqrt = (int)Math.Sqrt(x);
                return(new[] { Tuple.Create(sqrt, x) });
            }), Keep.Both)
                    .ToMaterialized(this.SinkProbe <Tuple <Result <int>, int> >(), Keep.Both)
                    .Run(Sys.Materializer());

            var source     = t.Item1.Item1;
            var killSwitch = t.Item1.Item2;
            var sink       = t.Item2;

            sink.Request(99);
            source.SendNext(1);
            sink.ExpectNext().Item1.Value.Should().Be(2);
            source.SendNext(2);
            sink.ExpectNext().Item1.Value.Should().Be(2);
            killSwitch.Abort(FailedElement.Exception);
            sink.ExpectError().InnerException.Should().Be(FailedElement.Exception);
        }
Esempio n. 2
0
        public void Restart_stages_should_demonstrate_a_restart_with_backoff_source()
        {
            #region restart-with-backoff-source
            var httpClient = new HttpClient();

            var restartSource = RestartSource.WithBackoff(() =>
            {
                // Create a source from a task
                return(Source.FromTask(
                           httpClient.GetAsync("http://example.com/eventstream") // Make a single request
                           )
                       .Select(c => c.Content.ReadAsStringAsync())
                       .Select(c => c.Result));
            },
                                                          minBackoff: TimeSpan.FromSeconds(3),
                                                          maxBackoff: TimeSpan.FromSeconds(30),
                                                          randomFactor: 0.2 // adds 20% "noise" to vary the intervals slightly
                                                          );
            #endregion

            #region with-kill-switch
            var killSwitch = restartSource
                             .ViaMaterialized(KillSwitches.Single <string>(), Keep.Right)
                             .ToMaterialized(Sink.ForEach <string>(evt => Console.WriteLine($"Got event: {evt}")), Keep.Left)
                             .Run(Materializer);

            DoSomethingElse();

            killSwitch.Shutdown();
            #endregion
        }
Esempio n. 3
0
        public void A_SharedKillSwitch_must_allow_using_multiple_KillSwitch_in_one_graph()
        {
            this.AssertAllStagesStopped(() =>
            {
                var killSwitch1 = KillSwitches.Shared("switch");
                var killSwitch2 = KillSwitches.Shared("switch");

                var downstream = RunnableGraph.FromGraph(GraphDsl.Create(this.SinkProbe <int>(), (b, sink) =>
                {
                    var merge   = b.Add(new Merge <int>(2));
                    var source1 = b.Add(Source.Maybe <int>().Via(killSwitch1.Flow <int>()));
                    var source2 = b.Add(Source.Maybe <int>().Via(killSwitch2.Flow <int>()));

                    b.From(source1).Via(merge).To(sink);
                    b.From(source2).To(merge);

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

                downstream.EnsureSubscription();
                downstream.ExpectNoMsg(TimeSpan.FromMilliseconds(100));

                killSwitch1.Shutdown();
                downstream.ExpectNoMsg(TimeSpan.FromMilliseconds(100));

                killSwitch2.Shutdown();
                downstream.ExpectComplete();
            }, Materializer);
        }
Esempio n. 4
0
        public void Shared_kill_switch_must_control_graph_completion_with_shutdown()
        {
            #region shared-shutdown
            var countingSrc      = Source.From(Enumerable.Range(1, int.MaxValue)).Delay(1.Seconds(), DelayOverflowStrategy.Backpressure);
            var lastSink         = Sink.Last <int>();
            var sharedKillSwitch = KillSwitches.Shared("my-kill-switch");

            var last = countingSrc
                       .Via(sharedKillSwitch.Flow <int>())
                       .RunWith(lastSink, Materializer);

            var delayedLast = countingSrc
                              .Delay(1.Seconds(), DelayOverflowStrategy.Backpressure)
                              .Via(sharedKillSwitch.Flow <int>())
                              .RunWith(lastSink, Materializer);

            DoSomethingElse();

            sharedKillSwitch.Shutdown();

            last.Wait(1.Seconds());
            last.Result.Should().Be(2);

            delayedLast.Wait(1.Seconds());
            delayedLast.Result.Should().Be(1);
            #endregion
        }
Esempio n. 5
0
        public async Task Given_journal_When_starting_projection_stream_Then_sink_receives_all_events()
        {
            await Init();

            _output.WriteLine(Sys.Settings.ToString());
            //generate some data
            var calculationActor = Sys.ActorOf(Props.Create <CalculatorActor>(), "CalculatorOne");

            calculationActor.Tell(new CalculatorActorProtocol.CalculateExpression("1+2-3"));
            calculationActor.Tell(new CalculatorActorProtocol.CalculateExpression("1-2*3"));
            calculationActor.Tell(new CalculatorActorProtocol.CalculateExpression("1/2+3"));

            var eventName = nameof(CalculatorActor.CalculationPerformed);

            var readJournal = PersistenceQuery.Get(Sys).ReadJournalFor <SqlReadJournal>(SqlReadJournal.Identifier);

            var sharedKillSwitch = KillSwitches.Shared("test");
            var source           = readJournal.EventsByTag(eventName, Offset.NoOffset())
                                   .Via(sharedKillSwitch.Flow <EventEnvelope>());

            var flow = FunctionTotalUsageFlow.Instance;
            var sink = Sink.Seq <SequencedFunctionTotalUsage>();

            var materializer = Sys.Materializer();
            var runTask      = source.RunWith(flow.ToMaterialized(sink, Keep.Right), materializer);

            await Task.Delay(5000);

            sharedKillSwitch.Shutdown();

            var res = await runTask;

            res.Should().HaveCount(6);
        }
Esempio n. 6
0
        public void A_SharedKillSwitch_must_ignore_subsequent_aborts_and_shutdowns_after_abort()
        {
            this.AssertAllStagesStopped(() =>
            {
                var killSwitch = KillSwitches.Shared("switch");

                var t = this.SourceProbe <int>()
                        .Via(killSwitch.Flow <int>())
                        .ToMaterialized(this.SinkProbe <int>(), Keep.Both)
                        .Run(Materializer);
                var upstream   = t.Item1;
                var downstream = t.Item2;

                downstream.Request(1);
                upstream.SendNext(1);
                downstream.ExpectNext(1);

                var testException = new TestException("Abort");
                killSwitch.Abort(testException);
                upstream.ExpectCancellation();
                downstream.ExpectError().InnerException.Should().Be(testException);

                killSwitch.Shutdown();
                upstream.ExpectNoMsg(TimeSpan.FromMilliseconds(100));
                downstream.ExpectNoMsg(TimeSpan.FromMilliseconds(100));

                killSwitch.Abort(new TestException("Abort_Late"));
                upstream.ExpectNoMsg(TimeSpan.FromMilliseconds(100));
                downstream.ExpectNoMsg(TimeSpan.FromMilliseconds(100));
            }, Materializer);
        }
Esempio n. 7
0
        public void BroadcastHub_must_be_able_to_implement_a_keep_dropping_if_unsubscribed_policy_with_a_simple_SinkIgnore()
        {
            this.AssertAllStagesStopped(() =>
            {
                var killSwitch = KillSwitches.Shared("test-switch");
                var source     = Source.From(Enumerable.Range(1, int.MaxValue))
                                 .Via(killSwitch.Flow <int>())
                                 .RunWith(BroadcastHub.Sink <int>(8), Materializer);

                // Now the Hub "drops" elements until we attach a new consumer (Source.ignore consumes as fast as possible)
                source.RunWith(Sink.Ignore <int>(), Materializer);

                // Now we attached a subscriber which will block the Sink.ignore to "take away" and drop elements anymore,
                // turning the BroadcastHub to a normal non-dropping mode
                var downstream = this.CreateSubscriberProbe <int>();
                source.RunWith(Sink.FromSubscriber(downstream), Materializer);

                downstream.Request(1);
                var first = downstream.ExpectNext();

                for (var i = first + 1; i < first + 11; i++)
                {
                    downstream.Request(1);
                    downstream.ExpectNext(i);
                }

                downstream.Cancel();
                killSwitch.Shutdown();
            }, Materializer);
        }
Esempio n. 8
0
        public void A_UniqueKillSwitch_must_work_if_used_multiple_times_in_a_flow()
        {
            var t = this.SourceProbe <int>()
                    .ViaMaterialized(KillSwitches.Single <int>(), Keep.Both)
                    //ex is a AggregateException from the Task
                    .Recover(ex => ex.InnerException is TestException ? -1 : Option <int> .None)
                    .ViaMaterialized(KillSwitches.Single <int>(), Keep.Both)
                    .ToMaterialized(this.SinkProbe <int>(), Keep.Both)
                    .Run(Materializer);
            var upstream    = t.Item1.Item1.Item1;
            var killSwitch1 = t.Item1.Item1.Item2;
            var killSwitch2 = t.Item1.Item2;
            var downstream  = t.Item2;

            downstream.Request(1);
            upstream.SendNext(1);
            downstream.ExpectNext(1);

            var testException = new TestException("Abort");

            killSwitch1.Abort(testException);
            upstream.ExpectCancellation();
            downstream.RequestNext(-1);

            killSwitch2.Shutdown();
            downstream.ExpectComplete();
        }
Esempio n. 9
0
 public void A_SharedKillSwitch_must_use_its_name_on_the_flows_it_hands_out()
 {
     this.AssertAllStagesStopped(() =>
     {
         var killSwitch = KillSwitches.Shared("MySwitchName");
         killSwitch.ToString().Should().Be("KillSwitch(MySwitchName)");
         killSwitch.Flow <int>().ToString().Should().Be("Flow(KillSwitch(MySwitchName))");
     }, Materializer);
 }
Esempio n. 10
0
        public IAsyncEnumerator <T> GetAsyncEnumerator(CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            return(new SinkQueueAsyncEnumerator <T>(_source
                                                    .Via(cancellationToken.AsFlow <T>(cancelGracefully: true))
                                                    .ViaMaterialized(KillSwitches.Single <T>(), Keep.Right)
                                                    .ToMaterialized(thisSinkQueue, Keep.Both)
                                                    .Run(_materializer),
                                                    cancellationToken));
        }
            public IDisposable CreateSubscription(long?lastProcessedCheckpoint, Action <string, Exception> errorHandler)
            {
                _errorHandler = errorHandler;

                var source = CreateSource(Offset.Sequence(lastProcessedCheckpoint ?? 0))
                             .Select(ee => (ee.Event as IDomainEvent, ee.Offset))
                             .Where(de => de.Item1 != null)
                             .Batch(20, de => ImmutableList <(IDomainEvent, Offset)> .Empty.Add(de !), (list, evt) => list.Add(evt !))
                             .Select(de =>
                {
                    var(domainEvent, offset) = de.Last();

                    return(new Transaction
                    {
                        Checkpoint = ((Sequence)offset).Value,
                        Id = EventId.New.Value,
                        StreamId = domainEvent.GetIdentity().Value,
                        TimeStampUtc = domainEvent.Timestamp.DateTime,
                        Events = new List <LiquidProjections.EventEnvelope>(
                            de
                            .Select(pair =>
                        {
                            var(evt, _) = pair;
                            return new LiquidProjections.EventEnvelope
                            {
                                Body = evt,
                                Headers = evt
                                          .Metadata
                                          .Select(p => Tuple.Create <string, object>(p.Key, p.Value))
                                          .ToDictionary(t => t.Item1, t => t.Item2)
                            };
                        }))
                    });
                })
                             .Batch(5, t => ImmutableList <Transaction> .Empty.Add(t), (list, transaction) => list.Add(transaction))
                             .AlsoTo(Sink.OnComplete <ImmutableList <Transaction> >(
                                         () => _isCancel.GetAndSet(true),
                                         e =>
                {
                    _isCancel.GetAndSet(true);
                    errorHandler(_exceptionInfo, e);
                }))
                             .ViaMaterialized(KillSwitches.Single <ImmutableList <Transaction> >(), (_, kill) => kill)
                             .PreMaterialize(_materializer);

                _cancelable = source.Item1;

                var sinkQueue = source.Item2.RunWith(Sink.Queue <ImmutableList <Transaction> >()
                                                     .WithAttributes(new Attributes(new Attributes.InputBuffer(2, 2))), _materializer);

                _runner = Run(sinkQueue);

                return(this);
            }
Esempio n. 12
0
 public void A_SharedKillSwitch_must_pass_through_all_elements_unmodified()
 {
     this.AssertAllStagesStopped(() =>
     {
         var killSwitch = KillSwitches.Shared("switch");
         var task       = Source.From(Enumerable.Range(1, 100))
                          .Via(killSwitch.Flow <int>())
                          .RunWith(Sink.Seq <int>(), Materializer);
         task.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue();
         task.Result.ShouldAllBeEquivalentTo(Enumerable.Range(1, 100));
     }, Materializer);
 }
Esempio n. 13
0
 public void A_SharedKillSwitch_should_not_cause_problems_if_switch_is_shutdown_after_flow_completed_normally()
 {
     this.AssertAllStagesStopped(() =>
     {
         var killSwitch = KillSwitches.Shared("switch");
         var task       = Source.From(Enumerable.Range(1, 10))
                          .Via(killSwitch.Flow <int>())
                          .RunWith(Sink.Seq <int>(), Materializer);
         task.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue();
         task.Result.ShouldAllBeEquivalentTo(Enumerable.Range(1, 10));
         killSwitch.Shutdown();
     }, Materializer);
 }
Esempio n. 14
0
        public void RetryConcat_tolerate_killswitch_terminations_inside_the_flow_on_start()
        {
            var t = this.SourceProbe <int>()
                    .ViaMaterialized(KillSwitches.Single <int>(), Keep.Right)
                    .Select(i => Tuple.Create(i, i))
                    .Via(Retry.Concat(100, RetryFlow <int>(), x => new[] { Tuple.Create(x, x + 1) }))
                    .ToMaterialized(this.SinkProbe <Tuple <Result <int>, int> >(), Keep.Both)
                    .Run(Sys.Materializer());

            var killSwitch = t.Item1;
            var sink       = t.Item2;

            sink.Request(99);
            killSwitch.Abort(FailedElement.Exception);
            sink.ExpectError().InnerException.Should().Be(FailedElement.Exception);
        }
Esempio n. 15
0
        public async Task Given_journal_When_starting_projection_stream_Then_projection_launched_producing_data()
        {
            var dep = await Init();

            _output.WriteLine(Sys.Settings.ToString());
            //generate some data
            var calculationActor = Sys.ActorOf(Props.Create <CalculatorActor>(), "CalculatorOne");

            calculationActor.Tell(new CalculatorActorProtocol.CalculateExpression("1+2-3"));
            calculationActor.Tell(new CalculatorActorProtocol.CalculateExpression("1-2*3"));
            calculationActor.Tell(new CalculatorActorProtocol.CalculateExpression("1/2+3"));

            var eventName = nameof(CalculatorActor.CalculationPerformed);

            var readJournal      = PersistenceQuery.Get(Sys).ReadJournalFor <SqlReadJournal>(SqlReadJournal.Identifier);
            var sharedKillSwitch = KillSwitches.Shared("test");
            var source           = readJournal.EventsByTag(eventName, Offset.NoOffset())
                                   .Via(sharedKillSwitch.Flow <EventEnvelope>());

            var flow = FunctionTotalUsageFlow.Instance;
            var sink = FunctionTotalUsageSink.Create(Sys, eventName);

            source.Via(flow).To(sink).Run(Sys.Materializer());

            await Task.Delay(5000);

            var projected = new FindProjectionQuery(dep.CreateFunctionUsageContext()).ExecuteForFunctionsTotalUsage();

            Assert.Equal(3, projected.Sequence);

            var usage = await new FunctionsTotalUsageQuery(dep.CreateFunctionUsageContext()).Execute();

            usage.Should().BeEquivalentTo(
                new FunctionTotalUsage {
                FunctionName = "AddChecked", InvocationsCount = 2
            },
                new FunctionTotalUsage {
                FunctionName = "SubtractChecked", InvocationsCount = 2
            },
                new FunctionTotalUsage {
                FunctionName = "MultiplyChecked", InvocationsCount = 1
            },
                new FunctionTotalUsage {
                FunctionName = "Divide", InvocationsCount = 1
            });
        }
Esempio n. 16
0
        public void A_SharedKillSwitch_must_provide_flows_that_materialize_to_its_owner_KillSwitch()
        {
            this.AssertAllStagesStopped(() =>
            {
                var killSwitch = KillSwitches.Shared("switch");
                var t          = Source.Maybe <int>()
                                 .ViaMaterialized(killSwitch.Flow <int>(), Keep.Right)
                                 .ToMaterialized(Sink.Ignore <int>(), Keep.Both)
                                 .Run(Materializer);

                var killSwitch2 = t.Item1;
                var completion  = t.Item2;
                killSwitch2.Should().Be(killSwitch);
                killSwitch2.Shutdown();
                completion.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue();
                completion.IsFaulted.Should().BeFalse();
            }, Materializer);
        }
Esempio n. 17
0
        public void A_SharedKillSwitch_must_complete_immediately_flows_materialized_after_switch_shutdown()
        {
            this.AssertAllStagesStopped(() =>
            {
                var killSwitch = KillSwitches.Shared("switch");
                killSwitch.Shutdown();

                var t = this.SourceProbe <int>()
                        .Via(killSwitch.Flow <int>())
                        .ToMaterialized(this.SinkProbe <int>(), Keep.Both)
                        .Run(Materializer);
                var upstream   = t.Item1;
                var downstream = t.Item2;

                upstream.ExpectCancellation();
                downstream.ExpectSubscriptionAndComplete();
            }, Materializer);
        }
Esempio n. 18
0
        public void Unique_kill_switch_must_control_graph_completion_with_shutdown()
        {
            #region unique-shutdown
            var countingSrc = Source.From(Enumerable.Range(1, int.MaxValue)).Delay(1.Seconds(), DelayOverflowStrategy.Backpressure);
            var lastSink    = Sink.Last <int>();

            var(killSwitch, last) = countingSrc
                                    .ViaMaterialized(KillSwitches.Single <int>(), Keep.Right)
                                    .ToMaterialized(lastSink, Keep.Both)
                                    .Run(Materializer);

            DoSomethingElse();

            killSwitch.Shutdown();

            AwaitCondition(() => last.IsCompleted);
            #endregion
        }
Esempio n. 19
0
        public void Unique_kill_switch_must_control_graph_completion_with_abort()
        {
            #region unique-abort
            var countingSrc = Source.From(Enumerable.Range(1, int.MaxValue)).Delay(1.Seconds(), DelayOverflowStrategy.Backpressure);
            var lastSink    = Sink.Last <int>();

            var(killSwitch, last) = countingSrc
                                    .ViaMaterialized(KillSwitches.Single <int>(), Keep.Right)
                                    .ToMaterialized(lastSink, Keep.Both)
                                    .Run(Materializer);

            var error = new Exception("boom");
            killSwitch.Abort(error);

            last.Wait(1.Seconds());
            last.Exception.Should().Be(error);
            #endregion
        }
Esempio n. 20
0
        public void A_SharedKillSwitch_must_not_affect_streams_corresponding_to_another_KillSwitch()
        {
            this.AssertAllStagesStopped(() =>
            {
                var killSwitch1 = KillSwitches.Shared("switch");
                var killSwitch2 = KillSwitches.Shared("switch");

                var t1 = this.SourceProbe <int>()
                         .Via(killSwitch1.Flow <int>())
                         .ToMaterialized(this.SinkProbe <int>(), Keep.Both)
                         .Run(Materializer);
                var t2 = this.SourceProbe <int>()
                         .Via(killSwitch2.Flow <int>())
                         .ToMaterialized(this.SinkProbe <int>(), Keep.Both)
                         .Run(Materializer);

                var upstream1   = t1.Item1;
                var downstream1 = t1.Item2;
                var upstream2   = t2.Item1;
                var downstream2 = t2.Item2;

                downstream1.Request(1);
                upstream1.SendNext(1);
                downstream1.ExpectNext(1);

                downstream2.Request(1);
                upstream2.SendNext(2);
                downstream2.ExpectNext(2);

                killSwitch1.Shutdown();
                upstream1.ExpectCancellation();
                downstream1.ExpectComplete();
                upstream2.ExpectNoMsg(TimeSpan.FromMilliseconds(100));
                downstream2.ExpectNoMsg(TimeSpan.FromMilliseconds(100));

                var testException = new TestException("Abort");
                killSwitch2.Abort(testException);
                upstream1.ExpectNoMsg(TimeSpan.FromMilliseconds(100));
                downstream1.ExpectNoMsg(TimeSpan.FromMilliseconds(100));
                upstream2.ExpectCancellation();
                downstream2.ExpectError().InnerException.Should().Be(testException);
            }, Materializer);
        }
Esempio n. 21
0
        public void A_UniqueKillSwitch_must_stop_a_stream_if_requested()
        {
            var t = this.SourceProbe <int>()
                    .ViaMaterialized(KillSwitches.Single <int>(), Keep.Both)
                    .ToMaterialized(this.SinkProbe <int>(), Keep.Both)
                    .Run(Materializer);
            var upstream   = t.Item1.Item1;
            var killSwitch = t.Item1.Item2;
            var downstream = t.Item2;

            downstream.Request(1);
            upstream.SendNext(1);
            downstream.ExpectNext(1);

            killSwitch.Shutdown();

            upstream.ExpectCancellation();
            downstream.ExpectComplete();
        }
Esempio n. 22
0
        public void A_SharedKillSwitch_must_fail_immediately_flows_materialized_after_switch_failure()
        {
            this.AssertAllStagesStopped(() =>
            {
                var killSwitch    = KillSwitches.Shared("switch");
                var testException = new TestException("Abort");
                killSwitch.Abort(testException);

                var t = this.SourceProbe <int>()
                        .Via(killSwitch.Flow <int>())
                        .ToMaterialized(this.SinkProbe <int>(), Keep.Both)
                        .Run(Materializer);
                var upstream   = t.Item1;
                var downstream = t.Item2;

                upstream.ExpectCancellation();
                downstream.ExpectSubscriptionAndError().InnerException.Should().Be(testException);
            }, Materializer);
        }
Esempio n. 23
0
        public void Shared_kill_switch_must_control_graph_completion_with_abort()
        {
            #region shared-abort
            var countingSrc      = Source.From(Enumerable.Range(1, int.MaxValue)).Delay(1.Seconds());
            var lastSink         = Sink.Last <int>();
            var sharedKillSwitch = KillSwitches.Shared("my-kill-switch");

            var last1 = countingSrc.Via(sharedKillSwitch.Flow <int>()).RunWith(lastSink, Materializer);
            var last2 = countingSrc.Via(sharedKillSwitch.Flow <int>()).RunWith(lastSink, Materializer);

            var error = new Exception("boom");
            sharedKillSwitch.Abort(error);

            last1.Wait(1.Seconds());
            last1.Exception.Should().Be(error);

            last2.Wait(1.Seconds());
            last2.Exception.Should().Be(error);
            #endregion
        }
Esempio n. 24
0
        public void A_UniqueKillSwitch_must_ignore_completion_after_already_completed()
        {
            var t = this.SourceProbe <int>()
                    .ViaMaterialized(KillSwitches.Single <int>(), Keep.Both)
                    .ToMaterialized(this.SinkProbe <int>(), Keep.Both)
                    .Run(Materializer);
            var upstream   = t.Item1.Item1;
            var killSwitch = t.Item1.Item2;
            var downstream = t.Item2;

            upstream.EnsureSubscription();
            downstream.EnsureSubscription();

            killSwitch.Shutdown();
            upstream.ExpectCancellation();
            downstream.ExpectComplete();

            killSwitch.Abort(new TestException("Won't happen"));
            upstream.ExpectNoMsg(TimeSpan.FromMilliseconds(100));
            downstream.ExpectNoMsg(TimeSpan.FromMilliseconds(100));
        }
Esempio n. 25
0
        public void Hubs_must_demonstrate_combination()
        {
            void WriteLine(string s) => TestActor.Tell(s);

            #region pub-sub-1
            // Obtain a Sink and Source which will publish and receive from the "bus" respectively.
            var(sink, source) = MergeHub
                                .Source <string>(perProducerBufferSize: 16)
                                .ToMaterialized(BroadcastHub.Sink <string>(bufferSize: 256), Keep.Both)
                                .Run(Materializer);
            #endregion

            #region pub-sub-2
            // Ensure that the Broadcast output is dropped if there are no listening parties.
            // If this dropping Sink is not attached, then the broadcast hub will not drop any
            // elements itself when there are no subscribers, backpressuring the producer instead.
            source.RunWith(Sink.Ignore <string>(), Materializer);
            #endregion

            #region pub-sub-3
            // We create now a Flow that represents a publish-subscribe channel using the above
            // started stream as its "topic". We add two more features, external cancellation of
            // the registration and automatic cleanup for very slow subscribers.
            Flow <string, string, UniqueKillSwitch> busFlow = Flow.FromSinkAndSource(sink, source)
                                                              .JoinMaterialized(KillSwitches.SingleBidi <string, string>(), Keep.Right)
                                                              .BackpressureTimeout(TimeSpan.FromSeconds(3));
            #endregion

            #region pub-sub-4

            UniqueKillSwitch killSwitch = Source
                                          .Repeat("Hello world!")
                                          .ViaMaterialized(busFlow, Keep.Right)
                                          .To(Sink.ForEach <string>(WriteLine))
                                          .Run(Materializer);

            // Shut down externally
            killSwitch.Shutdown();
            #endregion
        }
Esempio n. 26
0
        public void A_SharedKillSwitch_must_stop_a_stream_if_requested()
        {
            this.AssertAllStagesStopped(() =>
            {
                var killSwitch = KillSwitches.Shared("switch");

                var t = this.SourceProbe <int>()
                        .Via(killSwitch.Flow <int>())
                        .ToMaterialized(this.SinkProbe <int>(), Keep.Both)
                        .Run(Materializer);
                var upstream   = t.Item1;
                var downstream = t.Item2;

                downstream.Request(1);
                upstream.SendNext(1);
                downstream.ExpectNext(1);

                killSwitch.Shutdown();
                upstream.ExpectCancellation();
                downstream.ExpectComplete();
            }, Materializer);
        }
Esempio n. 27
0
        public void A_UniqueKillSwitch_must_fail_a_stream_if_requested()
        {
            var t = this.SourceProbe <int>()
                    .ViaMaterialized(KillSwitches.Single <int>(), Keep.Both)
                    .ToMaterialized(this.SinkProbe <int>(), Keep.Both)
                    .Run(Materializer);
            var upstream   = t.Item1.Item1;
            var killSwitch = t.Item1.Item2;
            var downstream = t.Item2;

            downstream.Request(1);
            upstream.SendNext(1);
            downstream.ExpectNext(1);

            var testException = new TestException("Abort");

            killSwitch.Abort(testException);

            upstream.ExpectCancellation();
            //is a AggregateException from the Task
            downstream.ExpectError().InnerException.Should().Be(testException);
        }
Esempio n. 28
0
        public void A_SharedKillSwitch_must_fail_a_stream_if_requested()
        {
            this.AssertAllStagesStopped(() =>
            {
                var killSwitch = KillSwitches.Shared("switch");

                var t = this.SourceProbe <int>()
                        .Via(killSwitch.Flow <int>())
                        .ToMaterialized(this.SinkProbe <int>(), Keep.Both)
                        .Run(Materializer);
                var upstream   = t.Item1;
                var downstream = t.Item2;

                downstream.Request(1);
                upstream.SendNext(1);
                downstream.ExpectNext(1);

                var testException = new TestException("Abort");
                killSwitch.Abort(testException);
                upstream.ExpectCancellation();
                downstream.ExpectError().InnerException.Should().Be(testException);
            }, Materializer);
        }
Esempio n. 29
0
        public void A_SharedKillSwitch_must_provide_a_flow_that_if_materialized_multiple_times_with_multiple_types_fails_all_streams_if_requested()
        {
            this.AssertAllStagesStopped(() =>
            {
                var killSwitch = KillSwitches.Shared("switch");

                var t1 = this.SourceProbe <int>()
                         .Via(killSwitch.Flow <int>())
                         .ToMaterialized(this.SinkProbe <int>(), Keep.Both)
                         .Run(Materializer);
                var t2 = this.SourceProbe <string>()
                         .Via(killSwitch.Flow <string>())
                         .ToMaterialized(this.SinkProbe <string>(), Keep.Both)
                         .Run(Materializer);

                var upstream1   = t1.Item1;
                var downstream1 = t1.Item2;
                var upstream2   = t2.Item1;
                var downstream2 = t2.Item2;

                downstream1.Request(1);
                upstream1.SendNext(1);
                downstream1.ExpectNext(1);

                downstream2.Request(2);
                upstream2.SendNext("A").SendNext("B");
                downstream2.ExpectNext("A", "B");

                var testException = new TestException("Abort");
                killSwitch.Abort(testException);
                upstream1.ExpectCancellation();
                upstream2.ExpectCancellation();

                downstream1.ExpectError().InnerException.Should().Be(testException);
                downstream2.ExpectError().InnerException.Should().Be(testException);
            }, Materializer);
        }
Esempio n. 30
0
        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;
            }));
        }