Пример #1
0
 public static Source <CommittableIncomingMessage, Akka.NotUsed> CommittableQueueWithWithBackoff(Action <SimpleQueueOptions> opt)
 {
     return(RestartSource.WithBackoff(() => CommittableQueue(opt),
                                      TimeSpan.FromSeconds(3),
                                      TimeSpan.FromSeconds(30),
                                      0.2));
 }
Пример #2
0
        public void A_restart_with_backoff_source_should_restart_on_failure()
        {
            this.AssertAllStagesStopped(() =>
            {
                var created = new AtomicCounter(0);
                var probe   = RestartSource.WithBackoff(() =>
                {
                    created.IncrementAndGet();
                    var enumerable = new List <string> {
                        "a", "b", "c"
                    }.Select(c =>
                    {
                        if (c == "c")
                        {
                            throw new ArgumentException("failed");
                        }
                        return(c);
                    });
                    return(Source.From(enumerable));
                }, TimeSpan.FromMilliseconds(10), TimeSpan.FromMilliseconds(20), 0).RunWith(this.SinkProbe <string>(), Materializer);

                probe.RequestNext("a");
                probe.RequestNext("b");
                probe.RequestNext("a");
                probe.RequestNext("b");
                probe.RequestNext("a");

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

                probe.Cancel();
            }, Materializer);
        }
Пример #3
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
        }
Пример #4
0
        public void A_restart_with_backoff_source_should_allow_using_withMaxRestarts_instead_of_minBackoff_to_determine_the_maxRestarts_reset_time()
        {
            this.AssertAllStagesStopped(() =>
            {
                var created = new AtomicCounter(0);
                var probe   = RestartSource.WithBackoff(() =>
                {
                    created.IncrementAndGet();
                    return(Source.From(new List <string> {
                        "a", "b"
                    }).TakeWhile(c => c != "b"));
                }, _shortRestartSettings.WithMaxRestarts(2, TimeSpan.FromSeconds(1)))
                              .RunWith(this.SinkProbe <string>(), Materializer);

                probe.RequestNext("a");
                probe.RequestNext("a");

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

                probe.RequestNext("a");

                probe.Request(1);
                probe.ExpectComplete();

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

                probe.Cancel();
            }, Materializer);
        }
Пример #5
0
        public void A_restart_with_backoff_source_should_cancel_the_currently_running_source_when_cancelled()
        {
            this.AssertAllStagesStopped(() =>
            {
                var created = new AtomicCounter(0);
                var tcs     = new TaskCompletionSource <Done>();
                var probe   = RestartSource.WithBackoff(() =>
                {
                    created.IncrementAndGet();
                    return(Source.From(new List <string> {
                        "a", "b"
                    })
                           .WatchTermination((source, _) =>
                    {
                        tcs.SetResult(Done.Instance);
                        return source;
                    }));
                }, TimeSpan.FromMilliseconds(10), TimeSpan.FromSeconds(2), 0).RunWith(this.SinkProbe <string>(), Materializer);

                probe.RequestNext("a");
                probe.Cancel();

                tcs.Task.Result.Should().BeSameAs(Done.Instance);

                // Wait to ensure it isn't restarted
                Thread.Sleep(200);
                created.Current.Should().Be(1);
            }, Materializer);
        }
Пример #6
0
        public void A_restart_with_backoff_source_should_backoff_before_restart()
        {
            this.AssertAllStagesStopped(() =>
            {
                var created = new AtomicCounter(0);
                var probe   = RestartSource.WithBackoff(() =>
                {
                    created.IncrementAndGet();
                    return(Source.From(new List <string> {
                        "a", "b"
                    }));
                }, TimeSpan.FromMilliseconds(200), TimeSpan.FromMilliseconds(1000), 0).RunWith(this.SinkProbe <string>(), Materializer);

                probe.RequestNext("a");
                probe.RequestNext("b");
                probe.Request(1);
                // There should be a delay of at least 200ms before we receive the element, wait for 100ms.
                var deadline = TimeSpan.FromMilliseconds(100).FromNow();
                // But the delay shouldn't be more than 300ms.
                probe.ExpectNext(TimeSpan.FromMilliseconds(300), "a");
                deadline.IsOverdue.Should().Be(true);

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

                probe.Cancel();
            }, Materializer);
        }
Пример #7
0
        public void A_restart_with_backoff_source_should_reset_maxRestarts_when_source_runs_for_at_least_minimum_backoff_without_completing()
        {
            this.AssertAllStagesStopped(() =>
            {
                var created = new AtomicCounter(0);
                var probe   = RestartSource.WithBackoff(() =>
                {
                    created.IncrementAndGet();
                    return(Source.Single("a"));
                }, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(3), 0, maxRestarts: 2).RunWith(this.SinkProbe <string>(), Materializer);

                probe.RequestNext("a");
                // There should be minBackoff delay
                probe.RequestNext("a");
                // The probe should now be backing off again with with increased backoff

                // Now wait for the delay to pass, then it will start the new source, we also want to wait for the
                // subsequent backoff to pass
                const int minBackoff = 1000;
                Thread.Sleep((minBackoff + (minBackoff * 2) + minBackoff + 500));

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

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

                probe.Cancel();
            }, Materializer);
        }
Пример #8
0
        public void A_restart_with_backoff_source_should_not_restart_the_source_when_maxRestarts_is_reached()
        {
            this.AssertAllStagesStopped(() =>
            {
                var created = new AtomicCounter(0);
                var probe   = RestartSource.WithBackoff(() =>
                {
                    created.IncrementAndGet();
                    return(Source.Single("a"));
                }, TimeSpan.FromMilliseconds(10), TimeSpan.FromMilliseconds(20), 0, maxRestarts: 1).RunWith(this.SinkProbe <string>(), Materializer);

                probe.RequestNext("a");
                probe.RequestNext("a");
                probe.ExpectComplete(TimeSpan.FromSeconds(5));

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

                probe.Cancel();
            }, Materializer);
        }
Пример #9
0
        public void A_restart_with_backoff_source_should_not_restart_the_source_when_cancelled_while_backing_off()
        {
            this.AssertAllStagesStopped(() =>
            {
                var created = new AtomicCounter(0);
                var probe   = RestartSource.WithBackoff(() =>
                {
                    created.IncrementAndGet();
                    return(Source.Single("a"));
                }, TimeSpan.FromMilliseconds(10), TimeSpan.FromMilliseconds(20), 0).RunWith(this.SinkProbe <string>(), Materializer);

                probe.RequestNext("a");
                probe.Request(1);
                // Should be backing off now
                probe.Cancel();

                // Wait to ensure it isn't restarted
                Thread.Sleep(300);
                created.Current.Should().Be(1);
            }, Materializer);
        }
Пример #10
0
        public void A_restart_with_backoff_source_should_not_restart_the_source_when_maxRestarts_is_reached()
        {
            this.AssertAllStagesStopped(() =>
            {
                var created = new AtomicCounter(0);
                var probe   = RestartSource.WithBackoff(() =>
                {
                    created.IncrementAndGet();
                    return(Source.Single("a"));
                }, _shortRestartSettings.WithMaxRestarts(1, _shortMinBackoff))
                              .RunWith(this.SinkProbe <string>(), Materializer);

                probe.RequestNext("a");
                probe.RequestNext("a");
                probe.ExpectComplete();

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

                probe.Cancel();
            }, Materializer);
        }
Пример #11
0
        public void A_restart_with_backoff_source_should_run_normally()
        {
            this.AssertAllStagesStopped(() =>
            {
                var created = new AtomicCounter(0);
                var probe   = RestartSource.WithBackoff(() =>
                {
                    created.IncrementAndGet();
                    return(Source.Repeat("a"));
                }, TimeSpan.FromMilliseconds(10), TimeSpan.FromMilliseconds(20), 0).RunWith(this.SinkProbe <string>(), Materializer);

                probe.RequestNext("a");
                probe.RequestNext("a");
                probe.RequestNext("a");
                probe.RequestNext("a");
                probe.RequestNext("a");

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

                probe.Cancel();
            }, Materializer);
        }
Пример #12
0
        public void A_restart_with_backoff_source_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 probe   = RestartSource.WithBackoff(() =>
                {
                    created.IncrementAndGet();
                    return(Source.From(new List <string> {
                        "a", "b"
                    }));
                }, _restartSettings)
                              .RunWith(this.SinkProbe <string>(), Materializer);

                probe.RequestNext("a");
                probe.RequestNext("b");
                // There should be _minBackoff delay
                probe.RequestNext("a");
                probe.RequestNext("b");
                probe.Request(1);
                // The probe should now be backing off again with with increased backoff

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

                probe.ExpectNext("a");
                probe.RequestNext("b");

                // We should have reset, so the restart delay should be back, ie we should receive the
                // next element within < 2 * _minBackoff
                probe.RequestNext(TimeSpan.FromTicks(_minBackoff.Ticks * 2) - TimeSpan.FromMilliseconds(10)).Should().Be("a");

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

                probe.Cancel();
            }, Materializer);
        }
Пример #13
0
        public void A_restart_with_backoff_source_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 probe   = RestartSource.WithBackoff(() =>
                {
                    created.IncrementAndGet();
                    return(Source.From(new List <string> {
                        "a", "b"
                    }));
                }, TimeSpan.FromMilliseconds(200), TimeSpan.FromMilliseconds(2000), 0).RunWith(this.SinkProbe <string>(), Materializer);

                probe.RequestNext("a");
                probe.RequestNext("b");
                // There should be a 200ms delay
                probe.RequestNext("a");
                probe.RequestNext("b");
                probe.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.ExpectNext("a");
                probe.RequestNext("b");

                // We should have reset, so the restart delay should be back to 200ms, ie we should definitely receive the
                // next element within 300ms
                probe.RequestNext(TimeSpan.FromMilliseconds(300)).Should().Be("a");

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

                probe.Cancel();
            }, Materializer);
        }
Пример #14
0
        public void A_restart_with_backoff_source_should_restart_on_completion()
        {
            this.AssertAllStagesStopped(() =>
            {
                var created = new AtomicCounter(0);
                var probe   = RestartSource.WithBackoff(() =>
                {
                    created.IncrementAndGet();
                    return(Source.From(new List <string> {
                        "a", "b"
                    }));
                }, _shortRestartSettings).RunWith(this.SinkProbe <string>(), Materializer);

                probe.RequestNext("a");
                probe.RequestNext("b");
                probe.RequestNext("a");
                probe.RequestNext("b");
                probe.RequestNext("a");

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

                probe.Cancel();
            }, Materializer);
        }
Пример #15
0
 private static Source <TOut, NotUsed> RestartSourceFactory <TOut, TMat>(Func <Source <TOut, TMat> > flowFactory, TimeSpan minBackoff, TimeSpan maxBackoff, double randomFactor, int maxRestarts, bool onlyOnFailures)
 {
     return(onlyOnFailures
         ? RestartSource.OnFailuresWithBackoff(flowFactory, minBackoff, maxBackoff, randomFactor, maxRestarts)
         : RestartSource.WithBackoff(flowFactory, minBackoff, maxBackoff, randomFactor, maxRestarts));
 }
Пример #16
0
        protected override void OnStartup(StartupEventArgs e)
        {
            GUID = GetGUID();

            _mtx = new Mutex(true, GUID, out var mtxSuccess);

            // 뮤텍스를 얻지 못하면 에러
            if (!mtxSuccess)
            {
                MessageBox.Show("이미 실행중입니다.");
                Shutdown();
                return;
            }

            try
            {
                var authority = AkkaHelper.ReadConfigurationFromHoconFile(Assembly.GetExecutingAssembly(), "conf")
                                .WithFallback(ConfigurationFactory
                                              .FromResource <ConsumerSettings <object, object> >("Akka.Streams.Kafka.reference.conf"))
                                .GetInt("ui.notification.authority-level");

                if (authority < 1 || authority > 5)
                {
                    MessageBox.Show("authority-level은 1~5까지 지정할 수 있습니다.", "Error");
                    Shutdown();
                    return;
                }

                var assembly        = Assembly.GetExecutingAssembly();
                var fileVersionInfo = FileVersionInfo.GetVersionInfo(assembly.Location);
                _version = fileVersionInfo.ProductVersion;

                var config = AkkaHelper.ReadConfigurationFromHoconFile(Assembly.GetExecutingAssembly(), "conf")
                             .WithFallback(ConfigurationFactory.FromResource <ConsumerSettings <object, object> >("Akka.Streams.Kafka.reference.conf"));


                CreateTrayIcon(config);
                CreateNotifier(config);

                var system = ActorSystem.Create("BLUECATS-ToastNotifier", config);

                notificationActor = system.ActorOf(NotificationActor.Props(Notifier), nameof(NotificationActor));
                var parserActor         = system.ActorOf(ParserActor.Props(notificationActor), nameof(ParserActor));
                var eventSubscribeActor = system.ActorOf(EventSubscribeActor.Props(notificationActor), nameof(EventSubscribeActor));
                system.EventStream.Subscribe(eventSubscribeActor, typeof(Akka.Event.Error));

                var bootStrapServers = GetBootStrapServers(config);

                var consumerSettings = ConsumerSettings <Null, string> .Create(system, null, Deserializers.Utf8)
                                       .WithBootstrapServers(bootStrapServers)
                                       .WithGroupId(GUID);

                notificationActor.Tell((NotificationLevel.Info, $"BLUE CATS: Client Start\n{GUID}"));

                RestartSource.WithBackoff(() =>
                                          KafkaConsumer.PlainSource(consumerSettings, GetSubscription(config)),
                                          minBackoff: TimeSpan.FromSeconds(3),
                                          maxBackoff: TimeSpan.FromSeconds(30),
                                          randomFactor: 0.2)
                .RunForeach(result =>
                {
                    parserActor.Tell(result);
                }, system.Materializer());
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                Current.Shutdown();
            }

            base.OnStartup(e);
        }