public async Task TransientErrorInSecondBatch_FastFailsRest_OverwritesNonTransientResult() { var batchSize = 10; Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter(); string cloudEndpointId = Guid.NewGuid().ToString(); var cloudProxy = ThrowingCloudProxy .Create() .WithBatchSize(batchSize) .WithReportErrorInBatch(ThrowingCloudProxy.Throw <Exception>()) .WithReportErrorInBatch(ThrowingCloudProxy.Throw <Client.Exceptions.IotHubException>()) .WithReportSuccessfulBatch() .Build(); Task <Option <ICloudProxy> > GetCloudProxy(string id) => Task.FromResult(Option.Some(cloudProxy)); var cloudEndpoint = new CloudEndpoint(cloudEndpointId, GetCloudProxy, routingMessageConverter); IProcessor cloudMessageProcessor = cloudEndpoint.CreateProcessor(); var sinkResult = await cloudMessageProcessor.ProcessAsync(GetMessages("device1", 3 * batchSize), CancellationToken.None); Assert.False(sinkResult.IsSuccessful); Assert.Equal(0, sinkResult.Succeeded.Count); Assert.Equal(2 * batchSize, sinkResult.Failed.Count); Assert.Equal(1 * batchSize, sinkResult.InvalidDetailsList.Count); Assert.True(sinkResult.SendFailureDetails.HasValue); Assert.Equal(FailureKind.Transient, sinkResult.SendFailureDetails.Expect(() => new Exception()).FailureKind); }
public async Task TransientErrorInSecondBatch_OverwritesNonTransientFailureDetails() { var batchSize = 10; Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter(); string cloudEndpointId = Guid.NewGuid().ToString(); var cloudProxy = ThrowingCloudProxy .CreateWithResponses(3, ThrowingCloudProxy.Success()) .Then(ThrowingCloudProxy.Throw <Exception>()) // non-transient error .ThenMany(batchSize - 4, ThrowingCloudProxy.Success()) // first batch ends here (3 success + 1 fail -> 10 - 4 to go) .ThenMany(3, ThrowingCloudProxy.Success()) .Then(ThrowingCloudProxy.Throw <Client.Exceptions.IotHubException>()) // transient error .ThenMany(batchSize - 4, ThrowingCloudProxy.Success()) // second batch ends here .ThenMany(1 * batchSize, ThrowingCloudProxy.Success()) .Build(); Task <Option <ICloudProxy> > GetCloudProxy(string id) => Task.FromResult(Option.Some(cloudProxy)); var cloudEndpoint = new CloudEndpoint(cloudEndpointId, GetCloudProxy, routingMessageConverter); IProcessor cloudMessageProcessor = cloudEndpoint.CreateProcessor(); var sinkResult = await cloudMessageProcessor.ProcessAsync(GetMessages("device1", 3 * batchSize), CancellationToken.None); Assert.False(sinkResult.IsSuccessful); Assert.Equal(batchSize, sinkResult.Succeeded.Count); Assert.Equal(batchSize, sinkResult.Failed.Count); Assert.Equal(batchSize, sinkResult.InvalidDetailsList.Count); Assert.True(sinkResult.SendFailureDetails.HasValue); Assert.Equal(FailureKind.Transient, sinkResult.SendFailureDetails.Expect(() => new Exception()).FailureKind); }
public async Task NonTransientErrorInFirstBatch_LetsTryTheRest_ButReportsSendFailure() { var batchSize = 10; Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter(); string cloudEndpointId = Guid.NewGuid().ToString(); var cloudProxy = ThrowingCloudProxy .Create() .WithBatchSize(batchSize) .WithReportErrorInBatch(ThrowingCloudProxy.Throw <Exception>()) .WithReportSuccessfulBatch(2) .Build(); Task <Option <ICloudProxy> > GetCloudProxy(string id) => Task.FromResult(Option.Some(cloudProxy)); var cloudEndpoint = new CloudEndpoint(cloudEndpointId, GetCloudProxy, routingMessageConverter); IProcessor cloudMessageProcessor = cloudEndpoint.CreateProcessor(); var sinkResult = await cloudMessageProcessor.ProcessAsync(GetMessages("device1", 3 * batchSize), CancellationToken.None); Assert.True(sinkResult.IsSuccessful); // non-transient errors are ignored, but reported in SendFailureDetails Assert.Equal(2 * batchSize, sinkResult.Succeeded.Count); Assert.Equal(0, sinkResult.Failed.Count); Assert.Equal(batchSize, sinkResult.InvalidDetailsList.Count); Assert.True(sinkResult.SendFailureDetails.HasValue); Assert.Equal(FailureKind.InvalidInput, sinkResult.SendFailureDetails.Expect(() => new Exception()).FailureKind); }
public async Task TransientErrorInFirstBatch_FastFailsRest() { var batchSize = 10; Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter(); string cloudEndpointId = Guid.NewGuid().ToString(); var cloudProxy = ThrowingCloudProxy .Create() .WithBatchSize(batchSize) .WithReportErrorInBatch(ThrowingCloudProxy.Throw <Client.Exceptions.IotHubException>()) .WithReportSuccessfulBatch(2) .Build(); Task <Try <ICloudProxy> > GetCloudProxy(string id) => Task.FromResult(Try.Success(cloudProxy)); var cloudEndpoint = new CloudEndpoint(cloudEndpointId, GetCloudProxy, routingMessageConverter, true); IProcessor cloudMessageProcessor = cloudEndpoint.CreateProcessor(); var sinkResult = await cloudMessageProcessor.ProcessAsync(GetMessages("device1", 3 * batchSize), CancellationToken.None); // although the test is setup to succeed with batch 2 and 3, they will fast fail because of the first one Assert.False(sinkResult.IsSuccessful); Assert.Equal(0, sinkResult.Succeeded.Count); Assert.Equal(30, sinkResult.Failed.Count); Assert.Equal(0, sinkResult.InvalidDetailsList.Count); Assert.True(sinkResult.SendFailureDetails.HasValue); Assert.Equal(FailureKind.Transient, sinkResult.SendFailureDetails.Expect(() => new Exception()).FailureKind); }
public async Task TransientErrorOfFirstIdentity_DoesNotFastFailsSecondIdentity_ButReportsError() { var batchSize = 10; Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter(); string cloudEndpointId = Guid.NewGuid().ToString(); // this wont fast fail var cloudProxy1 = ThrowingCloudProxy .Create() .WithBatchSize(batchSize) .WithReportSuccessfulBatch(3) .Build(); // this will fast fail after a batch (skipping the second and the third) var cloudProxy2 = ThrowingCloudProxy .Create() .WithBatchSize(batchSize) .WithReportSuccessfulBatch() .WithReportErrorInBatch(ThrowingCloudProxy.Throw <Client.Exceptions.IotHubException>()) .WithReportSuccessfulBatch() .Build(); var proxyMap = new Dictionary <string, ICloudProxy> { ["device1"] = cloudProxy1, ["device2"] = cloudProxy2 }; Task <Option <ICloudProxy> > GetCloudProxy(string id) => Task.FromResult(Option.Some(proxyMap[id])); var cloudEndpoint = new CloudEndpoint(cloudEndpointId, GetCloudProxy, routingMessageConverter); var cloudMessageProcessor = cloudEndpoint.CreateProcessor(); var random = new Random(35325); var messages = GetMessages("device1", 3 * batchSize).Concat(GetMessages("device2", 3 * batchSize)).OrderBy(order => random.Next()).ToList(); var sinkResult = await cloudMessageProcessor.ProcessAsync(messages, CancellationToken.None); Assert.False(sinkResult.IsSuccessful); // one batch went wrong, should report here Assert.Equal(3 * batchSize + 1 * batchSize, sinkResult.Succeeded.Count); // dev1 all good, dev2 1st good Assert.Equal(2 * batchSize, sinkResult.Failed.Count); Assert.Equal(0, sinkResult.InvalidDetailsList.Count); Assert.True(sinkResult.SendFailureDetails.HasValue); Assert.Equal(FailureKind.Transient, sinkResult.SendFailureDetails.Expect(() => new Exception()).FailureKind); }