Esempio n. 1
0
        public void A_restart_with_backoff_sink_should_not_restart_the_sink_when_completed_while_backing_off()
        {
            this.AssertAllStagesStopped(() =>
            {
                var created   = new AtomicCounter(0);
                var tuple     = this.SourceProbe <string>().ToMaterialized(this.SinkProbe <string>(), Keep.Both).Run(Materializer);
                var queue     = tuple.Item1;
                var sinkProbe = tuple.Item2;
                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))));
                }, TimeSpan.FromMilliseconds(200), TimeSpan.FromSeconds(2), 0), Keep.Left).Run(Materializer);

                probe.SendNext("a");
                sinkProbe.RequestNext("a");
                probe.SendNext("cancel");
                sinkProbe.RequestNext("cancel");
                // Should be backing off now
                probe.SendComplete();

                // Wait to ensure it isn't restarted
                Thread.Sleep(300);
                created.Current.Should().Be(1);

                sinkProbe.Cancel();
            }, Materializer);
        }
Esempio n. 2
0
        public void A_restart_with_backoff_sink_should_backoff_before_restart()
        {
            this.AssertAllStagesStopped(() =>
            {
                var created   = new AtomicCounter(0);
                var tuple     = this.SourceProbe <string>().ToMaterialized(this.SinkProbe <string>(), Keep.Both).Run(Materializer);
                var queue     = tuple.Item1;
                var sinkProbe = tuple.Item2;
                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))));
                }, TimeSpan.FromMilliseconds(200), TimeSpan.FromSeconds(2), 0), Keep.Left).Run(Materializer);

                probe.SendNext("a");
                sinkProbe.RequestNext("a");
                probe.SendNext("cancel");
                sinkProbe.RequestNext("cancel");
                probe.SendNext("b");
                sinkProbe.Request(1);
                var deadline = TimeSpan.FromMilliseconds(100).FromNow();
                sinkProbe.ExpectNext(TimeSpan.FromMilliseconds(300), "b");
                deadline.IsOverdue.Should().BeTrue();

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

                sinkProbe.Cancel();
                probe.SendComplete();
            }, Materializer);
        }
Esempio n. 3
0
        public void A_restart_with_backoff_sink_should_run_normally()
        {
            this.AssertAllStagesStopped(() =>
            {
                var created = new AtomicCounter(0);
                var tcs     = new TaskCompletionSource <IEnumerable <string> >();
                var probe   = this.SourceProbe <string>().ToMaterialized(RestartSink.WithBackoff(() =>
                {
                    created.IncrementAndGet();
                    return(Sink.Seq <string>().MapMaterializedValue(task =>
                    {
                        task.ContinueWith(c => tcs.SetResult(c.Result));
                        return Done.Instance;
                    }));
                }, TimeSpan.FromMilliseconds(10), TimeSpan.FromMilliseconds(20), 0), Keep.Left).Run(Materializer);

                probe.SendNext("a");
                probe.SendNext("b");
                probe.SendNext("c");
                probe.SendComplete();

                tcs.Task.Result.Should().ContainInOrder("a", "b", "c");
                created.Current.Should().Be(1);
            }, Materializer);
        }
Esempio n. 4
0
        public void A_restart_with_backoff_sink_should_not_restart_the_sink_when_maxRestarts_is_reached()
        {
            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))));
                }, _shortRestartSettings.WithMaxRestarts(1, _shortMinBackoff)), Keep.Left)
                                        .Run(Materializer);

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

                probe.ExpectCancellation();

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

                sinkProbe.Cancel();
                probe.SendComplete();
            }, Materializer);
        }
Esempio n. 5
0
 public static Sink <ByteString, Akka.NotUsed> SimpleWithBackoff(Action <SimpleQueueOptions> opt)
 {
     return(RestartSink.WithBackoff(() => Simple(opt),
                                    TimeSpan.FromSeconds(3),
                                    TimeSpan.FromSeconds(30),
                                    0.2));
 }
Esempio n. 6
0
        public void A_restart_with_backoff_sink_should_reset_exponential_backoff_back_to_minimum_when_source_runs_for_at_least_minimum_backoff_without_completing()
        {
            this.AssertAllStagesStopped(() =>
            {
                var created   = new AtomicCounter(0);
                var tuple     = this.SourceProbe <string>().ToMaterialized(this.SinkProbe <string>(), Keep.Both).Run(Materializer);
                var queue     = tuple.Item1;
                var sinkProbe = tuple.Item2;
                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))));
                }, TimeSpan.FromMilliseconds(200), TimeSpan.FromSeconds(2), 0), Keep.Left).Run(Materializer);

                probe.SendNext("a");
                sinkProbe.RequestNext("a");
                probe.SendNext("cancel");
                sinkProbe.RequestNext("cancel");
                // There should be a 200ms delay
                probe.SendNext("b");
                sinkProbe.RequestNext("b");
                probe.SendNext("cancel");
                sinkProbe.RequestNext("cancel");
                sinkProbe.Request(1);
                // The probe should now be backing off for 400ms

                // Now wait for the 400ms delay to pass, then it will start the new source, we also want to wait for the
                // subsequent 200ms min backoff to pass, so it resets the restart count
                Thread.Sleep(700);

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

                // We should have reset, so the restart delay should be back to 200ms, ie we should definitely receive the
                // next element within 300ms
                probe.SendNext("c");
                sinkProbe.Request(1);
                sinkProbe.ExpectNext(TimeSpan.FromMilliseconds(300), "c");

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

                sinkProbe.Cancel();
                probe.SendComplete();
            }, Materializer);
        }
Esempio n. 7
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);
        }
Esempio n. 8
0
        public void A_restart_with_backoff_sink_should_allow_using_withMaxRestarts_instead_of_minBackoff_to_determine_the_maxRestarts_reset_time()
        {
            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))));
                }, _shortRestartSettings.WithMaxRestarts(2, TimeSpan.FromSeconds(1))), Keep.Left)
                                        .Run(Materializer);

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

                Thread.Sleep(_shortMinBackoff + TimeSpan.FromTicks(_shortMinBackoff.Ticks * 2) + _shortMinBackoff); // if using shortMinBackoff as deadline cause reset

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

                // We cannot get a final element
                probe.SendNext("cancel");
                sinkProbe.Request(1);
                sinkProbe.ExpectNoMsg();

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

                sinkProbe.Cancel();
                probe.SendComplete();
            }, Materializer);
        }