public void LogInboundLowLevelTrace_NoException_Logged() { var envelope = new RawInboundEnvelope( Stream.Null, new MessageHeaderCollection { { DefaultMessageHeaders.MessageType, "Message.Type" }, { DefaultMessageHeaders.MessageId, "1234" }, { KafkaMessageHeaders.KafkaMessageKey, "key1234" } }, new KafkaConsumerEndpoint("topic1", "topic2"), "topic2", new KafkaOffset("topic2", 2, 42)); var expectedMessage = "BatchSequence 'batch123' processing has completed... | " + "endpointName: topic2, " + "messageType: Message.Type, " + "messageId: 1234, " + "offset: [2]@42, " + "kafkaKey: key1234"; _inboundLogger.LogInboundLowLevelTrace( "{sequenceType} '{sequenceId}' processing has completed...", envelope, () => new object[] { "BatchSequence", "batch123" }); _loggerSubstitute.Received(LogLevel.Trace, null, expectedMessage, 1999); }
public void LogProcessing_Logged() { var envelope = new RawInboundEnvelope( Stream.Null, new MessageHeaderCollection { { DefaultMessageHeaders.MessageType, "Message.Type" }, { DefaultMessageHeaders.MessageId, "1234" }, { KafkaMessageHeaders.KafkaMessageKey, "key1234" } }, new KafkaConsumerEndpoint("topic1", "topic2"), "topic2", new KafkaOffset("topic2", 2, 42)); var expectedMessage = "Processing inbound message. | " + "endpointName: topic2, " + "messageType: Message.Type, " + "messageId: 1234, " + "offset: [2]@42, " + "kafkaKey: key1234"; _inboundLogger.LogProcessing(envelope); _loggerSubstitute.Received(LogLevel.Information, null, expectedMessage, 1001); }
public void LogInboundTrace_NoException_Logged() { var envelope = new RawInboundEnvelope( Stream.Null, new MessageHeaderCollection { { DefaultMessageHeaders.MessageType, "Message.Type" }, { DefaultMessageHeaders.MessageId, "1234" }, { KafkaMessageHeaders.KafkaMessageKey, "key1234" } }, new KafkaConsumerEndpoint("topic1", "topic2"), "topic2", new KafkaOffset("topic2", 2, 42)); var expectedMessage = "The RetryErrorPolicy will be skipped because the current failed " + "attempts (5) exceeds the configured maximum attempts (3). | " + "endpointName: topic2, " + "messageType: Message.Type, " + "messageId: 1234, " + "offset: [2]@42, " + "kafkaKey: key1234"; _inboundLogger.LogInboundTrace( IntegrationLogEvents.PolicyMaxFailedAttemptsExceeded, envelope, () => new object?[] { nameof(RetryErrorPolicy), 5, 3 }); _loggerSubstitute.Received(LogLevel.Trace, null, expectedMessage, 1041); }
public void LogCannotMoveSequences_Logged() { var envelope = new RawInboundEnvelope( Stream.Null, new MessageHeaderCollection { { DefaultMessageHeaders.MessageType, "Message.Type" }, { DefaultMessageHeaders.MessageId, "1234" }, { KafkaMessageHeaders.KafkaMessageKey, "key1234" } }, new KafkaConsumerEndpoint("topic1", "topic2"), "topic2", new KafkaOffset("topic2", 2, 42)); var expectedMessage = "The message belongs to a FakeSequence and cannot be moved. | " + "endpointName: topic2, " + "messageType: Message.Type, " + "messageId: 1234, " + "offset: [2]@42, " + "kafkaKey: key1234"; _inboundLogger.LogCannotMoveSequences(envelope, new FakeSequence()); _loggerSubstitute.Received(LogLevel.Warning, null, expectedMessage, 1050); }
public void LogMoved_Logged() { var envelope = new RawInboundEnvelope( Stream.Null, new MessageHeaderCollection { { DefaultMessageHeaders.MessageType, "Message.Type" }, { DefaultMessageHeaders.MessageId, "1234" }, { KafkaMessageHeaders.KafkaMessageKey, "key1234" } }, new KafkaConsumerEndpoint("topic1", "topic2"), "topic2", new KafkaOffset("topic2", 2, 42)); var expectedMessage = "The message will be moved to the endpoint 'target1'. | " + "endpointName: topic2, " + "messageType: Message.Type, " + "messageId: 1234, " + "offset: [2]@42, " + "kafkaKey: key1234"; _inboundLogger.LogMoved(envelope, new TestProducerEndpoint("target1")); _loggerSubstitute.Received(LogLevel.Information, null, expectedMessage, 1048); }
public void LogProcessingFatalError_Logged() { var envelope = new RawInboundEnvelope( Stream.Null, new MessageHeaderCollection { { DefaultMessageHeaders.MessageType, "Message.Type" }, { DefaultMessageHeaders.MessageId, "1234" }, { KafkaMessageHeaders.KafkaMessageKey, "key1234" } }, new KafkaConsumerEndpoint("topic1", "topic2"), "topic2", new KafkaOffset("topic2", 2, 42)); var expectedMessage = "Fatal error occurred processing the consumed message. The consumer will be stopped. | " + "endpointName: topic2, " + "messageType: Message.Type, " + "messageId: 1234, " + "offset: [2]@42, " + "kafkaKey: key1234"; _inboundLogger.LogProcessingFatalError(envelope, new ArithmeticException()); _loggerSubstitute.Received(LogLevel.Critical, typeof(ArithmeticException), expectedMessage, 1023); }
public void LogInboundTrace_WithException_Logged() { var envelope = new RawInboundEnvelope( Stream.Null, new MessageHeaderCollection { { DefaultMessageHeaders.MessageType, "Message.Type" }, { DefaultMessageHeaders.MessageId, "1234" } }, new TestConsumerEndpoint("test1, test2"), "test1", new TestOffset("a", "42")); var expectedMessage = "The RetryErrorPolicy will be skipped because the current failed " + "attempts (5) exceeds the configured maximum attempts (3). | " + "endpointName: test1, " + "messageType: Message.Type, " + "messageId: 1234, " + "unused1: (null), " + "unused2: (null)"; _inboundLogger.LogInboundTrace( IntegrationLogEvents.PolicyMaxFailedAttemptsExceeded, envelope, new InvalidOperationException(), () => new object?[] { nameof(RetryErrorPolicy), 5, 3 }); _loggerSubstitute.Received( LogLevel.Trace, typeof(InvalidOperationException), expectedMessage, 1041); }
public async Task HandleAsync_EndpointWithBinaryFileMessageSerializer_EnvelopeUntouched() { var rawContent = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 }; var headers = new[] { new MessageHeader("x-message-type", typeof(BinaryFileMessage).AssemblyQualifiedName) }; var endpoint = TestConsumerEndpoint.GetDefault(); endpoint.Serializer = new BinaryFileMessageSerializer(); var envelope = new RawInboundEnvelope( rawContent, headers, endpoint, "test", new TestOffset()); IRawInboundEnvelope?result = null; await new BinaryFileHandlerConsumerBehavior().HandleAsync( new ConsumerPipelineContext( envelope, Substitute.For <IConsumer>(), Substitute.For <ISequenceStore>(), Substitute.For <IServiceProvider>()), context => { result = context.Envelope; return(Task.CompletedTask); }); result.Should().BeSameAs(envelope); }
public void LogCannotMoveSequences_Logged() { var envelope = new RawInboundEnvelope( Stream.Null, new MessageHeaderCollection { { DefaultMessageHeaders.MessageType, "Message.Type" }, { DefaultMessageHeaders.MessageId, "1234" } }, new TestConsumerEndpoint("test1, test2"), "test1", new TestOffset("a", "42")); var expectedMessage = "The message belongs to a FakeSequence and cannot be moved. | " + "endpointName: test1, " + "messageType: Message.Type, " + "messageId: 1234, " + "unused1: (null), " + "unused2: (null)"; _inboundLogger.LogCannotMoveSequences(envelope, new FakeSequence()); _loggerSubstitute.Received(LogLevel.Warning, null, expectedMessage, 1050); }
public void LogMoved_Logged() { var envelope = new RawInboundEnvelope( Stream.Null, new MessageHeaderCollection { { DefaultMessageHeaders.MessageType, "Message.Type" }, { DefaultMessageHeaders.MessageId, "1234" } }, new TestConsumerEndpoint("test1, test2"), "test1", new TestOffset("a", "42")); var expectedMessage = "The message will be moved to the endpoint 'target1'. | " + "endpointName: test1, " + "messageType: Message.Type, " + "messageId: 1234, " + "unused1: (null), " + "unused2: (null)"; _inboundLogger.LogMoved(envelope, new TestProducerEndpoint("target1")); _loggerSubstitute.Received(LogLevel.Information, null, expectedMessage, 1048); }
public void LogRollbackToSkipFailed_Logged() { var envelope = new RawInboundEnvelope( Stream.Null, new MessageHeaderCollection { { DefaultMessageHeaders.MessageType, "Message.Type" }, { DefaultMessageHeaders.MessageId, "1234" } }, new TestConsumerEndpoint("test1, test2"), "test1", new TestOffset("a", "42")); var expectedMessage = "Error occurred while rolling back or committing, the skip message error policy " + "cannot be applied. The consumer will be reconnected. | " + "endpointName: test1, " + "messageType: Message.Type, " + "messageId: 1234, " + "unused1: (null), " + "unused2: (null)"; _inboundLogger.LogRollbackToSkipFailed(envelope, new TimeoutException()); _loggerSubstitute.Received(LogLevel.Warning, typeof(TimeoutException), expectedMessage, 1052); }
protected virtual async Task HandleMessageAsync( byte[]?message, IReadOnlyCollection <MessageHeader> headers, string sourceEndpointName, IOffset offset, IDictionary <string, string>?additionalLogData) { var envelope = new RawInboundEnvelope( message, headers, Endpoint, sourceEndpointName, offset, additionalLogData); _statusInfo.RecordConsumedMessage(offset); var consumerPipelineContext = new ConsumerPipelineContext( envelope, this, GetSequenceStore(offset), ServiceProvider); await ExecutePipelineAsync(consumerPipelineContext).ConfigureAwait(false); }
public void LogProcessingFatalError_Logged() { var envelope = new RawInboundEnvelope( Stream.Null, new MessageHeaderCollection { { DefaultMessageHeaders.MessageType, "Message.Type" }, { DefaultMessageHeaders.MessageId, "1234" } }, new TestConsumerEndpoint("test1, test2"), "test1", new TestOffset("a", "42")); var expectedMessage = "Fatal error occurred processing the consumed message. The consumer will be stopped. | " + "endpointName: test1, " + "messageType: Message.Type, " + "messageId: 1234, " + "unused1: (null), " + "unused2: (null)"; _inboundLogger.LogProcessingFatalError(envelope, new ArithmeticException()); _loggerSubstitute.Received(LogLevel.Critical, typeof(ArithmeticException), expectedMessage, 1023); }
public void HandleAsync_WithoutActivityHeaders_NewActivityIsStarted() { var rawEnvelope = new RawInboundEnvelope( new byte[5], new MessageHeaderCollection { { DefaultMessageHeaders.TraceId, "00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01" } }, TestConsumerEndpoint.GetDefault(), TestConsumerEndpoint.GetDefault().Name, new TestOffset()); var entered = false; new ActivityConsumerBehavior().HandleAsync( new ConsumerPipelineContext( rawEnvelope, Substitute.For <IConsumer>(), Substitute.For <ISequenceStore>(), Substitute.For <IServiceProvider>()), _ => { Activity.Current.Should().NotBeNull(); Activity.Current.Id.Should().NotBeNullOrEmpty(); entered = true; return(Task.CompletedTask); }); entered.Should().BeTrue(); }
public async Task HandleAsync_BinaryFileMessage_BinaryFileMessageReturned() { var rawContent = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 }; var headers = new[] { new MessageHeader("x-message-type", typeof(BinaryFileMessage).AssemblyQualifiedName) }; var envelope = new RawInboundEnvelope( rawContent, headers, TestConsumerEndpoint.GetDefault(), "test", new TestOffset()); IRawInboundEnvelope?result = null; await new BinaryFileHandlerConsumerBehavior().HandleAsync( new ConsumerPipelineContext( envelope, Substitute.For <IConsumer>(), Substitute.For <ISequenceStore>(), Substitute.For <IServiceProvider>()), context => { result = context.Envelope; return(Task.CompletedTask); }); result.Should().BeAssignableTo <IInboundEnvelope <BinaryFileMessage> >(); var binaryFileMessage = result.As <IInboundEnvelope <BinaryFileMessage> >().Message !; binaryFileMessage.Content.ReadAll().Should().BeEquivalentTo(rawContent); }
public async Task HandleAsync_NoBinaryFileHeaders_EnvelopeUntouched() { var rawContent = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 }; var envelope = new RawInboundEnvelope( rawContent, null, TestConsumerEndpoint.GetDefault(), "test", new TestOffset()); IRawInboundEnvelope?result = null; await new BinaryFileHandlerConsumerBehavior().HandleAsync( new ConsumerPipelineContext( envelope, Substitute.For <IConsumer>(), Substitute.For <ISequenceStore>(), Substitute.For <IServiceProvider>()), context => { result = context.Envelope; return(Task.CompletedTask); }); result.Should().BeSameAs(envelope); }
public async Task HandleAsync_WithTraceIdHeader_NewActivityStartedAndParentIdIsSet() { var rawEnvelope = new RawInboundEnvelope( new byte[5], new MessageHeaderCollection { { DefaultMessageHeaders.TraceId, "00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01" } }, TestConsumerEndpoint.GetDefault(), TestConsumerEndpoint.GetDefault().Name, new TestOffset()); var entered = false; await new ActivityConsumerBehavior(Substitute.For <IActivityEnricherFactory>()) .HandleAsync( new ConsumerPipelineContext( rawEnvelope, Substitute.For <IConsumer>(), Substitute.For <ISequenceStore>(), Substitute.For <IServiceProvider>()), _ => { Activity.Current.Should().NotBeNull(); Activity.Current !.ParentId.Should() .Be("00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01"); Activity.Current.Id.Should().StartWith("00-0af7651916cd43dd8448eb211c80319c"); entered = true; return(Task.CompletedTask); });
public async Task HandleAsync_ExceptionThrown_ExceptionLogged() { var logger = new LoggerSubstitute <FatalExceptionLoggerConsumerBehavior>(); var integrationLogger = new SilverbackIntegrationLogger <FatalExceptionLoggerConsumerBehavior>( logger, new LogTemplates()); var rawEnvelope = new RawInboundEnvelope( new byte[5], null, TestConsumerEndpoint.GetDefault(), TestConsumerEndpoint.GetDefault().Name, new TestOffset()); try { await new FatalExceptionLoggerConsumerBehavior(integrationLogger).HandleAsync( new ConsumerPipelineContext( rawEnvelope, Substitute.For <IConsumer>(), Substitute.For <ISequenceStore>(), Substitute.For <IServiceProvider>()), _ => throw new InvalidCastException()); } catch { // Ignored } logger.Received(LogLevel.Critical, typeof(InvalidCastException)); }
public void LogProcessingError_Logged() { var envelope = new RawInboundEnvelope( Stream.Null, new MessageHeaderCollection { { DefaultMessageHeaders.MessageType, "Message.Type" }, { DefaultMessageHeaders.MessageId, "1234" } }, new TestConsumerEndpoint("test1, test2"), "test1", new TestOffset("a", "42")); var expectedMessage = "Error occurred processing the inbound message. | " + "endpointName: test1, " + "messageType: Message.Type, " + "messageId: 1234, " + "unused1: (null), " + "unused2: (null)"; _inboundLogger.LogProcessingError(envelope, new InvalidDataException()); _loggerSubstitute.Received(LogLevel.Error, typeof(InvalidDataException), expectedMessage, 1002); }
public void LogProcessing_Logged() { var envelope = new RawInboundEnvelope( Stream.Null, new MessageHeaderCollection { { DefaultMessageHeaders.MessageType, "Message.Type" }, { DefaultMessageHeaders.MessageId, "1234" } }, new TestConsumerEndpoint("test1, test2"), "test1", new TestOffset("a", "42")); var expectedMessage = "Processing inbound message. | " + "endpointName: test1, " + "messageType: Message.Type, " + "messageId: 1234, " + "unused1: (null), " + "unused2: (null)"; _inboundLogger.LogProcessing(envelope); _loggerSubstitute.Received(LogLevel.Information, null, expectedMessage, 1001); }
public void LogInboundLowLevelTrace_NoException_Logged() { var envelope = new RawInboundEnvelope( Stream.Null, new MessageHeaderCollection { { DefaultMessageHeaders.MessageType, "Message.Type" }, { DefaultMessageHeaders.MessageId, "1234" } }, new TestConsumerEndpoint("test1, test2"), "test1", new TestOffset("a", "42")); var expectedMessage = "BatchSequence 'batch123' processing has completed... | " + "endpointName: test1, " + "messageType: Message.Type, " + "messageId: 1234, " + "unused1: (null), " + "unused2: (null)"; _inboundLogger.LogInboundLowLevelTrace( "{sequenceType} '{sequenceId}' processing has completed...", envelope, () => new object[] { "BatchSequence", "batch123" }); _loggerSubstitute.Received(LogLevel.Trace, null, expectedMessage, 1999); }
public void Constructor_NullRawMessage_NoExceptionIsThrown() { var envelope = new RawInboundEnvelope( (Stream?)null, null, TestConsumerEndpoint.GetDefault(), "test", new TestOffset("a", "b")); envelope.Should().NotBeNull(); }
public async Task GetSequence_ChunkForExistingSequence_SequenceReturned() { var envelope1 = new RawInboundEnvelope( new byte[] { 0x01, 0x02, 0x03 }, new MessageHeaderCollection { { DefaultMessageHeaders.MessageId, "123" }, { DefaultMessageHeaders.ChunkIndex, "0" }, { DefaultMessageHeaders.ChunksCount, "4" } }, new TestConsumerEndpoint("test"), "test", new TestOffset()); var envelope2 = new RawInboundEnvelope( new byte[] { 0x04, 0x05, 0x06 }, new MessageHeaderCollection { { DefaultMessageHeaders.MessageId, "123" }, { DefaultMessageHeaders.ChunkIndex, "1" }, { DefaultMessageHeaders.ChunksCount, "4" } }, new TestConsumerEndpoint("test"), "test", new TestOffset()); var reader = new ChunkSequenceReader(); var context1 = ConsumerPipelineContextHelper.CreateSubstitute( envelope1, sequenceStore: _defaultSequenceStore); var sequence1 = await reader.GetSequenceAsync(context1); sequence1.Should().NotBeNull(); sequence1.Should().BeOfType <ChunkSequence>(); sequence1 !.TotalLength.Should().Be(4); sequence1.IsNew.Should().BeTrue(); var context2 = ConsumerPipelineContextHelper.CreateSubstitute( envelope2, sequenceStore: _defaultSequenceStore); var sequence2 = await reader.GetSequenceAsync(context2); sequence2.Should().NotBeNull(); sequence2.Should().BeSameAs(sequence1); sequence2 !.IsNew.Should().BeFalse(); }
public void CreateTypedInboundEnvelope_EnvelopeReturned() { var endpoint = TestConsumerEndpoint.GetDefault(); var rawEnvelope = new RawInboundEnvelope( Array.Empty <byte>(), new[] { new MessageHeader("one", "1"), new MessageHeader("two", "2") }, endpoint, "test", new TestOffset()); var message = new TestEventOne(); var envelope = SerializationHelper.CreateTypedInboundEnvelope(rawEnvelope, message, typeof(TestEventOne)); envelope.Should().BeOfType <InboundEnvelope <TestEventOne> >(); envelope.As <InboundEnvelope <TestEventOne> >().Message.Should().Be(message); envelope.Headers.Should().ContainSingle(header => header.Name == "one" && header.Value == "1"); envelope.Headers.Should().ContainSingle(header => header.Name == "two" && header.Value == "2"); envelope.Endpoint.Should().Be(endpoint); }
public void HandleAsync_ExceptionThrown_ExceptionRethrown() { var rawEnvelope = new RawInboundEnvelope( new byte[5], null, TestConsumerEndpoint.GetDefault(), TestConsumerEndpoint.GetDefault().Name, new TestOffset()); Func <Task> act = () => new FatalExceptionLoggerConsumerBehavior(_inboundLogger).HandleAsync( new ConsumerPipelineContext( rawEnvelope, Substitute.For <IConsumer>(), Substitute.For <ISequenceStore>(), Substitute.For <IServiceProvider>()), _ => throw new InvalidCastException()); act.Should().ThrowExactly <ConsumerPipelineFatalException>() .WithInnerExceptionExactly <InvalidCastException>(); }
public async Task CanHandle_NonChunk_FalseReturned() { var envelope = new RawInboundEnvelope( new byte[] { 0x01, 0x02, 0x03 }, new MessageHeaderCollection { { DefaultMessageHeaders.MessageId, "123" } }, new TestConsumerEndpoint("test"), "test", new TestOffset()); var context = ConsumerPipelineContextHelper.CreateSubstitute( envelope, sequenceStore: _defaultSequenceStore); var result = await new ChunkSequenceReader().CanHandleAsync(context); result.Should().BeFalse(); }
public async Task GetSequence_MissingFirstChunk_NullReturned() { var envelope = new RawInboundEnvelope( new byte[] { 0x04, 0x05, 0x06 }, new MessageHeaderCollection { { DefaultMessageHeaders.MessageId, "123" }, { DefaultMessageHeaders.ChunkIndex, "1" }, { DefaultMessageHeaders.ChunksCount, "4" } }, new TestConsumerEndpoint("test"), "test", new TestOffset()); var context = ConsumerPipelineContextHelper.CreateSubstitute( envelope, sequenceStore: _defaultSequenceStore); var sequence = await new ChunkSequenceReader().GetSequenceAsync(context); sequence.Should().BeNull(); }
public async Task GetSequence_FirstChunk_SequenceReturned() { var envelope = new RawInboundEnvelope( new byte[] { 0x01, 0x02, 0x03 }, new MessageHeaderCollection { { DefaultMessageHeaders.MessageId, "123" }, { DefaultMessageHeaders.ChunkIndex, "0" }, { DefaultMessageHeaders.ChunksCount, "4" }, }, new TestConsumerEndpoint("test"), "test", new TestOffset()); var context = ConsumerPipelineContextHelper.CreateSubstitute( envelope, sequenceStore: _defaultSequenceStore); var sequence = await new ChunkSequenceReader().GetSequenceAsync(context); sequence.Should().NotBeNull(); sequence !.TotalLength.Should().Be(4); sequence.IsNew.Should().BeTrue(); }