public async Task HandleErrorAsync_Whatever_ConsumerRolledBackAndTransactionAborted() { var policy = new RetryErrorPolicy().MaxFailedAttempts(3).Build(_serviceProvider); var envelope = new InboundEnvelope( "hey oh!", new MemoryStream(), null, new TestOffset(), TestConsumerEndpoint.GetDefault(), TestConsumerEndpoint.GetDefault().Name); var transactionManager = Substitute.For <IConsumerTransactionManager>(); await policy.HandleErrorAsync( ConsumerPipelineContextHelper.CreateSubstitute( envelope, _serviceProvider, transactionManager), new InvalidOperationException("test")); await transactionManager.Received(1).RollbackAsync( Arg.Any <InvalidOperationException>(), false, true, false); }
public async Task HandleAsync_ThrowException_ExceptionIsThrown() { var message = new TestValidationMessage { Id = "1", String10 = "123456789abc", IntRange = 5, NumbersOnly = "123" }; var expectedMessage = $"The message is not valid:{Environment.NewLine}- The field String10 must be a string with a maximum length of 10."; var endpoint = TestConsumerEndpoint.GetDefault(); endpoint.MessageValidationMode = MessageValidationMode.ThrowException; var envelope = new InboundEnvelope( message, null, null, new TestOffset(), endpoint, "source-endpoint"); IRawInboundEnvelope?result = null; Func <Task> act = () => new ValidatorConsumerBehavior(_inboundLogger).HandleAsync( ConsumerPipelineContextHelper.CreateSubstitute(envelope, _serviceProvider), context => { result = context.Envelope; return(Task.CompletedTask); }); await act.Should().ThrowAsync <MessageValidationException>().WithMessage(expectedMessage); result.Should().BeNull(); }
public void CanHandle_Sequence_FalseReturned() { var policy = new MoveMessageErrorPolicy(TestProducerEndpoint.GetDefault()).Build(_serviceProvider); var envelope = new InboundEnvelope( "hey oh!", new MemoryStream(), null, new TestOffset(), new TestConsumerEndpoint("test") { Batch = new BatchSettings { Size = 10 } }, TestConsumerEndpoint.GetDefault().Name); var context = ConsumerPipelineContextHelper.CreateSubstitute(envelope, _serviceProvider); context.SetSequence(new BatchSequence("batch", context), false); var result = policy.CanHandle( context, new InvalidOperationException("test")); result.Should().BeFalse(); }
public async Task HandleAsync_ValidMessage_NoLogAndNoException(MessageValidationMode validationMode) { var message = new TestValidationMessage { Id = "1", String10 = "123", IntRange = 5, NumbersOnly = "123" }; var endpoint = TestConsumerEndpoint.GetDefault(); endpoint.MessageValidationMode = validationMode; var envelope = new InboundEnvelope( message, null, null, new TestOffset(), endpoint, "source-endpoint"); IRawInboundEnvelope?result = null; Func <Task> act = () => new ValidatorConsumerBehavior(_inboundLogger).HandleAsync( ConsumerPipelineContextHelper.CreateSubstitute(envelope, _serviceProvider), context => { result = context.Envelope; return(Task.CompletedTask); }); await act.Should().NotThrowAsync <ValidationException>(); result.Should().NotBeNull(); _loggerSubstitute.DidNotReceive(LogLevel.Warning, null).Should().BeTrue(); }
public void CanHandle_Whatever_TrueReturned(int failedAttempts) { var rawMessage = new MemoryStream(); var headers = new[] { new MessageHeader( DefaultMessageHeaders.FailedAttempts, failedAttempts.ToString(CultureInfo.InvariantCulture)) }; var testPolicy = new TestErrorPolicy(); var chain = new ErrorPolicyChain( new RetryErrorPolicy().MaxFailedAttempts(3), testPolicy) .Build(_serviceProvider); var result = chain.CanHandle( ConsumerPipelineContextHelper.CreateSubstitute( new InboundEnvelope( rawMessage, headers, new TestOffset(), TestConsumerEndpoint.GetDefault(), TestConsumerEndpoint.GetDefault().Name)), new InvalidOperationException("test")); result.Should().BeTrue(); }
public async Task HandleAsync_LogWarning_WarningIsLogged( IIntegrationMessage message, string expectedValidationMessage) { var endpoint = TestConsumerEndpoint.GetDefault(); endpoint.MessageValidationMode = MessageValidationMode.LogWarning; var envelope = new InboundEnvelope( message, null, null, new TestOffset(), endpoint, "source-endpoint"); IRawInboundEnvelope?result = null; await new ValidatorConsumerBehavior(_inboundLogger).HandleAsync( ConsumerPipelineContextHelper.CreateSubstitute(envelope, _serviceProvider), context => { result = context.Envelope; return(Task.CompletedTask); }); result.Should().NotBeNull(); _loggerSubstitute.Received(LogLevel.Warning, null, expectedValidationMessage, 1080); }
public void CanHandle_WithMaxFailedAttempts_ExpectedResultReturned( int failedAttempts, bool expectedResult) { var envelope = new InboundEnvelope( new MemoryStream(), new[] { new MessageHeader( DefaultMessageHeaders.FailedAttempts, failedAttempts.ToString(CultureInfo.InvariantCulture)) }, new TestOffset(), TestConsumerEndpoint.GetDefault(), TestConsumerEndpoint.GetDefault().Name); var policy = new TestErrorPolicy() .MaxFailedAttempts(3) .Build(Substitute.For<IServiceProvider>()); var canHandle = policy.CanHandle( ConsumerPipelineContextHelper.CreateSubstitute(envelope), new InvalidOperationException()); canHandle.Should().Be(expectedResult); }
public async Task Transform_SingleMessage_HeadersProperlyModified() { var policy = ErrorPolicy .Move(TestProducerEndpoint.GetDefault()) .Transform((outboundEnvelope, ex) => { outboundEnvelope.Headers.Add("error", ex.GetType().Name); }) .Build(_serviceProvider); var envelope = new InboundEnvelope( new MemoryStream(Encoding.UTF8.GetBytes("hey oh!")), null, new TestOffset(), TestConsumerEndpoint.GetDefault(), TestConsumerEndpoint.GetDefault().Name); envelope.Headers.Add("key", "value"); await policy.HandleErrorAsync( ConsumerPipelineContextHelper.CreateSubstitute(envelope, _serviceProvider), new InvalidOperationException("test")); var producer = (TestProducer)_broker.GetProducer(TestProducerEndpoint.GetDefault()); var newHeaders = producer.ProducedMessages[0].Headers; newHeaders.Should().HaveCount(6); // message-id, message-type, key, traceid, error, source-endpoint }
public void CanHandle_WithDifferentFailedAttemptsCount_ReturnReflectsMaxFailedAttempts( int failedAttempts, bool expectedResult) { var policy = ErrorPolicy.Retry().MaxFailedAttempts(3).Build(_serviceProvider); var rawMessage = new MemoryStream(); var headers = new[] { new MessageHeader(DefaultMessageHeaders.FailedAttempts, failedAttempts) }; var envelope = new InboundEnvelope( rawMessage, headers, new TestOffset(), TestConsumerEndpoint.GetDefault(), TestConsumerEndpoint.GetDefault().Name); var canHandle = policy.CanHandle( ConsumerPipelineContextHelper.CreateSubstitute(envelope, _serviceProvider), new InvalidOperationException("test")); canHandle.Should().Be(expectedResult); }
public async Task HandleError_WithPublish_MessagePublished() { var publisher = Substitute.For <IPublisher>(); var serviceProvider = new ServiceCollection().AddScoped(_ => publisher) .BuildServiceProvider(new ServiceProviderOptions { ValidateScopes = true }); var policy = new TestErrorPolicy() .Publish(_ => new TestEventTwo { Content = "aaa" }) .Build(serviceProvider); var envelope = new InboundEnvelope( new MemoryStream(), new[] { new MessageHeader(DefaultMessageHeaders.FailedAttempts, "3") }, new TestOffset(), TestConsumerEndpoint.GetDefault(), TestConsumerEndpoint.GetDefault().Name); await policy.HandleErrorAsync( ConsumerPipelineContextHelper.CreateSubstitute(envelope, serviceProvider), new ArgumentNullException()); await publisher.Received().PublishAsync(Arg.Any <TestEventTwo>()); }
public async Task HandleErrorAsync_WithTransform_MessageTranslated() { var policy = new MoveMessageErrorPolicy(TestProducerEndpoint.GetDefault()) .Transform((originalEnvelope, _) => { originalEnvelope.Message = new TestEventTwo(); }) .Build(_serviceProvider); var rawMessage = new MemoryStream(Encoding.UTF8.GetBytes("hey oh!")); var headers = new[] { new MessageHeader(DefaultMessageHeaders.MessageType, typeof(string).AssemblyQualifiedName) }; var envelope = new InboundEnvelope( rawMessage, headers, new TestOffset(), TestConsumerEndpoint.GetDefault(), TestConsumerEndpoint.GetDefault().Name); await policy.HandleErrorAsync( ConsumerPipelineContextHelper.CreateSubstitute(envelope, _serviceProvider), new InvalidOperationException("test")); var producer = (TestProducer)_broker.GetProducer(TestProducerEndpoint.GetDefault()); var(producedMessage, _) = await producer.Endpoint.Serializer.DeserializeAsync( new MemoryStream(producer.ProducedMessages[0].Message !), producer.ProducedMessages[0].Headers, MessageSerializationContext.Empty); producedMessage.Should().BeOfType <TestEventTwo>(); }
public async Task HandleErrorAsync_RetryWithMaxFailedAttempts_AppliedAccordingToMaxFailedAttempts(int failedAttempts) { var rawMessage = new MemoryStream(); var headers = new[] { new MessageHeader( DefaultMessageHeaders.FailedAttempts, failedAttempts.ToString(CultureInfo.InvariantCulture)) }; var testPolicy = new TestErrorPolicy(); var chain = new ErrorPolicyChain( new[] { new RetryErrorPolicy().MaxFailedAttempts(3), testPolicy }) .Build(_serviceProvider); await chain.HandleErrorAsync( ConsumerPipelineContextHelper.CreateSubstitute( new InboundEnvelope( rawMessage, headers, new TestOffset(), TestConsumerEndpoint.GetDefault(), TestConsumerEndpoint.GetDefault().Name)), new InvalidOperationException("test")); testPolicy.Applied.Should().Be(failedAttempts > 3); }
public void LogSkippingIncompleteSequence_Logged() { var expectedMessage = "Skipping the incomplete sequence 'fake1'. The first message is missing."; _silverbackLogger.LogSkippingIncompleteSequence( new IncompleteSequence("fake1", ConsumerPipelineContextHelper.CreateSubstitute())); _loggerSubstitute.Received(LogLevel.Warning, null, expectedMessage, 1009); }
public async Task AddAsync_NewSequence_SequenceAddedAndReturned() { var store = new DefaultSequenceStore(new IntegrationLoggerSubstitute <DefaultSequenceStore>()); var context = ConsumerPipelineContextHelper.CreateSubstitute(sequenceStore: store); var newSequence = new ChunkSequence("abc", 10, context); var result = await store.AddAsync(newSequence); result.Should().BeSameAs(newSequence); (await store.GetAsync <ChunkSequence>("abc")).Should().BeSameAs(newSequence); }
public FakeSequence(string sequenceId, bool isComplete, bool isAborted, ISequenceStore store) : base(sequenceId, ConsumerPipelineContextHelper.CreateSubstitute(sequenceStore: store)) { if (isComplete) { CompleteAsync().Wait(); } if (isAborted) { AbortAsync(SequenceAbortReason.EnumerationAborted).Wait(); } }
public async Task AddAsyncAndGetAsync_Sequence_IsNewFlagAutomaticallyHandled() { var store = new DefaultSequenceStore(new IntegrationLoggerSubstitute <DefaultSequenceStore>()); var context = ConsumerPipelineContextHelper.CreateSubstitute(sequenceStore: store); var sequence = await store.AddAsync(new ChunkSequence("abc", 10, context)); sequence.IsNew.Should().BeTrue(); sequence = (await store.GetAsync <ChunkSequence>("abc")) !; sequence !.IsNew.Should().BeFalse(); }
public async Task AddAsync_ExistingSequence_SequenceAbortedAndReplaced() { var store = new DefaultSequenceStore(new IntegrationLoggerSubstitute <DefaultSequenceStore>()); var context = ConsumerPipelineContextHelper.CreateSubstitute(sequenceStore: store); var originalSequence = new ChunkSequence("abc", 10, context); await store.AddAsync(originalSequence); var newSequence = new ChunkSequence("abc", 10, context); await store.AddAsync(newSequence); originalSequence.IsAborted.Should().BeTrue(); (await store.GetAsync <ChunkSequence>("abc")).Should().BeSameAs(newSequence); }
public async Task GetAsync_NotExistingSequence_NullReturned() { var store = new DefaultSequenceStore(new IntegrationLoggerSubstitute <DefaultSequenceStore>()); var context = ConsumerPipelineContextHelper.CreateSubstitute(sequenceStore: store); await store.AddAsync(new ChunkSequence("aaa", 10, context)); await store.AddAsync(new ChunkSequence("bbb", 10, context)); await store.AddAsync(new ChunkSequence("ccc", 10, context)); var result = await store.GetAsync <ChunkSequence>("123"); result.Should().BeNull(); }
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 SilverbackIntegrationLoggerBenchmark() { _integrationLogger = new SilverbackIntegrationLogger( new FakeLogger(), new LogTemplates().ConfigureAdditionalData <TestConsumerEndpoint>("offset")); _singleMessageContext = ConsumerPipelineContextHelper.CreateSubstitute( new RawInboundEnvelope( Array.Empty <byte>(), new MessageHeaderCollection { new MessageHeader("Test", "Test"), new MessageHeader(DefaultMessageHeaders.FailedAttempts, 1), new MessageHeader(DefaultMessageHeaders.MessageType, "Something.Xy"), new MessageHeader(DefaultMessageHeaders.MessageId, "1234"), }, new TestConsumerEndpoint("Test"), "Test", new TestOffset("abc", "1"), new Dictionary <string, string> { ["offset"] = "1@42" })); _sequenceContext = ConsumerPipelineContextHelper.CreateSubstitute( new RawInboundEnvelope( Array.Empty <byte>(), new MessageHeaderCollection { new MessageHeader("Test", "Test"), new MessageHeader(DefaultMessageHeaders.FailedAttempts, 1), new MessageHeader(DefaultMessageHeaders.MessageType, "Something.Xy"), new MessageHeader(DefaultMessageHeaders.MessageId, "5678"), new MessageHeader(DefaultMessageHeaders.BatchId, "1234"), new MessageHeader(DefaultMessageHeaders.BatchSize, "11"), }, new TestConsumerEndpoint("Test"), "Test", new TestOffset("abc", "2"), new Dictionary <string, string> { ["offset"] = "1@43" })); var sequence = new BatchSequence("123", _sequenceContext); sequence.AddAsync(_sequenceContext.Envelope, null, false); _sequenceContext.SetSequence(sequence, true); }
public async Task Remove_NotExistingSequence_NoExceptionThrown() { var store = new DefaultSequenceStore(new IntegrationLoggerSubstitute <DefaultSequenceStore>()); var context = ConsumerPipelineContextHelper.CreateSubstitute(sequenceStore: store); await store.AddAsync(new ChunkSequence("aaa", 10, context)); await store.AddAsync(new ChunkSequence("bbb", 10, context)); await store.AddAsync(new ChunkSequence("ccc", 10, context)); await store.RemoveAsync("123"); (await store.GetAsync <ChunkSequence>("aaa")).Should().NotBeNull(); (await store.GetAsync <ChunkSequence>("bbb")).Should().NotBeNull(); (await store.GetAsync <ChunkSequence>("ccc")).Should().NotBeNull(); }
public async Task Remove_ExistingSequence_SequenceRemoved() { var store = new DefaultSequenceStore(new SilverbackLoggerSubstitute <DefaultSequenceStore>()); var context = ConsumerPipelineContextHelper.CreateSubstitute(sequenceStore: store); await store.AddAsync(new ChunkSequence("aaa", 10, context)); await store.AddAsync(new ChunkSequence("bbb", 10, context)); await store.AddAsync(new ChunkSequence("ccc", 10, context)); await store.RemoveAsync("bbb"); (await store.GetAsync <ChunkSequence>("bbb")).Should().BeNull(); (await store.GetAsync <ChunkSequence>("aaa")).Should().NotBeNull(); (await store.GetAsync <ChunkSequence>("ccc")).Should().NotBeNull(); }
public void CanHandle_SingleMessage_TrueReturned() { var policy = new MoveMessageErrorPolicy(TestProducerEndpoint.GetDefault()).Build(_serviceProvider); var envelope = new InboundEnvelope( "hey oh!", new MemoryStream(), null, new TestOffset(), TestConsumerEndpoint.GetDefault(), TestConsumerEndpoint.GetDefault().Name); var result = policy.CanHandle( ConsumerPipelineContextHelper.CreateSubstitute(envelope, _serviceProvider), new InvalidOperationException("test")); result.Should().BeTrue(); }
public async Task HandleErrorAsync_SingleMessage_TrueReturned() { var policy = new MoveMessageErrorPolicy(TestProducerEndpoint.GetDefault()).Build(_serviceProvider); var envelope = new InboundEnvelope( "hey oh!", new MemoryStream(Encoding.UTF8.GetBytes("hey oh!")), null, new TestOffset(), new TestConsumerEndpoint("source-endpoint"), "source-endpoint"); var result = await policy.HandleErrorAsync( ConsumerPipelineContextHelper.CreateSubstitute(envelope, _serviceProvider), new InvalidOperationException("test")); result.Should().BeTrue(); }
public void CanHandle_Whatever_TrueReturned() { var policy = new StopConsumerErrorPolicy().Build(_serviceProvider); var envelope = new InboundEnvelope( "hey oh!", new MemoryStream(), null, new TestOffset(), TestConsumerEndpoint.GetDefault(), TestConsumerEndpoint.GetDefault().Name); var canHandle = policy.CanHandle( ConsumerPipelineContextHelper.CreateSubstitute(envelope, _serviceProvider), new InvalidOperationException("test")); canHandle.Should().BeTrue(); }
public async Task HandleErrorAsync_Whatever_FalseReturned() { var policy = new StopConsumerErrorPolicy().Build(_serviceProvider); var envelope = new InboundEnvelope( "hey oh!", new MemoryStream(), null, new TestOffset(), TestConsumerEndpoint.GetDefault(), TestConsumerEndpoint.GetDefault().Name); var result = await policy.HandleErrorAsync( ConsumerPipelineContextHelper.CreateSubstitute(envelope, _serviceProvider), new InvalidOperationException("test")); result.Should().BeFalse(); }
public void CanHandle_WithApplyWhen_ExpectedResultReturned( IInboundEnvelope envelope, Exception exception, bool mustApply) { var policy = new TestErrorPolicy() .ApplyWhen( (msg, ex) => msg.Headers.GetValue <int>(DefaultMessageHeaders.FailedAttempts) <= 5 && ex.Message != "no") .Build(Substitute.For <IServiceProvider>()); var canHandle = policy.CanHandle( ConsumerPipelineContextHelper.CreateSubstitute(envelope), exception); canHandle.Should().Be(mustApply); }
public async Task HandleErrorAsync_Whatever_ConsumerCommittedButTransactionAborted() { var policy = new MoveMessageErrorPolicy(TestProducerEndpoint.GetDefault()).Build(_serviceProvider); var envelope = new InboundEnvelope( "hey oh!", new MemoryStream(Encoding.UTF8.GetBytes("hey oh!")), null, new TestOffset(), new TestConsumerEndpoint("source-endpoint"), "source-endpoint"); var transactionManager = Substitute.For <IConsumerTransactionManager>(); await policy.HandleErrorAsync( ConsumerPipelineContextHelper.CreateSubstitute(envelope, _serviceProvider, transactionManager), new InvalidOperationException("test")); await transactionManager.Received(1).RollbackAsync(Arg.Any <InvalidOperationException>(), true); }
public async Task HandleErrorAsync_NotDeserializedInboundMessage_MessagePreserved() { var policy = new MoveMessageErrorPolicy(TestProducerEndpoint.GetDefault()).Build(_serviceProvider); var envelope = new InboundEnvelope( new MemoryStream(Encoding.UTF8.GetBytes("hey oh!")), null, new TestOffset(), TestConsumerEndpoint.GetDefault(), TestConsumerEndpoint.GetDefault().Name); await policy.HandleErrorAsync( ConsumerPipelineContextHelper.CreateSubstitute(envelope, _serviceProvider), new InvalidOperationException("test")); var producer = (TestProducer)_broker.GetProducer(TestProducerEndpoint.GetDefault()); var producedMessage = producer.ProducedMessages.Last(); producedMessage.Message.Should().BeEquivalentTo(producedMessage.Message); }
public async Task HandleErrorAsync_InboundMessage_MessageMoved() { var policy = new MoveMessageErrorPolicy(TestProducerEndpoint.GetDefault()).Build(_serviceProvider); var envelope = new InboundEnvelope( "hey oh!", new MemoryStream(), null, new TestOffset(), TestConsumerEndpoint.GetDefault(), TestConsumerEndpoint.GetDefault().Name); await policy.HandleErrorAsync( ConsumerPipelineContextHelper.CreateSubstitute(envelope, _serviceProvider), new InvalidOperationException("test")); var producer = (TestProducer)_broker.GetProducer(TestProducerEndpoint.GetDefault()); producer.ProducedMessages.Should().HaveCount(1); }