private async Task UploadChangesAsync(EndpointHealthUpdate[] bucket)
 {
     while (true)
     {
         try
         {
             await _exchangeClient.UploadHealthAsync(bucket, _cancellation.Token);
             return;
         }
         catch (OperationCanceledException) when (_cancellation.IsCancellationRequested)
         {
             throw;
         }
         catch (Exception e)
         {
             Logger.Error($"Unable to upload endpoint updates: {e.Message}", e);
             await Task.Delay(_config.UploadRetryInterval, _cancellation.Token);
         }
     }
 }
        public async Task UploadHealthAsync_should_pass_clientCurrentTime_with_request()
        {
            var mockHttp = new MockHttpMessageHandler();
            var mockTimeCoordinator = new Mock<ITimeCoordinator>();
            var mockCredentialsProvider = new Mock<ICredentialsProvider>();
            var currentTimeUtc = DateTime.UtcNow;
            mockTimeCoordinator.Setup(c => c.UtcNow).Returns(currentTimeUtc);
            var client = new TestableHealthMonitorExchangeClient(mockHttp, mockTimeCoordinator.Object, mockCredentialsProvider.Object);

            mockHttp.Setup(
                $"http://mock/api/endpoints/health?clientCurrentTime={currentTimeUtc.ToString("u", CultureInfo.InvariantCulture)}", 
                req => new HttpResponseMessage(HttpStatusCode.OK));

            try
            {
                var update = new EndpointHealthUpdate(Guid.NewGuid(), new EndpointHealth(DateTime.UtcNow, TimeSpan.Zero, EndpointStatus.Faulty));
                await client.UploadHealthAsync(new[] { update }, CancellationToken.None);
            }
            catch (Exception e)
            {
                throw new InvalidOperationException($"Client should not throw, but it did: {e.Message}", e);
            }
        }