public async Task ProcessEvents_MultipleDispatch_CheckpointsCorrectly(int batchCheckpointFrequency, int expected) { var partitionContext = EventHubTests.GetPartitionContext(); var options = new EventHubOptions { BatchCheckpointFrequency = batchCheckpointFrequency }; var processor = new Mock <EventProcessorHost>(MockBehavior.Strict); processor.Setup(p => p.CheckpointAsync(partitionContext.PartitionId, It.IsAny <EventData>(), It.IsAny <CancellationToken>())).Returns(Task.CompletedTask); partitionContext.ProcessorHost = processor.Object; var loggerMock = new Mock <ILogger>(); var executor = new Mock <ITriggeredFunctionExecutor>(MockBehavior.Strict); executor.Setup(p => p.TryExecuteAsync(It.IsAny <TriggeredFunctionData>(), It.IsAny <CancellationToken>())).ReturnsAsync(new FunctionResult(true)); var eventProcessor = new EventHubListener.EventProcessor(options, executor.Object, loggerMock.Object, false); for (int i = 0; i < 100; i++) { List <EventData> events = new List <EventData>() { new EventData(new byte[0]), new EventData(new byte[0]), new EventData(new byte[0]) }; await eventProcessor.ProcessEventsAsync(partitionContext, events); } processor.Verify( p => p.CheckpointAsync(partitionContext.PartitionId, It.IsAny <EventData>(), It.IsAny <CancellationToken>()), Times.Exactly(expected)); }
public async Task ProcessEvents_SingleDispatch_CheckpointsCorrectly(int batchCheckpointFrequency, int expected) { var partitionContext = EventHubTests.GetPartitionContext(); var checkpoints = 0; var options = new EventHubOptions { BatchCheckpointFrequency = batchCheckpointFrequency }; var checkpointer = new Mock <EventHubListener.ICheckpointer>(MockBehavior.Strict); checkpointer.Setup(p => p.CheckpointAsync(partitionContext)).Callback <PartitionContext>(c => { checkpoints++; }).Returns(Task.CompletedTask); var loggerMock = new Mock <ILogger>(); var executor = new Mock <ITriggeredFunctionExecutor>(MockBehavior.Strict); executor.Setup(p => p.TryExecuteAsync(It.IsAny <TriggeredFunctionData>(), It.IsAny <CancellationToken>())).ReturnsAsync(new FunctionResult(true)); var eventProcessor = new EventHubListener.EventProcessor(options, executor.Object, loggerMock.Object, true, checkpointer.Object); for (int i = 0; i < 100; i++) { List <EventData> events = new List <EventData>() { new EventData(new byte[0]) }; await eventProcessor.ProcessEventsAsync(partitionContext, events); } Assert.Equal(expected, checkpoints); }
public async Task ProcessErrorsAsync_RebalancingExceptions_LoggedAsInformation() { var partitionContext = EventHubTests.GetPartitionContext(partitionId: "123", eventHubPath: "abc", owner: "def"); var options = new EventHubOptions(); var executor = new Mock <ITriggeredFunctionExecutor>(MockBehavior.Strict); var testLogger = new TestLogger("Test"); var eventProcessor = new EventHubListener.EventProcessor(options, executor.Object, testLogger, true); var disconnectedEx = new EventHubsException(true, "My ReceiverDisconnectedException!", EventHubsException.FailureReason.ConsumerDisconnected); await eventProcessor.ProcessErrorAsync(partitionContext, disconnectedEx); var msg = testLogger.GetLogMessages().Single(); StringAssert.IsMatch("Processing error \\(Partition Id: '123', Owner: '[\\w\\d-]+', EventHubPath: 'abc'\\). An exception of type 'EventHubsException' was thrown. This exception type is typically a result of Event Hub processor rebalancing or a transient error and can be safely ignored.", msg.FormattedMessage); Assert.NotNull(msg.Exception); Assert.AreEqual(LogLevel.Information, msg.Level); testLogger.ClearLogMessages(); var leaseLostEx = new EventHubsException(true, "My LeaseLostException!", EventHubsException.FailureReason.ConsumerDisconnected); await eventProcessor.ProcessErrorAsync(partitionContext, leaseLostEx); msg = testLogger.GetLogMessages().Single(); StringAssert.IsMatch("Processing error \\(Partition Id: '123', Owner: '[\\w\\d-]+', EventHubPath: 'abc'\\). An exception of type 'EventHubsException' was thrown. This exception type is typically a result of Event Hub processor rebalancing or a transient error and can be safely ignored.", msg.FormattedMessage); Assert.NotNull(msg.Exception); Assert.AreEqual(LogLevel.Information, msg.Level); }
public async Task ProcessEvents_Failure_Checkpoints() { var partitionContext = EventHubTests.GetPartitionContext(); var options = new EventHubOptions(); var checkpointer = new Mock <EventHubListener.ICheckpointer>(MockBehavior.Strict); checkpointer.Setup(p => p.CheckpointAsync(partitionContext)).Returns(Task.CompletedTask); List <EventData> events = new List <EventData>(); List <FunctionResult> results = new List <FunctionResult>(); for (int i = 0; i < 10; i++) { events.Add(new EventData(new byte[0])); var succeeded = i > 7 ? false : true; results.Add(new FunctionResult(succeeded)); } var executor = new Mock <ITriggeredFunctionExecutor>(MockBehavior.Strict); int execution = 0; executor.Setup(p => p.TryExecuteAsync(It.IsAny <TriggeredFunctionData>(), It.IsAny <CancellationToken>())).ReturnsAsync(() => { var result = results[execution++]; return(result); }); var loggerMock = new Mock <ILogger>(); var eventProcessor = new EventHubListener.EventProcessor(options, executor.Object, loggerMock.Object, true, checkpointer.Object); await eventProcessor.ProcessEventsAsync(partitionContext, events); checkpointer.Verify(p => p.CheckpointAsync(partitionContext), Times.Once); }
public async Task ProcessEvents_CancellationToken_CancelsExecution() { var partitionContext = EventHubTests.GetPartitionContext(); var options = new EventHubOptions(); var processor = new Mock <EventProcessorHost>(MockBehavior.Strict); processor.Setup(p => p.CheckpointAsync(partitionContext.PartitionId, It.IsAny <EventData>(), It.IsAny <CancellationToken>())).Returns(Task.CompletedTask); partitionContext.ProcessorHost = processor.Object; var loggerMock = new Mock <ILogger>(); var executor = new Mock <ITriggeredFunctionExecutor>(MockBehavior.Strict); executor.Setup(p => p.TryExecuteAsync(It.IsAny <TriggeredFunctionData>(), It.IsAny <CancellationToken>())) .Callback <TriggeredFunctionData, CancellationToken>(async(TriggeredFunctionData triggeredFunctionData, CancellationToken cancellationToken) => { while (!cancellationToken.IsCancellationRequested) { await Task.Delay(100); } }) .ReturnsAsync(new FunctionResult(true)); var eventProcessor = new EventHubListener.EventProcessor(options, executor.Object, loggerMock.Object, true); List <EventData> events = new List <EventData>() { new EventData(new byte[0]) }; CancellationTokenSource source = new CancellationTokenSource(); // Start another thread to cancel execution _ = Task.Run(async() => { await Task.Delay(500); }); await eventProcessor.ProcessEventsAsync(partitionContext, events, source.Token); }
public async Task CloseAsync_Shutdown_DoesNotCheckpoint() { var partitionContext = EventHubTests.GetPartitionContext(); var options = new EventHubOptions(); var checkpointer = new Mock <EventHubListener.ICheckpointer>(MockBehavior.Strict); var executor = new Mock <ITriggeredFunctionExecutor>(MockBehavior.Strict); var loggerMock = new Mock <ILogger>(); var eventProcessor = new EventHubListener.EventProcessor(options, executor.Object, loggerMock.Object, true, checkpointer.Object); await eventProcessor.CloseAsync(partitionContext, CloseReason.Shutdown); checkpointer.Verify(p => p.CheckpointAsync(partitionContext), Times.Never); }
public async Task ProcessErrorsAsync_LoggedAsError() { var partitionContext = EventHubTests.GetPartitionContext(partitionId: "123", eventHubPath: "abc", owner: "def"); var options = new EventHubOptions(); var executor = new Mock <ITriggeredFunctionExecutor>(MockBehavior.Strict); var testLogger = new TestLogger("Test"); var eventProcessor = new EventHubListener.EventProcessor(options, executor.Object, testLogger, true); var ex = new InvalidOperationException("My InvalidOperationException!"); await eventProcessor.ProcessErrorAsync(partitionContext, ex); var msg = testLogger.GetLogMessages().Single(); StringAssert.IsMatch("Processing error \\(Partition Id: '123', Owner: '[\\w\\d-]+', EventHubPath: 'abc'\\).", msg.FormattedMessage); Assert.IsInstanceOf <InvalidOperationException>(msg.Exception); Assert.AreEqual(LogLevel.Error, msg.Level); }
public async Task ProcessErrorsAsync_LoggedAsError() { var partitionContext = EventHubTests.GetPartitionContext(partitionId: "123", eventHubPath: "abc", owner: "def"); var options = new EventHubOptions(); var checkpointer = new Mock <EventHubListener.ICheckpointer>(MockBehavior.Strict); var executor = new Mock <ITriggeredFunctionExecutor>(MockBehavior.Strict); var testLogger = new TestLogger("Test"); var eventProcessor = new EventHubListener.EventProcessor(options, executor.Object, testLogger, true, checkpointer.Object); var ex = new InvalidOperationException("My InvalidOperationException!"); await eventProcessor.ProcessErrorAsync(partitionContext, ex); var msg = testLogger.GetLogMessages().Single(); Assert.Equal("Error processing event from Partition Id: '123', Owner: 'def', EventHubPath: 'abc'", msg.FormattedMessage); Assert.IsType <InvalidOperationException>(msg.Exception); Assert.Equal(LogLevel.Error, msg.Level); }
public async Task CloseAsync_Shutdown_DoesNotCheckpoint() { var partitionContext = EventHubTests.GetPartitionContext(); var options = new EventHubOptions(); var processor = new Mock <EventProcessorHost>(MockBehavior.Strict); processor.Setup(p => p.CheckpointAsync(partitionContext.PartitionId, It.IsAny <EventData>(), It.IsAny <CancellationToken>())).Returns(Task.CompletedTask); partitionContext.ProcessorHost = processor.Object; var executor = new Mock <ITriggeredFunctionExecutor>(MockBehavior.Strict); var loggerMock = new Mock <ILogger>(); var eventProcessor = new EventHubListener.EventProcessor(options, executor.Object, loggerMock.Object, true); await eventProcessor.CloseAsync(partitionContext, ProcessingStoppedReason.Shutdown); processor.Verify( p => p.CheckpointAsync(partitionContext.PartitionId, It.IsAny <EventData>(), It.IsAny <CancellationToken>()), Times.Never); }
public async Task ProcessErrorsAsync_RebalancingExceptions_LoggedAsInformation() { var partitionContext = EventHubTests.GetPartitionContext(partitionId: "123", eventHubPath: "abc", owner: "def"); var options = new EventHubOptions(); var checkpointer = new Mock <EventHubListener.ICheckpointer>(MockBehavior.Strict); var executor = new Mock <ITriggeredFunctionExecutor>(MockBehavior.Strict); var testLogger = new TestLogger("Test"); var eventProcessor = new EventHubListener.EventProcessor(options, executor.Object, testLogger, true, checkpointer.Object); // ctor is private var constructor = typeof(ReceiverDisconnectedException) .GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(string) }, null); ReceiverDisconnectedException disconnectedEx = (ReceiverDisconnectedException)constructor.Invoke(new[] { "My ReceiverDisconnectedException!" }); await eventProcessor.ProcessErrorAsync(partitionContext, disconnectedEx); var msg = testLogger.GetLogMessages().Single(); Assert.Equal("Processing error (Partition Id: '123', Owner: 'def', EventHubPath: 'abc'). An exception of type 'ReceiverDisconnectedException' was thrown. This exception type is typically a result of Event Hub processor rebalancing or a transient error and can be safely ignored.", msg.FormattedMessage); Assert.NotNull(msg.Exception); Assert.Equal(LogLevel.Information, msg.Level); testLogger.ClearLogMessages(); // ctor is private constructor = typeof(LeaseLostException) .GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(string), typeof(Exception) }, null); LeaseLostException leaseLostEx = (LeaseLostException)constructor.Invoke(new object[] { "My LeaseLostException!", new Exception() }); await eventProcessor.ProcessErrorAsync(partitionContext, leaseLostEx); msg = testLogger.GetLogMessages().Single(); Assert.Equal("Processing error (Partition Id: '123', Owner: 'def', EventHubPath: 'abc'). An exception of type 'LeaseLostException' was thrown. This exception type is typically a result of Event Hub processor rebalancing or a transient error and can be safely ignored.", msg.FormattedMessage); Assert.NotNull(msg.Exception); Assert.Equal(LogLevel.Information, msg.Level); }