Пример #1
0
        public async Task ProcessAsync_SendThrowsNonRetryable_Test()
        {
            var throwingDeviceProxy = ThrowingDeviceProxyBuilder
                                      .Create()
                                      .WithThrow <Exception>()
                                      .Build();

            var messageProcessor = this.CreateMessageProcessor(throwingDeviceProxy);

            var message1 = GetMessage();
            var message2 = GetMessage();

            ISinkResult <IRoutingMessage> result = await messageProcessor.ProcessAsync(message1, CancellationToken.None);

            Assert.NotNull(result);
            Assert.Empty(result.Succeeded);
            Assert.Empty(result.Failed);
            Assert.Equal(1, result.InvalidDetailsList.Count);
            Assert.False(result.SendFailureDetails.HasValue);

            ISinkResult <IRoutingMessage> resultBatch = await messageProcessor.ProcessAsync(new[] { message1, message2 }, CancellationToken.None);

            Assert.NotNull(resultBatch);
            Assert.Empty(resultBatch.Succeeded);
            Assert.Empty(resultBatch.Failed);
            Assert.Equal(2, resultBatch.InvalidDetailsList.Count);
            Assert.False(resultBatch.SendFailureDetails.HasValue);
        }
Пример #2
0
            public static void SendFailure(EndpointExecutorFsm fsm, ISinkResult <IMessage> result, Stopwatch stopwatch)
            {
                long latencyInMs = stopwatch.ElapsedMilliseconds;

                if (!Routing.PerfCounter.LogExternalWriteLatency(fsm.Endpoint.IotHubName, fsm.Endpoint.Name, fsm.Endpoint.Type, false, latencyInMs, out string error))
                {
                    Log.LogError((int)EventIds.CounterFailure, "[LogExternalWriteLatencyCounterFailed] {0}", error);
                }

                SendFailureDetails failureDetails = result.SendFailureDetails.GetOrElse(DefaultSendFailureDetails);

                foreach (InvalidDetails <IMessage> invalidDetails in result.InvalidDetailsList)
                {
                    Routing.UserAnalyticsLogger.LogInvalidMessage(fsm.Endpoint.IotHubName, invalidDetails.Item, invalidDetails.FailureKind);
                }

                Log.LogWarning(
                    (int)EventIds.SendFailure,
                    failureDetails.RawException,
                    "[SendFailure] Sending failed. SuccessfulSize: {0}, FailedSize: {1}, InvalidSize: {2}, {3}",
                    result.Succeeded.Count,
                    result.Failed.Count,
                    result.InvalidDetailsList.Count,
                    GetContextString(fsm));

                LogUnhealthyEndpointOpMonError(fsm, failureDetails.FailureKind);
            }
Пример #3
0
        public async Task ModuleMessageProcessor_ProcessAsyncTest_InactiveDeviceProxy()
        {
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            var deviceProxy = new Mock <IDeviceProxy>();

            deviceProxy.Setup(d => d.SendMessageAsync(It.IsAny <IMessage>(), It.IsAny <string>())).Returns(Task.CompletedTask);
            deviceProxy.Setup(d => d.IsActive).Returns(false);
            var    routingMessage        = Mock.Of <IRoutingMessage>();
            string moduleId              = "device1/module1";
            string moduleEndpointAddress = "in1";
            IReadOnlyDictionary <DeviceSubscription, bool> deviceSubscriptions = new ReadOnlyDictionary <DeviceSubscription, bool>(
                new Dictionary <DeviceSubscription, bool>
            {
                [DeviceSubscription.ModuleMessages] = true
            });
            var connectionManager = new Mock <IConnectionManager>();

            connectionManager.Setup(c => c.GetDeviceConnection(It.IsAny <string>())).Returns(Option.Some(deviceProxy.Object));
            connectionManager.Setup(c => c.GetSubscriptions(It.IsAny <string>())).Returns(Option.Some(deviceSubscriptions));
            var moduleEndpoint = new ModuleEndpoint($"{moduleId}/{moduleEndpointAddress}", moduleId, moduleEndpointAddress, connectionManager.Object, routingMessageConverter);

            IProcessor moduleMessageProcessor        = moduleEndpoint.CreateProcessor();
            ISinkResult <IRoutingMessage> sinkResult = await moduleMessageProcessor.ProcessAsync(routingMessage, CancellationToken.None);

            Assert.True(sinkResult.Failed.Contains(routingMessage));
            Assert.Equal(FailureKind.None, sinkResult.SendFailureDetails.Map(x => x.FailureKind).GetOrElse(FailureKind.None));
        }
Пример #4
0
        static async Task EnterDeadCheckpointingAsync(EndpointExecutorFsm thisPtr)
        {
            ICommand next;

            try
            {
                Preconditions.CheckNotNull(thisPtr.currentCheckpointCommand);
                using (var cts = new CancellationTokenSource(thisPtr.config.Timeout))
                {
                    ISinkResult <IMessage> result = thisPtr.currentCheckpointCommand.Result;
                    Events.Checkpoint(thisPtr, result);
                    await thisPtr.Checkpointer.CommitAsync(result.Succeeded, EmptyMessages, thisPtr.lastFailedRevivalTime, thisPtr.unhealthySince, cts.Token);

                    Events.CheckpointSuccess(thisPtr, result);
                }

                next = Commands.DeadSucceed;
                Events.DeadSuccess(thisPtr, thisPtr.currentCheckpointCommand.Result.Succeeded);
            }
            catch (Exception ex)
            {
                Events.CheckpointFailure(thisPtr, ex);
                next = thisPtr.config.ThrowOnDead
                    ? (ICommand)Commands.Throw(ex)
                    : Commands.DeadSucceed;
            }

            await RunInternalAsync(thisPtr, next);
        }
Пример #5
0
        public async Task ProcessAsync_NoConnection_ShoulFailTest()
        {
            var throwingDeviceProxy = ThrowingDeviceProxyBuilder
                                      .Create()
                                      .WithActiveStatus(false)
                                      .Build();

            var messageProcessor = this.CreateMessageProcessor(throwingDeviceProxy);

            var message1 = GetMessage();
            var message2 = GetMessage();

            ISinkResult <IRoutingMessage> result = await messageProcessor.ProcessAsync(message1, CancellationToken.None);

            Assert.NotNull(result);
            Assert.Empty(result.Succeeded);
            Assert.Equal(1, result.Failed.Count);
            Assert.Empty(result.InvalidDetailsList);
            Assert.True(result.SendFailureDetails.HasValue);

            ISinkResult <IRoutingMessage> resultBatch = await messageProcessor.ProcessAsync(new[] { message1, message2 }, CancellationToken.None);

            Assert.NotNull(resultBatch);
            Assert.Empty(resultBatch.Succeeded);
            Assert.Equal(2, resultBatch.Failed.Count);
            Assert.Empty(resultBatch.InvalidDetailsList);
            Assert.True(resultBatch.SendFailureDetails.HasValue);
        }
Пример #6
0
        public async Task ProcessAsyncTest()
        {
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();

            const string Mod1Id        = "device1/module1";
            const string ModEndpointId = "in1";

            var deviceProxyMock = new Mock <IDeviceProxy>();

            deviceProxyMock.Setup(c => c.SendMessageAsync(It.IsAny <IMessage>(), It.Is <string>((ep) => ep.Equals(ModEndpointId, StringComparison.OrdinalIgnoreCase))))
            .Returns(Task.CompletedTask);

            deviceProxyMock.SetupGet(p => p.IsActive).Returns(true);

            IReadOnlyDictionary <DeviceSubscription, bool> deviceSubscriptions = new ReadOnlyDictionary <DeviceSubscription, bool>(
                new Dictionary <DeviceSubscription, bool>
            {
                [DeviceSubscription.ModuleMessages] = true
            });
            var connectionManager = new Mock <IConnectionManager>();

            connectionManager.Setup(c => c.GetDeviceConnection(It.IsAny <string>())).Returns(Option.Some(deviceProxyMock.Object));
            connectionManager.Setup(c => c.GetSubscriptions(It.IsAny <string>())).Returns(Option.Some(deviceSubscriptions));

            byte[] messageBody = Encoding.UTF8.GetBytes("Message body");
            var    properties  = new Dictionary <string, string>()
            {
                { "Prop1", "Val1" },
                { "Prop2", "Val2" },
            };

            var systemProperties = new Dictionary <string, string>
            {
                { SystemProperties.DeviceId, Mod1Id }
            };

            var message1 = new RoutingMessage(TelemetryMessageSource.Instance, messageBody, properties, systemProperties);
            var message2 = new RoutingMessage(TelemetryMessageSource.Instance, messageBody, properties, systemProperties);

            var        moduleEndpoint         = new ModuleEndpoint($"{Mod1Id}/{ModEndpointId}", Mod1Id, ModEndpointId, connectionManager.Object, routingMessageConverter);
            IProcessor moduleMessageProcessor = moduleEndpoint.CreateProcessor();

            ISinkResult <IRoutingMessage> result = await moduleMessageProcessor.ProcessAsync(message1, CancellationToken.None);

            Assert.NotNull(result);
            Assert.NotEmpty(result.Succeeded);
            Assert.Empty(result.Failed);
            Assert.Empty(result.InvalidDetailsList);
            Assert.False(result.SendFailureDetails.HasValue);

            ISinkResult <IRoutingMessage> resultBatch = await moduleMessageProcessor.ProcessAsync(new[] { message1, message2 }, CancellationToken.None);

            Assert.NotNull(resultBatch);
            Assert.NotEmpty(resultBatch.Succeeded);
            Assert.Empty(resultBatch.Failed);
            Assert.Empty(resultBatch.InvalidDetailsList);
            Assert.False(resultBatch.SendFailureDetails.HasValue);
        }
Пример #7
0
 public static void Checkpoint(EndpointExecutorFsm fsm, ISinkResult <IMessage> result)
 {
     Log.LogDebug(
         (int)EventIds.Checkpoint,
         "[Checkpoint] Checkpointing began. CheckpointOffset: {0}, SuccessfulSize: {1}, RemainingSize: {2}, {3}",
         fsm.Status.CheckpointerStatus.Offset,
         result.Succeeded.Count + result.InvalidDetailsList.Count,
         result.Failed.Count,
         GetContextString(fsm));
 }
Пример #8
0
        public void Merge(ISinkResult <T> other)
        {
            this.Succeeded.AddRange(other.Succeeded);
            this.Failed.AddRange(other.Failed);
            this.InvalidDetailsList.AddRange(other.InvalidDetailsList);

            if (IsMoreSignificant(this.SendFailureDetails, other.SendFailureDetails))
            {
                this.SendFailureDetails = other.SendFailureDetails;
            }
        }
Пример #9
0
        public async Task TestSendCompletes()
        {
            var retryPolicy          = new RetryPolicy(new ErrorDetectionStrategy(_ => true), new FixedInterval(3, TimeSpan.FromMilliseconds(10)));
            var items                = new[] { 1, 2, 3, 4, 5, 6 };
            var testSink             = new PartialFailureSink <int>(new Exception());
            var sink                 = new RetryingSink <int>(testSink, retryPolicy);
            ISinkResult <int> result = await sink.ProcessAsync(items, CancellationToken.None);

            await sink.CloseAsync(CancellationToken.None);

            Assert.True(result.IsSuccessful);
            Assert.Equal(new List <int>(items), result.Succeeded);
        }
Пример #10
0
            public static void CheckpointSuccess(EndpointExecutorFsm fsm, ISinkResult <IMessage> result)
            {
                Log.LogInformation((int)EventIds.CheckpointSuccess, "[CheckpointSuccess] Checkpointing succeeded. CheckpointOffset: {0}, {1}",
                                   fsm.Status.CheckpointerStatus.Offset, GetContextString(fsm));

                IList <IMessage> invalidMessages = result.InvalidDetailsList.Select(d => d.Item).ToList();

                SetProcessingInternalCounters(fsm, "Success", result.Succeeded);
                SetProcessingInternalCounters(fsm, "Failure", result.Failed);
                SetProcessingInternalCounters(fsm, "Invalid", invalidMessages);

                SetSuccessfulEgressUserMetricCounter(fsm, result.Succeeded);
                SetInvalidEgressUserMetricCounter(fsm, invalidMessages);
            }
Пример #11
0
        public async Task SmokeTask()
        {
            var         factory = new RetryingSinkFactory <int>(new TestSinkFactory <int>(), RetryPolicy.NoRetry);
            ISink <int> sink    = await factory.CreateAsync("hub");

            ISinkResult <int> result = await sink.ProcessAsync(1, CancellationToken.None);

            Assert.True(result.IsSuccessful);
            Assert.Equal(new List <int> {
                1
            }, result.Succeeded);
            Assert.False(result.Failed.Any());
            Assert.False(result.InvalidDetailsList.Any());

            await sink.CloseAsync(CancellationToken.None);
        }
Пример #12
0
        public async Task Events_CloudProxyNotFoundWithDeviceInvalidStateException_DropMessage_Test()
        {
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            var    routingMessage  = Mock.Of <IRoutingMessage>();
            string cloudEndpointId = Guid.NewGuid().ToString();

            Mock.Get(routingMessage).Setup(rm => rm.SystemProperties).Returns(new Dictionary <string, string> {
                { "connectionDeviceId", "myConnectionDeviceId" }
            });
            var cloudEndpoint = new CloudEndpoint(cloudEndpointId, id => Task.FromResult(Try <ICloudProxy> .Failure(new DeviceInvalidStateException("Device removed from scope"))), routingMessageConverter, trackDeviceState: true);

            IProcessor cloudMessageProcessor         = cloudEndpoint.CreateProcessor();
            ISinkResult <IRoutingMessage> sinkResult = await cloudMessageProcessor.ProcessAsync(routingMessage, CancellationToken.None);

            Assert.Equal(FailureKind.InvalidInput, sinkResult.SendFailureDetails.OrDefault().FailureKind);
            Assert.Equal(typeof(DeviceInvalidStateException), sinkResult.SendFailureDetails.OrDefault().RawException.GetType());
        }
Пример #13
0
        public async Task Events_CloudProxyNotFoundTest()
        {
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            var    routingMessage  = Mock.Of <IRoutingMessage>();
            string cloudEndpointId = Guid.NewGuid().ToString();

            Mock.Get(routingMessage).Setup(rm => rm.SystemProperties).Returns(new Dictionary <string, string> {
                { "connectionDeviceId", "myConnectionDeviceId" }
            });
            var cloudEndpoint = new CloudEndpoint(cloudEndpointId, id => Task.FromResult(Option.None <ICloudProxy>()), routingMessageConverter);

            IProcessor cloudMessageProcessor         = cloudEndpoint.CreateProcessor();
            ISinkResult <IRoutingMessage> sinkResult = await cloudMessageProcessor.ProcessAsync(routingMessage, CancellationToken.None);

            Assert.Equal(FailureKind.None, sinkResult.SendFailureDetails.OrDefault().FailureKind);
            Assert.Equal(typeof(EdgeHubConnectionException), sinkResult.SendFailureDetails.OrDefault().RawException.GetType());
        }
Пример #14
0
        public async Task ModuleMessageProcessor_RetryableExceptionTest(Exception exception, bool isRetryable)
        {
            // Arrange
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            var deviceProxy = new Mock <IDeviceProxy>();

            deviceProxy.Setup(d => d.SendMessageAsync(It.IsAny <IMessage>(), It.IsAny <string>()))
            .ThrowsAsync(exception);
            deviceProxy.Setup(d => d.IsActive).Returns(true);
            IReadOnlyDictionary <DeviceSubscription, bool> deviceSubscriptions = new ReadOnlyDictionary <DeviceSubscription, bool>(
                new Dictionary <DeviceSubscription, bool>
            {
                [DeviceSubscription.ModuleMessages] = true
            });
            var connectionManager = new Mock <IConnectionManager>();

            connectionManager.Setup(c => c.GetDeviceConnection(It.IsAny <string>())).Returns(Option.Some(deviceProxy.Object));
            connectionManager.Setup(c => c.GetSubscriptions(It.IsAny <string>())).Returns(Option.Some(deviceSubscriptions));
            var    routingMessage        = Mock.Of <IRoutingMessage>();
            string moduleId              = "device1/module1";
            string moduleEndpointAddress = "in1";

            var moduleEndpoint = new ModuleEndpoint($"{moduleId}/{moduleEndpointAddress}", moduleId, moduleEndpointAddress, connectionManager.Object, routingMessageConverter);

            // Act
            IProcessor moduleMessageProcessor    = moduleEndpoint.CreateProcessor();
            ISinkResult <IRoutingMessage> result = await moduleMessageProcessor.ProcessAsync(routingMessage, CancellationToken.None);

            // Assert
            Assert.NotNull(result);
            if (isRetryable)
            {
                Assert.Equal(1, result.Failed.Count);
                Assert.Equal(0, result.Succeeded.Count);
                Assert.Equal(0, result.InvalidDetailsList.Count);
                Assert.Equal(routingMessage, result.Failed.First());
            }
            else
            {
                Assert.Equal(1, result.InvalidDetailsList.Count);
                Assert.Equal(0, result.Succeeded.Count);
                Assert.Equal(0, result.Failed.Count);
                Assert.Equal(routingMessage, result.InvalidDetailsList.First().Item);
                Assert.Equal(FailureKind.InvalidInput, result.InvalidDetailsList.First().FailureKind);
            }
        }
Пример #15
0
        public async Task TestFailure()
        {
            var retryPolicy          = new RetryPolicy(new ErrorDetectionStrategy(_ => true), new FixedInterval(2, TimeSpan.FromMilliseconds(10)));
            var items                = new[] { 1, 2, 3, 4, 5, 6 };
            var testSink             = new PartialFailureSink <int>(new Exception());
            var sink                 = new RetryingSink <int>(testSink, retryPolicy);
            ISinkResult <int> result = await sink.ProcessAsync(items, CancellationToken.None);

            Assert.False(result.IsSuccessful);
            Assert.Equal(new List <int> {
                1, 2, 3, 4, 5
            }, result.Succeeded);
            Assert.Equal(new List <int> {
                6
            }, result.Failed);
            Assert.Equal(new List <InvalidDetails <int> >(), result.InvalidDetailsList);
        }
Пример #16
0
        public async Task CloudMessageProcessor_ProcessAsyncTest()
        {
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            var    routingMessage  = Mock.Of <IRoutingMessage>();
            var    cloudProxy      = Mock.Of <ICloudProxy>(c => c.IsActive);
            string cloudEndpointId = Guid.NewGuid().ToString();

            Mock.Get(routingMessage).Setup(rm => rm.SystemProperties).Returns(new Dictionary <string, string> {
                { "connectionDeviceId", "myConnectionDeviceId" }
            });
            Mock.Get(cloudProxy).Setup(cp => cp.SendMessageAsync(It.IsAny <IMessage>())).Returns(Task.FromResult(true));
            var cloudEndpoint = new CloudEndpoint(cloudEndpointId, id => Task.FromResult(Option.Some(cloudProxy)), routingMessageConverter);

            IProcessor cloudMessageProcessor         = cloudEndpoint.CreateProcessor();
            ISinkResult <IRoutingMessage> sinkResult = await cloudMessageProcessor.ProcessAsync(routingMessage, CancellationToken.None);

            Assert.True(sinkResult.Succeeded.Contains(routingMessage));
        }
Пример #17
0
        public async Task SmokeTest()
        {
            var        endpoint  = new PartialFailureEndpoint("id1");
            IProcessor processor = endpoint.CreateProcessor();

            Assert.True(processor.ErrorDetectionStrategy.IsTransient(new Exception()));

            Assert.Equal(endpoint, processor.Endpoint);
            ISinkResult <IMessage> result = await processor.ProcessAsync(new IMessage[] {}, CancellationToken.None);

            Assert.Equal(new IMessage[0], result.Succeeded);

            IMessage[]             messages = new[] { Message1, Message2, Message3, Message4 };
            ISinkResult <IMessage> result2  = await processor.ProcessAsync(messages, CancellationToken.None);

            Assert.Equal(new[] { Message1, Message2 }, result2.Succeeded);
            Assert.Equal(new[] { Message3, Message4 }, result2.Failed);
        }
Пример #18
0
        public async Task SmokeTest()
        {
            var        endpoint  = new RevivableEndpoint("id1");
            IProcessor processor = endpoint.CreateProcessor();

            Assert.True(processor.ErrorDetectionStrategy.IsTransient(new Exception()));

            Assert.Equal(endpoint, processor.Endpoint);
            Assert.Equal(new List <IMessage>(), endpoint.Processed);
            Assert.Equal(string.Empty, endpoint.IotHubName);

            ISinkResult <IMessage> result = await processor.ProcessAsync(new IMessage[0], CancellationToken.None);

            Assert.Equal(new IMessage[0], result.Succeeded);
            Assert.Equal(new List <IMessage>(), endpoint.Processed);

            IMessage[]             messages = new[] { Message1, Message2, Message3 };
            ISinkResult <IMessage> result2  = await processor.ProcessAsync(messages, CancellationToken.None);

            Assert.Equal(new[] { Message1, Message2, Message3 }, result2.Succeeded);
            Assert.Equal(new List <IMessage> {
                Message1, Message2, Message3
            }, endpoint.Processed);

            // set to failing
            endpoint.Failing = true;
            ISinkResult <IMessage> result3 = await processor.ProcessAsync(messages, CancellationToken.None);

            Assert.True(result3.SendFailureDetails.HasValue);
            Assert.Equal(new List <IMessage> {
                Message1, Message2, Message3
            }, endpoint.Processed);

            // revive
            endpoint.Failing = false;
            ISinkResult <IMessage> result4 = await processor.ProcessAsync(messages, CancellationToken.None);

            Assert.Equal(new[] { Message1, Message2, Message3 }, result4.Succeeded);
            Assert.Equal(new List <IMessage> {
                Message1, Message2, Message3, Message1, Message2, Message3
            }, endpoint.Processed);

            await processor.CloseAsync(CancellationToken.None);
        }
Пример #19
0
        public async Task Events_DeviceIdNotFoundTest()
        {
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            var    routingMessage  = Mock.Of <IRoutingMessage>();
            string cloudEndpointId = Guid.NewGuid().ToString();

            Mock.Get(routingMessage).Setup(rm => rm.SystemProperties).Returns(new Dictionary <string, string> {
                { "messageId", "myConnectionDeviceId" }
            });
            var cloudProxy    = Mock.Of <ICloudProxy>();
            var cloudEndpoint = new CloudEndpoint(cloudEndpointId, id => Task.FromResult(Try.Success(cloudProxy)), routingMessageConverter, trackDeviceState: false);

            IProcessor cloudMessageProcessor         = cloudEndpoint.CreateProcessor();
            ISinkResult <IRoutingMessage> sinkResult = await cloudMessageProcessor.ProcessAsync(routingMessage, CancellationToken.None);

            Assert.Equal(FailureKind.InvalidInput, sinkResult.SendFailureDetails.OrDefault().FailureKind);
            Assert.Equal(typeof(InvalidOperationException), sinkResult.SendFailureDetails.OrDefault().RawException.GetType());
            Assert.Equal(1, sinkResult.InvalidDetailsList.Count);
            Assert.Equal(0, sinkResult.Failed.Count);
            Assert.Equal(0, sinkResult.Succeeded.Count);
        }
Пример #20
0
        public async Task TestCancellation()
        {
            var cts         = new CancellationTokenSource();
            var retryPolicy = new RetryPolicy(new ErrorDetectionStrategy(_ => true), new FixedInterval(2, TimeSpan.FromMilliseconds(10)));
            var items       = new[] { 1, 2, 3, 4, 5, 6 };

            var testSink = new FailedSink <int>(new Exception());
            var sink     = new RetryingSink <int>(testSink, retryPolicy);
            Task <ISinkResult <int> > task = sink.ProcessAsync(items, cts.Token);

            cts.Cancel();
            ISinkResult <int> result = await task;

            Assert.False(result.IsSuccessful);
            Assert.Equal(new List <int>(), result.Succeeded);
            Assert.Equal(new List <int> {
                1, 2, 3, 4, 5, 6
            }, result.Failed);
            Assert.Equal(new List <InvalidDetails <int> >(), result.InvalidDetailsList);
            Assert.True(result.SendFailureDetails.HasValue);
            result.SendFailureDetails.ForEach(sfd => Assert.IsType <TaskCanceledException>(sfd.RawException));
        }
Пример #21
0
        public async Task SmokeTest()
        {
            var        endpoint  = new NullEndpoint("endpoint1");
            IProcessor processor = endpoint.CreateProcessor();

            Assert.True(processor.ErrorDetectionStrategy.IsTransient(new Exception()));

            Assert.Equal(endpoint, processor.Endpoint);
            ISinkResult <IMessage> result = await processor.ProcessAsync(new IMessage[] { }, CancellationToken.None);

            Assert.Equal(new IMessage[0], result.Succeeded);

            ISinkResult <IMessage> result2 = await processor.ProcessAsync(new[] { Message1, Message2, Message3 }, CancellationToken.None);

            Assert.Equal(new[] { Message1, Message2, Message3 }, result2.Succeeded);

            var endpoint2 = new NullEndpoint("id2", "name2", "hub2");

            Assert.Equal("id2", endpoint2.Id);
            Assert.Equal("name2", endpoint2.Name);
            Assert.Equal("hub2", endpoint2.IotHubName);
        }
Пример #22
0
        public async Task SmokeTest()
        {
            var        cts       = new CancellationTokenSource();
            var        endpoint  = new FailedEndpoint("id1", "name1", "hub1", new InvalidOperationException());
            IProcessor processor = endpoint.CreateProcessor();

            Assert.True(processor.ErrorDetectionStrategy.IsTransient(new Exception()));

            Assert.Equal(endpoint, processor.Endpoint);
            ISinkResult <IMessage> result = await processor.ProcessAsync(new IMessage[0], cts.Token);

            Assert.True(result.SendFailureDetails.HasValue);
            result.SendFailureDetails.ForEach(ex => Assert.IsType <InvalidOperationException>(ex.RawException));
            Assert.True(processor.CloseAsync(CancellationToken.None).IsCompleted);

            var                    endpoint2  = new FailedEndpoint("id2");
            IProcessor             processor2 = endpoint2.CreateProcessor();
            ISinkResult <IMessage> result2    = await processor2.ProcessAsync(new IMessage[0], cts.Token);

            Assert.True(result2.SendFailureDetails.HasValue);
            result2.SendFailureDetails.ForEach(ex => Assert.IsType <Exception>(ex.RawException));
        }
Пример #23
0
        public async Task TestNonTransient()
        {
            var retryPolicy = new RetryPolicy(new ErrorDetectionStrategy(_ => false), new FixedInterval(int.MaxValue, TimeSpan.FromMilliseconds(10)));
            var items       = new[] { 1, 2, 3, 4, 5, 6 };

            var testSink = new FailedSink <int>(new Exception("non-transient"));
            var sink     = new RetryingSink <int>(testSink, retryPolicy);

            using (var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(500)))
            {
                ISinkResult <int> result = await sink.ProcessAsync(items, cts.Token);

                Assert.False(result.IsSuccessful);
                Assert.Equal(new List <int>(), result.Succeeded);
                Assert.Equal(new List <int> {
                    1, 2, 3, 4, 5, 6
                }, result.Failed);
                Assert.Equal(new List <InvalidDetails <int> >(), result.InvalidDetailsList);
                Assert.True(result.SendFailureDetails.HasValue);
                result.SendFailureDetails.ForEach(sfd => Assert.IsType <Exception>(sfd.RawException));
                result.SendFailureDetails.ForEach(sfd => Assert.Equal("non-transient", sfd.RawException.Message));
            }
        }
Пример #24
0
        static async Task EnterCheckpointingAsync(EndpointExecutorFsm thisPtr)
        {
            ICommand next;

            try
            {
                Preconditions.CheckNotNull(thisPtr.currentCheckpointCommand);
                using (var cts = new CancellationTokenSource(thisPtr.config.Timeout))
                {
                    ISinkResult <IMessage> result = thisPtr.currentCheckpointCommand.Result;

                    if (result.Succeeded.Any() || result.InvalidDetailsList.Any())
                    {
                        ICollection <IMessage> toCheckpoint = result.InvalidDetailsList.Count > 0
                            ? result.Succeeded.Concat(result.InvalidDetailsList.Select(i => i.Item)).ToList()
                            : result.Succeeded;
                        ICollection <IMessage> remaining = result.Failed;

                        Events.Checkpoint(thisPtr, result);
                        await thisPtr.Checkpointer.CommitAsync(toCheckpoint, remaining, Option.None <DateTime>(), thisPtr.unhealthySince, cts.Token);

                        Events.CheckpointSuccess(thisPtr, result);
                    }
                }

                next = EnterCheckpointingHelper(thisPtr);
            }
            catch (Exception ex)
            {
                Events.CheckpointFailure(thisPtr, ex);
                next = thisPtr.config.ThrowOnDead
                    ? Commands.Throw(ex)
                    : EnterCheckpointingHelper(thisPtr);
            }

            await RunInternalAsync(thisPtr, next);
        }
Пример #25
0
        public async Task SmokeTest()
        {
            var        endpoint  = new TestEndpoint("id1", "name1", "hub1");
            IProcessor processor = endpoint.CreateProcessor();

            Assert.Equal(endpoint, processor.Endpoint);
            Assert.True(processor.ErrorDetectionStrategy.IsTransient(new Exception()));
            Assert.Equal(new List <IMessage>(), endpoint.Processed);
            Assert.Equal("name1", endpoint.Name);
            Assert.Equal("hub1", endpoint.IotHubName);

            ISinkResult <IMessage> result = await processor.ProcessAsync(new IMessage[0], CancellationToken.None);

            Assert.Equal(new IMessage[0], result.Succeeded);
            Assert.Equal(new List <IMessage>(), endpoint.Processed);

            IMessage[]             messages = new[] { Message1, Message2, Message3 };
            ISinkResult <IMessage> result2  = await processor.ProcessAsync(messages, CancellationToken.None);

            Assert.Equal(new[] { Message1, Message2, Message3 }, result2.Succeeded);
            Assert.Equal(new List <IMessage> {
                Message1, Message2, Message3
            }, endpoint.Processed);
        }
Пример #26
0
        public async Task RetryableExceptionsTest(Exception exception, bool isRetryable)
        {
            // Arrange
            string id         = "d1";
            var    cloudProxy = new Mock <ICloudProxy>();

            cloudProxy.Setup(c => c.SendMessageAsync(It.IsAny <IMessage>()))
            .ThrowsAsync(exception);
            var        cloudEndpoint = new CloudEndpoint(Guid.NewGuid().ToString(), _ => Task.FromResult(Option.Some(cloudProxy.Object)), new RoutingMessageConverter());
            IProcessor processor     = cloudEndpoint.CreateProcessor();
            var        message       = new RoutingMessage(TelemetryMessageSource.Instance, new byte[0], ImmutableDictionary <string, string> .Empty, new Dictionary <string, string>
            {
                [Core.SystemProperties.ConnectionDeviceId] = id
            });

            // Act
            ISinkResult <IRoutingMessage> result = await processor.ProcessAsync(message, CancellationToken.None);

            // Assert
            Assert.NotNull(result);
            if (isRetryable)
            {
                Assert.Equal(1, result.Failed.Count);
                Assert.Equal(0, result.Succeeded.Count);
                Assert.Equal(0, result.InvalidDetailsList.Count);
                Assert.Equal(message, result.Failed.First());
            }
            else
            {
                Assert.Equal(1, result.InvalidDetailsList.Count);
                Assert.Equal(0, result.Succeeded.Count);
                Assert.Equal(0, result.Failed.Count);
                Assert.Equal(message, result.InvalidDetailsList.First().Item);
                Assert.Equal(FailureKind.InvalidInput, result.InvalidDetailsList.First().FailureKind);
            }
        }
        public async Task ProcessAsyncTest()
        {
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            string cloudEndpointId = Guid.NewGuid().ToString();

            var cloudProxyMock = new Mock <ICloudProxy>();

            cloudProxyMock.Setup(c => c.SendMessageAsync(It.IsAny <IMessage>()))
            .Callback <IMessage>(
                msg =>
            {
                if (msg.Properties.ContainsKey("Delay"))
                {
                    Task.Delay(TimeSpan.FromSeconds(10)).Wait();
                }
            })
            .Returns(Task.CompletedTask);
            cloudProxyMock.SetupGet(p => p.IsActive).Returns(true);

            string device1Id = "device1";
            string device2Id = "device2";

            byte[] messageBody = Encoding.UTF8.GetBytes("Message body");
            var    properties  = new Dictionary <string, string>()
            {
                { "Prop1", "Val1" },
                { "Prop2", "Val2" }
            };

            var device1SystemProperties = new Dictionary <string, string>
            {
                { SystemProperties.DeviceId, device1Id }
            };

            var device2SystemProperties = new Dictionary <string, string>
            {
                { SystemProperties.DeviceId, device2Id }
            };

            var cancelProperties = new Dictionary <string, string>()
            {
                { "Delay", "true" },
                { "Prop2", "Val2" }
            };

            var message1 = new RoutingMessage(TelemetryMessageSource.Instance, messageBody, properties, device1SystemProperties);
            var message2 = new RoutingMessage(TelemetryMessageSource.Instance, messageBody, properties, device2SystemProperties);
            var message3 = new RoutingMessage(TelemetryMessageSource.Instance, messageBody, cancelProperties, device1SystemProperties);

            Task <Option <ICloudProxy> > GetCloudProxy(string id)
            {
                return(Task.FromResult(
                           id.Equals(device1Id)
                        ? Option.Some(cloudProxyMock.Object)
                        : Option.None <ICloudProxy>()));
            }

            var        cloudEndpoint         = new CloudEndpoint(cloudEndpointId, GetCloudProxy, routingMessageConverter, maxBatchSize: 1);
            IProcessor cloudMessageProcessor = cloudEndpoint.CreateProcessor();

            ISinkResult <IRoutingMessage> result1 = await cloudMessageProcessor.ProcessAsync(message1, CancellationToken.None);

            Assert.NotNull(result1);
            Assert.NotEmpty(result1.Succeeded);
            Assert.Empty(result1.Failed);
            Assert.Empty(result1.InvalidDetailsList);
            Assert.False(result1.SendFailureDetails.HasValue);

            ISinkResult <IRoutingMessage> result2 = await cloudMessageProcessor.ProcessAsync(message2, CancellationToken.None);

            Assert.NotNull(result2);
            Assert.Empty(result2.InvalidDetailsList);
            Assert.NotEmpty(result2.Failed);
            Assert.Empty(result2.Succeeded);
            Assert.True(result2.SendFailureDetails.HasValue);

            ISinkResult <IRoutingMessage> resultBatch = await cloudMessageProcessor.ProcessAsync(new[] { message1, message2 }, CancellationToken.None);

            Assert.NotNull(resultBatch);
            Assert.Equal(1, resultBatch.Succeeded.Count);
            Assert.Equal(1, resultBatch.Failed.Count);
            Assert.Empty(resultBatch.InvalidDetailsList);
            Assert.True(resultBatch.SendFailureDetails.HasValue);

            ISinkResult <IRoutingMessage> resultBatchCancelled = await cloudMessageProcessor.ProcessAsync(new[] { message1, message2 }, new CancellationToken(true));

            Assert.NotNull(resultBatchCancelled);
            Assert.Empty(resultBatchCancelled.Succeeded);
            Assert.NotEmpty(resultBatchCancelled.Failed);
            Assert.Empty(resultBatchCancelled.InvalidDetailsList);
            Assert.True(resultBatchCancelled.SendFailureDetails.HasValue);

            var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
            ISinkResult <IRoutingMessage> resultBatchCancelled2 = await cloudMessageProcessor.ProcessAsync(new[] { message1, message3, message1 }, cts.Token);

            Assert.NotNull(resultBatchCancelled2);
            Assert.Equal(2, resultBatchCancelled2.Succeeded.Count);
            Assert.Equal(1, resultBatchCancelled2.Failed.Count);
            Assert.Empty(resultBatchCancelled2.InvalidDetailsList);
            Assert.True(resultBatchCancelled2.SendFailureDetails.HasValue);
        }
        public async Task ProcessInBatchesWithBatchSizeTest()
        {
            // Arrange
            string device1 = "d1";
            string device2 = "d2";
            string device3 = "d3";

            IList <IRoutingMessage> device1Messages = GetMessages(device1, 45);
            IList <IRoutingMessage> device2Messages = GetMessages(device2, 25);
            IList <IRoutingMessage> device3Messages = GetMessages(device3, 30);

            IList <IRoutingMessage> messagesToProcess = device1Messages
                                                        .Concat(device2Messages)
                                                        .Concat(device3Messages)
                                                        .ToList();

            Mock <ICloudProxy> InitCloudProxy(List <int> receivedMsgCountList)
            {
                var cp = new Mock <ICloudProxy>();

                cp.Setup(c => c.SendMessageBatchAsync(It.IsAny <IEnumerable <IMessage> >()))
                .Callback <IEnumerable <IMessage> >(b => receivedMsgCountList.Add(b.Count()))
                .Returns(Task.CompletedTask);
                cp.SetupGet(p => p.IsActive).Returns(true);
                return(cp);
            }

            var device1CloudReceivedMessagesCountList = new List <int>();
            Mock <ICloudProxy> device1CloudProxy      = InitCloudProxy(device1CloudReceivedMessagesCountList);

            var device2CloudReceivedMessagesCountList = new List <int>();
            Mock <ICloudProxy> device2CloudProxy      = InitCloudProxy(device2CloudReceivedMessagesCountList);

            var device3CloudReceivedMessagesCountList = new List <int>();
            Mock <ICloudProxy> device3CloudProxy      = InitCloudProxy(device3CloudReceivedMessagesCountList);

            Task <Option <ICloudProxy> > GetCloudProxy(string id)
            {
                ICloudProxy cp = null;

                if (id == device1)
                {
                    cp = device1CloudProxy.Object;
                }
                else if (id == device2)
                {
                    cp = device2CloudProxy.Object;
                }
                else if (id == device3)
                {
                    cp = device3CloudProxy.Object;
                }

                return(Task.FromResult(Option.Maybe(cp)));
            }

            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            string cloudEndpointId = Guid.NewGuid().ToString();
            var    cloudEndpoint   = new CloudEndpoint(cloudEndpointId, GetCloudProxy, routingMessageConverter, 30);

            // Act
            IProcessor cloudMessageProcessor         = cloudEndpoint.CreateProcessor();
            ISinkResult <IRoutingMessage> sinkResult = await cloudMessageProcessor.ProcessAsync(messagesToProcess, CancellationToken.None);

            // Assert
            Assert.Equal(messagesToProcess, sinkResult.Succeeded);
            Assert.Equal(device1CloudReceivedMessagesCountList, new[] { 30, 15 });
            Assert.Equal(device2CloudReceivedMessagesCountList, new[] { 25 });
            Assert.Equal(device3CloudReceivedMessagesCountList, new[] { 30 });
        }
        public async Task ProcessAsync_SendThrows_Test()
        {
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            string cloudEndpointId = Guid.NewGuid().ToString();

            var cloudProxyMock = new Mock <ICloudProxy>();

            cloudProxyMock.Setup(c => c.SendMessageAsync(It.IsAny <IMessage>()))
            .Throws <TimeoutException>();
            cloudProxyMock.SetupGet(p => p.IsActive).Returns(true);

            string device1Id = "device1";
            string device2Id = "device2";

            byte[] messageBody = Encoding.UTF8.GetBytes("Message body");
            var    properties  = new Dictionary <string, string>()
            {
                { "Prop1", "Val1" },
                { "Prop2", "Val2" }
            };

            var device1SystemProperties = new Dictionary <string, string>
            {
                { SystemProperties.DeviceId, device1Id }
            };

            var device2SystemProperties = new Dictionary <string, string>
            {
                { SystemProperties.DeviceId, device2Id }
            };

            var message1 = new RoutingMessage(TelemetryMessageSource.Instance, messageBody, properties, device1SystemProperties);
            var message2 = new RoutingMessage(TelemetryMessageSource.Instance, messageBody, properties, device2SystemProperties);

            Task <Option <ICloudProxy> > GetCloudProxy(string id)
            {
                return(Task.FromResult(Option.Some(cloudProxyMock.Object)));
            }

            var        cloudEndpoint         = new CloudEndpoint(cloudEndpointId, GetCloudProxy, routingMessageConverter);
            IProcessor cloudMessageProcessor = cloudEndpoint.CreateProcessor();

            ISinkResult <IRoutingMessage> result = await cloudMessageProcessor.ProcessAsync(new[] { message1, message2 }, CancellationToken.None);

            Assert.NotNull(result);
            Assert.Empty(result.Succeeded);
            Assert.Equal(2, result.Failed.Count);
            Assert.Empty(result.InvalidDetailsList);
            Assert.True(result.SendFailureDetails.HasValue);

            // throw non-retryable
            cloudProxyMock.Setup(c => c.SendMessageAsync(It.IsAny <IMessage>()))
            .Throws <Exception>();

            ISinkResult <IRoutingMessage> result1 = await cloudMessageProcessor.ProcessAsync(new[] { message1, message2 }, CancellationToken.None);

            Assert.NotNull(result1);
            Assert.Empty(result1.Succeeded);
            Assert.Empty(result1.Failed);
            Assert.Equal(2, result1.InvalidDetailsList.Count);
            Assert.True(result1.SendFailureDetails.HasValue);
        }
Пример #30
0
 public Checkpoint(ISinkResult <IMessage> result)
 {
     this.Result = Preconditions.CheckNotNull(result);
 }