示例#1
0
        public async Task Notifier_should_send_current_health_to_the_API()
        {
            var endpointId     = Guid.NewGuid();
            var expectedHealth = new EndpointHealth(HealthStatus.Offline, new Dictionary <string, string> {
                { "key", "value" }
            });
            HealthUpdate lastCaptured = null;
            var          countdown    = new AsyncCountdown("update", 5);

            SetupHealthCheckInterval(TimeSpan.FromMilliseconds(1));
            SetupEndpointRegistration(endpointId);

            _mockClient.Setup(c => c.SendHealthUpdateAsync(endpointId, AuthenticationToken, It.IsAny <HealthUpdate>(), It.IsAny <CancellationToken>()))
            .Returns((Guid id, string authToken, HealthUpdate upd, CancellationToken token) => _awaitableFactory
                     .Execute(() => lastCaptured = upd)
                     .WithCountdown(countdown)
                     .RunAsync());

            using (CreateNotifier(token => Task.FromResult(expectedHealth)))
                await countdown.WaitAsync(TestMaxTime);

            Assert.NotNull(lastCaptured);
            Assert.Equal(expectedHealth.Status, lastCaptured.Status);
            Assert.Equal(expectedHealth.Details, lastCaptured.Details);
            Assert.True(lastCaptured.CheckTimeUtc > DateTime.UtcNow.AddMinutes(-1) && lastCaptured.CheckTimeUtc < DateTime.UtcNow.AddMinutes(1));
        }
示例#2
0
        public async Task Notifier_should_register_endpoint_with_all_details_and_specified_host()
        {
            EndpointDefinition captured = null;
            var countdown  = new AsyncCountdown("register", 1);
            var endpointId = Guid.NewGuid();

            _mockClient
            .Setup(c => c.RegisterEndpointAsync(It.IsAny <EndpointDefinition>(), It.IsAny <CancellationToken>()))
            .Returns((EndpointDefinition def, CancellationToken token) => _awaitableFactory
                     .Execute(() => { captured = def; return(endpointId); })
                     .WithCountdown(countdown)
                     .RunAsync());

            SetupHealthCheckInterval(TimeSpan.FromMilliseconds(1));

            Action <IEndpointDefintionBuilder> builder = b => b.DefineName("endpointName")
                                                         .DefineGroup("endpointGroup")
                                                         .DefineTags("t1")
                                                         .DefineAddress("host", "uniqueName")
                                                         .DefinePassword(AuthenticationToken);

            using (CreateNotifier(builder, token => Task.FromResult(new EndpointHealth(HealthStatus.Offline))))
                await countdown.WaitAsync(TestMaxTime);

            Assert.NotNull(captured);
            Assert.Equal("endpointName", captured.EndpointName);
            Assert.Equal("endpointGroup", captured.GroupName);
            Assert.Equal(new[] { "t1" }, captured.Tags);
            Assert.Equal("host:uniqueName", captured.Address);
        }
        public async Task Exchange_should_try_download_list_of_endpoints_periodically()
        {
            SetupDefaultRegisterEndpointsMock();

            var endpointIdentities1 = new[] { new EndpointIdentity(Guid.NewGuid(), MonitorTypeName, "address1"), new EndpointIdentity(Guid.NewGuid(), MonitorTypeName, "address2") };
            var endpointIdentities2 = new[] { new EndpointIdentity(Guid.NewGuid(), MonitorTypeName, "address1"), new EndpointIdentity(Guid.NewGuid(), MonitorTypeName, "address3") };
            var countdown1          = new AsyncCountdown("endpointIdentities1", 1);
            var countdown2          = new AsyncCountdown("endpointIdentities2", 1);

            var monitorTag = "some_tag";

            SetupExchangeClient(c => c.GetEndpointIdentitiesAsync(monitorTag, It.IsAny <CancellationToken>()),

                                () => { throw new InvalidOperationException(); },
                                () => _awaitableFactory.Return(endpointIdentities1).WithCountdown(countdown1).RunAsync(),
                                () => { throw new InvalidOperationException(); },
                                () => _awaitableFactory.Return(endpointIdentities2).WithCountdown(countdown2).RunAsync());

            using (CreateExchange(new DataExchangeConfig(100, 10, TimeSpan.FromSeconds(1), TimeSpan.FromMilliseconds(1), monitorTag)))
            {
                await countdown1.WaitAsync(TestMaxWaitTime);

                await countdown2.WaitAsync(TestMaxWaitTime);
            }
        }
        public async Task Exchange_should_upload_monitor_healths_in_buckets()
        {
            SetupDefaultRegisterEndpointsMock();
            var identity = SetupDefaultEndpointIdentitiesMock().First();

            int bucketCount = 10;
            int bucketSize  = 10;
            var uploads     = new List <int>();

            var countdown = new AsyncCountdown(nameof(IHealthMonitorExchangeClient.UploadHealthAsync), bucketCount);

            SetupDefaultHealthUploadMock(x => { uploads.Add(x.Length); countdown.Decrement(); });

            var healths = PrepareEndpointHealths(bucketSize * bucketCount);

            using (var ex = CreateExchange(new DataExchangeConfig(bucketSize * bucketCount, bucketSize, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1), EndpointMetadata.DefaultMonitorTag)))
            {
                foreach (var health in healths)
                {
                    ex.UpdateHealth(identity.Id, health);
                }

                await countdown.WaitAsync(TestMaxWaitTime);
            }

            Assert.Equal(new[] { bucketSize }, uploads.Distinct());
        }
示例#5
0
        public async Task Notifier_should_register_endpoint_again_if_notification_failed_with_EndpointNotFoundException()
        {
            var oldEndpointId        = Guid.NewGuid();
            var newEndpointId        = Guid.NewGuid();
            var oldEndpointCountdown = new AsyncCountdown("oldEndpoint", 1);
            var newEndpointCountdown = new AsyncCountdown("newEndpoint", 1);

            _mockClient
            .SetupSequence(c => c.RegisterEndpointAsync(It.IsAny <EndpointDefinition>(), It.IsAny <CancellationToken>()))
            .Returns(Task.FromResult(oldEndpointId))
            .Returns(Task.FromResult(newEndpointId));

            _mockClient
            .Setup(c => c.SendHealthUpdateAsync(oldEndpointId, AuthenticationToken, It.IsAny <HealthUpdate>(), It.IsAny <CancellationToken>()))
            .Returns(() => _awaitableFactory
                     .Throw(new EndpointNotFoundException())
                     .WithCountdown(oldEndpointCountdown)
                     .RunAsync());

            _mockClient
            .Setup(c => c.SendHealthUpdateAsync(newEndpointId, AuthenticationToken, It.IsAny <HealthUpdate>(), It.IsAny <CancellationToken>()))
            .Returns(() => _awaitableFactory
                     .Return()
                     .WithCountdown(newEndpointCountdown)
                     .RunAsync());

            using (CreateNotifier())
            {
                await oldEndpointCountdown.WaitAsync(TestMaxTime);

                await newEndpointCountdown.WaitAsync(TestMaxTime);
            }
        }
        public async Task Executor_should_execute_tasks_until_disposal()
        {
            var task1Name  = "task1";
            var task2Name  = "task2";
            var countdown1 = new AsyncCountdown(task1Name, 10);
            var counter1   = new AsyncCounter();
            var countdown2 = new AsyncCountdown(task2Name, 10);
            var counter2   = new AsyncCounter();

            using (var executor = ContinuousTaskExecutor <string> .StartExecutor(Mock.Of <ITimeCoordinator>()))
            {
                Assert.True(executor.TryRegisterTaskFor(task1Name, (item, token) => StartTaskAsync(countdown1, counter1, token)));
                await countdown1.WaitAsync(_testTimeout);

                Assert.True(executor.TryRegisterTaskFor(task2Name, (item, token) => StartTaskAsync(countdown2, counter2, token)));
                await countdown2.WaitAsync(_testTimeout);

                // check that task 1 still works
                await countdown1.ResetTo(10).WaitAsync(_testTimeout);
            }

            var expected1 = counter1.Value;
            var expected2 = counter2.Value;
            await Task.Delay(200);

            Assert.Equal(expected1, counter1.Value);
            Assert.Equal(expected2, counter2.Value);
        }
        public async Task Executor_should_continue_processing_other_tasks_when_one_finish()
        {
            var task1Name     = "task1";
            var task2Name     = "task2";
            var countdown1    = new AsyncCountdown(task1Name, 10);
            var task2Finished = new SemaphoreSlim(0);

            using (var executor = ContinuousTaskExecutor <string> .StartExecutor(Mock.Of <ITimeCoordinator>()))
            {
                executor.FinishedTaskFor += item =>
                {
                    if (item == task2Name)
                    {
                        task2Finished.Release();
                    }
                };

                Assert.True(executor.TryRegisterTaskFor(task1Name, (item, token) => StartTaskAsync(token, b => b.WithCountdown(countdown1))));
                await countdown1.WaitAsync(_testTimeout);

                Assert.True(executor.TryRegisterTaskFor(task2Name, (item, token) => Task.Delay(25, token)));

                await task2Finished.WaitAsync(_testTimeout);

                // check that task 1 still works
                await countdown1.ResetTo(10).WaitAsync(_testTimeout);
            }
        }
示例#8
0
        public async Task Notifier_should_survive_communication_errors_and_eventually_restore_connectivity()
        {
            var healthUpdateCountdown  = new AsyncCountdown("update", 10);
            var healthUpdateCountdown2 = new AsyncCountdown("update2", 10);
            var registrationCountdown  = new AsyncCountdown("registration", 10);
            var intervalCountdown      = new AsyncCountdown("interval", 10);
            var delayCountdown         = new AsyncCountdown("delay", 10);
            var healthCheckInterval    = TimeSpan.FromMilliseconds(127);
            var endpointId             = Guid.NewGuid();


            var workingHealthUpdate    = _awaitableFactory.Return().WithCountdown(healthUpdateCountdown2);
            var notWorkingHealthUpdate = _awaitableFactory.Throw(new TaskCanceledException()).WithCountdown(healthUpdateCountdown);
            var currentHealthUpdate    = notWorkingHealthUpdate;

            var notWorkingRegistration = _awaitableFactory.Throw <Guid>(new TaskCanceledException()).WithCountdown(registrationCountdown);
            var workingRegistration    = _awaitableFactory.Return(endpointId);
            var currentRegistration    = notWorkingRegistration;

            var notWorkingHealthCheckInterval = _awaitableFactory.Throw <TimeSpan>(new TaskCanceledException()).WithCountdown(intervalCountdown);
            var workingHealthCheckInterval    = _awaitableFactory.Return(healthCheckInterval);
            var currentHealthCheckInterval    = notWorkingHealthCheckInterval;

            _mockClient.Setup(c => c.SendHealthUpdateAsync(It.IsAny <Guid>(), AuthenticationToken, It.IsAny <HealthUpdate>(), It.IsAny <CancellationToken>()))
            .Returns(() => currentHealthUpdate.RunAsync());

            _mockClient.Setup(c => c.RegisterEndpointAsync(It.IsAny <EndpointDefinition>(), It.IsAny <CancellationToken>()))
            .Returns(() => currentRegistration.RunAsync());

            _mockClient.Setup(c => c.GetHealthCheckIntervalAsync(It.IsAny <CancellationToken>()))
            .Returns(() => currentHealthCheckInterval.RunAsync());

            _mockTimeCoordinator.Setup(c => c.Delay(healthCheckInterval, It.IsAny <CancellationToken>()))
            .Returns(() => _awaitableFactory.Return().WithCountdown(delayCountdown).RunAsync());

            using (CreateNotifier())
            {
                await registrationCountdown.WaitAsync(TestMaxTime);

                currentRegistration = workingRegistration;

                await healthUpdateCountdown.WaitAsync(TestMaxTime);

                currentHealthUpdate = workingHealthUpdate;

                await healthUpdateCountdown2.WaitAsync(TestMaxTime);

                await intervalCountdown.WaitAsync(TestMaxTime);

                currentHealthCheckInterval = workingHealthCheckInterval;

                await delayCountdown.WaitAsync(TestMaxTime);
            }
        }
        public async Task Exchange_should_download_list_of_endpoints()
        {
            SetupDefaultRegisterEndpointsMock();

            var endpointIdentitiesGetCountdown = new AsyncCountdown(nameof(IHealthMonitorExchangeClient.GetEndpointIdentitiesAsync), 1);

            var ids = SetupDefaultEndpointIdentitiesMock(cfg => cfg.WithCountdown(endpointIdentitiesGetCountdown));

            using (CreateExchange())
                await endpointIdentitiesGetCountdown.WaitAsync(TimeSpan.FromSeconds(5));

            _endpointRegistry.Verify(r => r.UpdateEndpoints(ids));
        }
        public async Task Notifier_should_retry_sending_health_updates_according_to_recommened_backOff_strategy_in_case_of_exceptions()
        {
            var endpointId = Guid.NewGuid();

            SetupEndpointRegistration(endpointId);
            var checkInterval = TimeSpan.FromMilliseconds(127);

            SetupHealthCheckInterval(checkInterval);
            var minRepeats = 10;
            var countdown  = new AsyncCountdown("update", minRepeats);
            var updates    = new ConcurrentQueue <HealthUpdate>();

            var backOffPlan = new BackOffPlan(null, false);

            _mockClient
            .Setup(c => c.SendHealthUpdateAsync(endpointId, AuthenticationToken, It.IsAny <HealthUpdate>(), It.IsAny <CancellationToken>()))
            .Returns((Guid id, string authToken, HealthUpdate upd, CancellationToken token) =>
            {
                updates.Enqueue(upd);
                return(_awaitableFactory
                       .Throw(new InvalidOperationException())
                       .WithCountdown(countdown)
                       .RunAsync());
            });

            using (CreateNotifier())
                await countdown.WaitAsync(TestMaxTime);

            int expectedSeconds = 1;

            for (int i = 0; i < minRepeats; ++i)
            {
                backOffPlan = new BackOffPlan(TimeSpan.FromSeconds(Math.Min(expectedSeconds, MaxEndpointNotifierRetryDelayInSecs)), true);

                _mockBackOffStategy
                .Setup(b => b.GetCurrent(TimeSpan.FromSeconds(expectedSeconds), It.IsAny <CancellationToken>()))
                .Returns(Task.FromResult(backOffPlan));

                _mockTimeCoordinator.Verify(c => c.Delay(TimeSpan.FromSeconds(expectedSeconds), It.IsAny <CancellationToken>()));

                expectedSeconds = Math.Min(expectedSeconds *= 2, MaxEndpointNotifierRetryDelayInSecs);
            }

            _mockTimeCoordinator.Verify(c => c.Delay(checkInterval, It.IsAny <CancellationToken>()), Times.Once);

            Assert.Equal(1, updates.Distinct().Count());
        }
        public async Task Exchange_should_try_upload_supported_monitor_types_on_start_until_they_succeeds()
        {
            var countdown = new AsyncCountdown(nameof(IHealthMonitorExchangeClient.RegisterMonitorsAsync), 1);

            SetupExchangeClient(
                c => c.RegisterMonitorsAsync(It.IsAny <IEnumerable <string> >(), It.IsAny <CancellationToken>()),

                () => { throw new InvalidOperationException(); },
                () => { throw new InvalidOperationException(); },
                () => _awaitableFactory.Return().WithCountdown(countdown).RunAsync()
                );

            SetupDefaultEndpointIdentitiesMock();

            using (CreateExchange(new DataExchangeConfig(100, 10, TimeSpan.FromMilliseconds(1), TimeSpan.FromSeconds(1), EndpointMetadata.DefaultMonitorTag)))
                await countdown.WaitAsync(TestMaxWaitTime);
        }
        public async Task Exchange_should_try_download_list_of_endpoints_periodically_until_disposal()
        {
            var countdown = new AsyncCountdown(nameof(IHealthMonitorExchangeClient.RegisterMonitorsAsync), 10);
            var counter   = new AsyncCounter();

            SetupDefaultRegisterEndpointsMock();

            _exchangeClient.Setup(c => c.GetEndpointIdentitiesAsync(EndpointMetadata.DefaultMonitorTag, It.IsAny <CancellationToken>()))
            .Returns(() => _awaitableFactory.Throw <EndpointIdentity[]>(new InvalidOperationException()).WithCountdown(countdown).WithCounter(counter).RunAsync());

            using (CreateExchange(new DataExchangeConfig(100, 10, TimeSpan.FromSeconds(1), TimeSpan.FromMilliseconds(1), EndpointMetadata.DefaultMonitorTag)))
                await countdown.WaitAsync(TestMaxWaitTime);

            var capturedCalls = counter.Value;

            Assert.True(capturedCalls > 0, "capturedCalls>0");

            await Task.Delay(PostRunDelay);

            Assert.Equal(capturedCalls, counter.Value);
        }
        public async Task Executor_should_immediately_break_the_loop_on_cancelation()
        {
            var timeCoordinator  = new Mock <ITimeCoordinator>();
            var countdown        = new AsyncCountdown("task", 1);
            var taskNotCancelled = false;

            using (var executor = ContinuousTaskExecutor <string> .StartExecutor(timeCoordinator.Object))
            {
                executor.TryRegisterTaskFor("task", async(item, token) =>
                {
                    countdown.Decrement();
                    await Task.Delay(_testTimeout, token);
                    taskNotCancelled = true;
                });

                await countdown.WaitAsync(_testTimeout);
            }

            Assert.False(taskNotCancelled, "Task was not cancelled");
            timeCoordinator.Verify(c => c.Delay(It.IsAny <TimeSpan>(), It.IsAny <CancellationToken>()), Times.Never, "Executor should not trigger any delay");
        }
示例#14
0
        public async Task Notifier_should_cancel_health_check_on_dispose()
        {
            SetupEndpointRegistration(Guid.NewGuid());
            SetupHealthCheckInterval(TimeSpan.FromMilliseconds(1));

            var notCancelled = false;
            var countdown    = new AsyncCountdown("healthCheck", 1);
            Func <CancellationToken, Task <EndpointHealth> > healthCheck = async token =>
            {
                countdown.Decrement();
                await Task.Delay(TestMaxTime, token);

                notCancelled = true;
                return(new EndpointHealth(HealthStatus.Healthy));
            };

            using (CreateNotifier(healthCheck))
                await countdown.WaitAsync(TestMaxTime);

            Assert.False(notCancelled);
        }
        public async Task Monitor_should_start_checking_the_health_of_endpoints_until_disposed()
        {
            var endpoint1Countdown = new AsyncCountdown("endpoint1", 2);
            var endpoint2Countdown = new AsyncCountdown("endpoint2", 1);
            var endpoint3Countdown = new AsyncCountdown("endpoint3", 2);

            var counters     = new[] { new AsyncCounter(), new AsyncCounter(), new AsyncCounter() };
            var healthCheck1 = _awaitableFactory.Return(new HealthInfo(HealthStatus.Healthy)).WithCountdown(endpoint1Countdown).WithCounter(counters[0]);
            var healthCheck2 = _awaitableFactory.Return(new HealthInfo(HealthStatus.Healthy)).WithCountdown(endpoint2Countdown).WithCounter(counters[1]);
            var healthCheck3 = _awaitableFactory.Return(new HealthInfo(HealthStatus.Healthy)).WithCountdown(endpoint3Countdown).WithCounter(counters[2]);

            _mockHealthMonitor.Setup(cfg => cfg.CheckHealthAsync("address1", It.IsAny <CancellationToken>())).Returns(healthCheck1.RunAsync);
            _mockHealthMonitor.Setup(cfg => cfg.CheckHealthAsync("address2", It.IsAny <CancellationToken>())).Returns(healthCheck2.RunAsync);
            _mockHealthMonitor.Setup(cfg => cfg.CheckHealthAsync("address3", It.IsAny <CancellationToken>())).Returns(healthCheck3.RunAsync);

            var endpoint1 = _endpointRegistry.TryRegister(CreateEndpointIdentity("address1"));

            _endpointRegistry.TryRegister(CreateEndpointIdentity("address2"));

            using (CreateEndpointMonitor(TimeSpan.FromMilliseconds(50)))
            {
                await endpoint1Countdown.WaitAsync(TestMaxWaitTime);

                await endpoint2Countdown.WaitAsync(TestMaxWaitTime);

                _endpointRegistry.TryRegister(CreateEndpointIdentity("address3"));
                await endpoint3Countdown.WaitAsync(TestMaxWaitTime);

                _endpointRegistry.TryUnregister(endpoint1.Identity);
                // ensure that endpoint 2 still is running, and give time for endpoint 1 to shutdown
                await endpoint2Countdown.ResetTo(10).WaitAsync(TestMaxWaitTime);

                // ensure that endpoint 1 calls does not change, while endpoint 2 still runs
                await AssertValueDidNotChangedAfterOperationAsync(
                    () => counters[0].Value,
                    () => endpoint2Countdown.ResetTo(10).WaitAsync(TestMaxWaitTime));
            }

            await AssertValueDidNotChangedAfterOperationAsync(() => counters.Sum(c => c.Value), () => Task.Delay(200));
        }
        public async Task Exchange_should_retry_uploading_supported_monitor_types_until_disposal()
        {
            var countdown = new AsyncCountdown(nameof(IHealthMonitorExchangeClient.RegisterMonitorsAsync), 10);
            var counter   = new AsyncCounter();

            _exchangeClient
            .Setup(c => c.RegisterMonitorsAsync(It.IsAny <IEnumerable <string> >(), It.IsAny <CancellationToken>()))
            .Returns(() => _awaitableFactory.Throw(new InvalidOperationException()).WithCountdown(countdown).WithCounter(counter).RunAsync());

            SetupDefaultEndpointIdentitiesMock();

            using (CreateExchange(new DataExchangeConfig(100, 10, TimeSpan.FromMilliseconds(1), TimeSpan.FromSeconds(1))))
                await countdown.WaitAsync(TestMaxWaitTime);

            var capturedCalls = counter.Value;

            Assert.True(capturedCalls > 0, "capturedCalls>0");

            await Task.Delay(PostRunDelay);

            Assert.Equal(capturedCalls, counter.Value);
        }
示例#17
0
        public async Task Manager_should_delete_old_stats()
        {
            const int expectedRepeats = 3;

            var age            = TimeSpan.FromHours(1);
            var utcNow         = DateTime.UtcNow;
            var asyncCountdown = new AsyncCountdown("delete old stats", expectedRepeats);
            var asyncCounter   = new AsyncCounter();

            var monitorSettings = new Mock <IMonitorSettings>();

            monitorSettings.Setup(s => s.StatsHistoryMaxAge).Returns(age);

            var timeCoordinator = new Mock <ITimeCoordinator>();

            timeCoordinator.Setup(c => c.UtcNow).Returns(utcNow);

            var endpointMetricsCoordinator = new Mock <IEndpointMetricsForwarderCoordinator>();

            var repository = new Mock <IEndpointStatsRepository>();

            repository.Setup(r => r.DeleteStatisticsOlderThan(utcNow - age, It.IsAny <int>())).Returns(() =>
            {
                asyncCountdown.Decrement();
                asyncCounter.Increment();

                const int deletedItemsCount = 127;
                return(asyncCounter.Value >= expectedRepeats ? 0 : deletedItemsCount);
            });

            using (new EndpointStatsManager(repository.Object, monitorSettings.Object, timeCoordinator.Object, endpointMetricsCoordinator.Object))
                await asyncCountdown.WaitAsync(MaxTestTime);

            await Task.Delay(TimeSpan.FromMilliseconds(500));

            //it should stop calling cleanup when there are no more items to be cleaned
            Assert.Equal(expectedRepeats, asyncCounter.Value);
        }
        public async Task Exchange_should_retry_health_update_send_in_case_of_errors()
        {
            var count     = 10;
            var countdown = new AsyncCountdown(nameof(IHealthMonitorExchangeClient.UploadHealthAsync), count);

            SetupDefaultRegisterEndpointsMock();
            var identity = SetupDefaultEndpointIdentitiesMock().First();

            var attempts = 10;

            SetupDefaultHealthUploadMock(updates =>
            {
                if (attempts-- > 0)
                {
                    throw new Exception();
                }

                foreach (var update in updates)
                {
                    countdown.Decrement();
                }
            });


            var config = new DataExchangeConfig(100, count, TimeSpan.FromMilliseconds(1), TimeSpan.FromSeconds(1), EndpointMetadata.DefaultMonitorTag);

            var healths = PrepareEndpointHealths(count);

            using (var ex = CreateExchange(config))
            {
                foreach (var health in healths)
                {
                    ex.UpdateHealth(identity.Id, health);
                }

                await countdown.WaitAsync(TestMaxWaitTime);
            }
        }
        public async Task Exchange_should_retry_health_update_send_until_disposal()
        {
            var countdown = new AsyncCountdown(nameof(IHealthMonitorExchangeClient.UploadHealthAsync), 10);

            SetupDefaultRegisterEndpointsMock();
            var identity = SetupDefaultEndpointIdentitiesMock().First();

            int calls = 0;

            SetupDefaultHealthUploadMock(x =>
            {
                Interlocked.Increment(ref calls);
                countdown.Decrement();
                if (calls > 1)
                {
                    throw new InvalidOperationException();
                }
            });

            var healths = PrepareEndpointHealths(2);

            using (var ex = CreateExchange(new DataExchangeConfig(100, 1, TimeSpan.FromMilliseconds(1), TimeSpan.FromSeconds(1), EndpointMetadata.DefaultMonitorTag)))
            {
                foreach (var health in healths)
                {
                    ex.UpdateHealth(identity.Id, health);
                }
                await countdown.WaitAsync(TestMaxWaitTime);
            }

            var capturedCalls = calls;

            Assert.True(capturedCalls > 0, "capturedCalls>0");

            await Task.Delay(PostRunDelay);

            Assert.Equal(capturedCalls, calls);
        }
        public async Task Notifier_should_send_notifications_within_specified_time_span()
        {
            var minimumChecks = 3;

            var countdown  = new AsyncCountdown("notifications", minimumChecks);
            var endpointId = Guid.NewGuid();
            var interval   = TimeSpan.FromMilliseconds(300);

            SetupHealthCheckInterval(interval);

            SetupEndpointRegistration(endpointId);

            _mockClient
            .Setup(c => c.SendHealthUpdateAsync(endpointId, AuthenticationToken, It.IsAny <HealthUpdate>(), It.IsAny <CancellationToken>()))
            .Returns(() => _awaitableFactory.Return().WithDelay(TimeSpan.FromMilliseconds(100)).WithTimeline("updateHealth").WithCountdown(countdown).RunAsync());

            _mockTimeCoordinator
            .Setup(c => c.Delay(interval, It.IsAny <CancellationToken>()))
            .Returns(() => _awaitableFactory.Return().WithDelay(TimeSpan.FromMilliseconds(50)).WithTimeline("delay").RunAsync());

            using (CreateNotifier())
                await countdown.WaitAsync(TestMaxTime);

            var actualEventTimeline = _awaitableFactory.GetOrderedTimelineEvents()
                                      .Select(eventName => eventName == "updateHealth_start" || eventName == "delay_start" ? "update_start" : eventName)
                                      .Select(eventName => eventName == "updateHealth_finish" || eventName == "delay_finish" ? "update_finish" : eventName)
                                      .Take(minimumChecks * 4)
                                      .ToArray();

            for (int i = 0; i < minimumChecks; i++)
            {
                var actualSequence = actualEventTimeline.Skip(i * 4).Take(4).ToList();
                Assert.Equal("update_start", actualSequence.First());
                Assert.Equal("update_finish", actualSequence.Last());
                Assert.Equal(2, actualSequence.Count(s => s == "update_start"));
                Assert.Equal(2, actualSequence.Count(s => s == "update_finish"));
            }
        }
        public async Task Manager_should_delete_old_stats()
        {
            var age            = TimeSpan.FromHours(1);
            var utcNow         = DateTime.UtcNow;
            var asyncCountdown = new AsyncCountdown("delete old stats", 1);

            var monitorSettings = new Mock <IMonitorSettings>();

            monitorSettings.Setup(s => s.StatsHistoryMaxAge).Returns(age);

            var timeCoordinator = new Mock <ITimeCoordinator>();

            timeCoordinator.Setup(c => c.UtcNow).Returns(utcNow);

            var endpointMetricsCoordinator = new Mock <IEndpointMetricsForwarderCoordinator>();

            var repository = new Mock <IEndpointStatsRepository>();

            repository.Setup(r => r.DeleteStatisticsOlderThan(utcNow - age)).Callback(() => asyncCountdown.Decrement());

            using (new EndpointStatsManager(repository.Object, monitorSettings.Object, timeCoordinator.Object, endpointMetricsCoordinator.Object))
                await asyncCountdown.WaitAsync(MaxTestTime);
        }
        public async Task Executor_should_cancel_all_tasks_on_disposal_and_report_all_finished()
        {
            var task1NotCancelled = false;
            var task2NotCancelled = false;
            var task1             = "task1";
            var task2             = "task2";
            var task1Ran          = new AsyncCountdown(task1, 1);
            var task2Ran          = new AsyncCountdown(task2, 1);
            var completed         = new ConcurrentQueue <string>();

            using (var executor = ContinuousTaskExecutor <string> .StartExecutor(Mock.Of <ITimeCoordinator>()))
            {
                executor.FinishedTaskFor += item => completed.Enqueue(item);

                executor.TryRegisterTaskFor(task1, async(item, token) =>
                {
                    task1Ran.Decrement();
                    await Task.Delay(_testTimeout, token);
                    task1NotCancelled = true;
                });
                executor.TryRegisterTaskFor(task2, async(item, token) =>
                {
                    task2Ran.Decrement();
                    await Task.Delay(_testTimeout, token);
                    task2NotCancelled = true;
                });

                await task1Ran.WaitAsync(_testTimeout);

                await task2Ran.WaitAsync(_testTimeout);
            }
            Assert.False(task1NotCancelled, "task1NotCancelled");
            Assert.False(task2NotCancelled, "task2NotCancelled");

            CollectionAssert.AreEquivalent(new[] { task1, task2 }, completed);
        }
        public async Task Monitor_should_check_endpoint_health_with_regular_intervals()
        {
            var interval      = TimeSpan.FromMilliseconds(200);
            var healthCounter = new AsyncCountdown("health", 1);
            var delayCounter  = new AsyncCountdown("delay", 1);

            _mockHealthMonitor.Setup(cfg => cfg.CheckHealthAsync("address", It.IsAny <CancellationToken>())).Returns(() => _awaitableFactory.Return(new HealthInfo(HealthStatus.Healthy)).WithTimeline("health").WithCountdown(healthCounter).RunAsync());
            _mockTimeCoordinator.Setup(cfg => cfg.Delay(interval, It.IsAny <CancellationToken>())).Returns(() => _awaitableFactory.Return().WithDelay(interval).WithTimeline("delay").WithCountdown(delayCounter).RunAsync());

            _endpointRegistry.TryRegister(CreateEndpointIdentity("address"));
            using (CreateEndpointMonitor(interval))
                await Task.WhenAll(healthCounter.WaitAsync(TestMaxWaitTime), delayCounter.WaitAsync(TestMaxWaitTime));

            var results = _awaitableFactory.GetTimeline();

            Assert.True(results.Length > 1, "results.Length>1");
            var delayTask  = results[0];
            var healthTask = results[1];

            Assert.Equal(delayTask.Tag, "delay");
            Assert.Equal(healthTask.Tag, "health");

            AssertTimeOrder(delayTask.Started, healthTask.Started, healthTask.Finished, delayTask.Finished);
        }
示例#24
0
        public async Task Notifier_should_send_faulty_health_to_the_API_if_provided_health_method_throws()
        {
            var          endpointId   = Guid.NewGuid();
            HealthUpdate lastCaptured = null;
            var          countdown    = new AsyncCountdown("update", 5);

            SetupHealthCheckInterval(TimeSpan.FromMilliseconds(1));
            SetupEndpointRegistration(endpointId);

            _mockClient.Setup(c => c.SendHealthUpdateAsync(endpointId, AuthenticationToken, It.IsAny <HealthUpdate>(), It.IsAny <CancellationToken>()))
            .Returns((Guid id, string authToken, HealthUpdate upd, CancellationToken token) => _awaitableFactory
                     .Execute(() => lastCaptured = upd)
                     .WithCountdown(countdown)
                     .RunAsync());

            using (CreateNotifier(async token => { await Task.Delay(50, token); throw new InvalidOperationException("some reason"); }))
                await countdown.WaitAsync(TestMaxTime);

            Assert.NotNull(lastCaptured);
            Assert.Equal(HealthStatus.Faulty, lastCaptured.Status);
            Assert.Equal("Unable to collect health information", lastCaptured.Details["reason"]);
            Assert.True(lastCaptured.Details["exception"].StartsWith("System.InvalidOperationException: some reason"));
            Assert.True(lastCaptured.CheckTimeUtc > DateTime.UtcNow.AddMinutes(-1) && lastCaptured.CheckTimeUtc < DateTime.UtcNow.AddMinutes(1));
        }
示例#25
0
        public async Task Notifier_should_send_notifications_within_specified_time_span()
        {
            var minimumChecks         = 3;
            var expectedEventTimeline = new List <string>();

            for (var i = 0; i < minimumChecks; ++i)
            {
                expectedEventTimeline.AddRange(new[] { "updateHealth_start", "delay_start", "update_finish", "update_finish" });
            }

            var countdown  = new AsyncCountdown("notifications", minimumChecks);
            var endpointId = Guid.NewGuid();
            var interval   = TimeSpan.FromMilliseconds(300);

            SetupHealthCheckInterval(interval);

            SetupEndpointRegistration(endpointId);

            _mockClient
            .Setup(c => c.SendHealthUpdateAsync(endpointId, AuthenticationToken, It.IsAny <HealthUpdate>(), It.IsAny <CancellationToken>()))
            .Returns(() => _awaitableFactory.Return().WithDelay(TimeSpan.FromMilliseconds(100)).WithTimeline("updateHealth").WithCountdown(countdown).RunAsync());

            _mockTimeCoordinator
            .Setup(c => c.Delay(interval, It.IsAny <CancellationToken>()))
            .Returns(() => _awaitableFactory.Return().WithDelay(TimeSpan.FromMilliseconds(50)).WithTimeline("delay").RunAsync());

            using (CreateNotifier())
                await countdown.WaitAsync(TestMaxTime);

            var actualEventTimeline = _awaitableFactory.GetOrderedTimelineEvents()
                                      .Select(eventName => (eventName == "updateHealth_finish" || eventName == "delay_finish") ? "update_finish" : eventName)
                                      .Take(minimumChecks * 4)
                                      .ToArray();

            Assert.True(expectedEventTimeline.SequenceEqual(actualEventTimeline), $"Expected:\n{string.Join(",", expectedEventTimeline)}\nGot:\n{string.Join(",", actualEventTimeline)}");
        }