Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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 = ErrorPolicy.Chain(
                ErrorPolicy.Retry().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();
        }
Ejemplo n.º 3
0
        public void Configure(IEndpointsConfigurationBuilder builder)
        {
            // Consume the samples-binary-file-streaming topic
            builder.AddInbound(
                new KafkaConsumerEndpoint("samples-binary-file-streaming")
            {
                Configuration = new KafkaConsumerConfig
                {
                    // The consumer needs at least the bootstrap server address and a group id to be able to connect
                    BootstrapServers = "PLAINTEXT://localhost:9092",
                    GroupId          = GetType().Assembly.FullName ?? "sample-consumer",

                    // AutoOffsetReset.Earliest means that the consumer must start consuming from the beginning of
                    // the topic, if no offset was stored for this consumer group
                    AutoOffsetReset = AutoOffsetReset.Earliest
                },

                // Force the consumer to use the BinaryFileMessageSerializer: this is not strictly necessary when
                // the messages are produced by Silverback but it increases the interoperability, since it doesn't
                // have to rely on the 'x-message-type' header value to switch to the BinaryFileMessageSerializer.
                //
                // In this example the BinaryFileMessageSerializer is also set to return a CustomBinaryFileMessage
                // instead of the normal BinaryFileMessage. This is only needed because we want to read the custom
                // 'x-message-filename' header, otherwise 'Serializer = BinaryFileMessageSerializer.Default' would
                // work perfectly fine (returning a basic BinaryFileMessage, without the extra properties).
                Serializer = new BinaryFileMessageSerializer <CustomBinaryFileMessage>(),

                // Retry each chunks sequence 5 times in case of an exception
                ErrorPolicy = ErrorPolicy.Retry(5)
            });
        }
Ejemplo n.º 4
0
        public void CanHandle_Sequence_FalseReturned()
        {
            var policy   = ErrorPolicy.Move(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 HandleError_WithTransform_MessageTranslated()
        {
            var policy = ErrorPolicy
                         .Move(TestProducerEndpoint.GetDefault())
                         .Transform((originalEnvelope, ex) => { 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(
                producer.ProducedMessages[0].Message,
                producer.ProducedMessages[0].Headers,
                MessageSerializationContext.Empty);

            producedMessage.Should().BeOfType <TestEventTwo>();
        }
        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
        }
Ejemplo n.º 7
0
        public void HandleError_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 = ErrorPolicy.Chain(
                ErrorPolicy.Retry(3),
                testPolicy)
                        .Build(_serviceProvider);

            chain.HandleErrorAsync(
                ConsumerPipelineContextHelper.CreateSubstitute(
                    new InboundEnvelope(
                        rawMessage,
                        headers,
                        new TestOffset(),
                        TestConsumerEndpoint.GetDefault(),
                        TestConsumerEndpoint.GetDefault().Name)),
                new InvalidOperationException("test"));

            testPolicy.Applied.Should().Be(failedAttempts > 3);
        }
Ejemplo n.º 8
0
        public async Task RetryAndSkipPolicies_JsonChunkSequenceStillFailingAfterRetries_OffsetCommitted()
        {
            var tryCount = 0;

            var serviceProvider = Host.ConfigureServices(
                services => services
                .AddLogging()
                .AddSilverback()
                .UseModel()
                .WithConnectionToMessageBroker(
                    options => options.AddMockedKafka(
                        mockedKafkaOptions => mockedKafkaOptions.WithDefaultPartitionsCount(1)))
                .AddEndpoints(
                    endpoints => endpoints
                    .AddOutbound <IIntegrationEvent>(
                        new KafkaProducerEndpoint(DefaultTopicName)
            {
                Chunk = new ChunkSettings
                {
                    Size = 10
                }
            })
                    .AddInbound(
                        new KafkaConsumerEndpoint(DefaultTopicName)
            {
                Configuration = new KafkaConsumerConfig
                {
                    GroupId          = "consumer1",
                    EnableAutoCommit = false,
                    CommitOffsetEach = 1
                },
                ErrorPolicy = ErrorPolicy.Chain(
                    ErrorPolicy.Retry().MaxFailedAttempts(10),
                    ErrorPolicy.Skip())
            }))
                .AddSingletonBrokerBehavior <SpyBrokerBehavior>()
                .AddDelegateSubscriber(
                    (IIntegrationEvent _, IServiceProvider sp) =>
            {
                var logger = sp.GetRequiredService <ISilverbackLogger <ErrorHandlingTests> >();
                tryCount++;
                logger.LogInformation($"Handling message ({tryCount})...");
                throw new InvalidOperationException("Retry!");
            }))
                                  .Run();

            var publisher = serviceProvider.GetRequiredService <IEventPublisher>();
            await publisher.PublishAsync(
                new TestEventOne
            {
                Content = "Hello E2E!"
            });

            await KafkaTestingHelper.WaitUntilAllMessagesAreConsumedAsync();

            tryCount.Should().Be(11);
            DefaultTopic.GetCommittedOffsetsCount("consumer1").Should().Be(3);
        }
Ejemplo n.º 9
0
        public async Task RetryPolicy_SuccessfulAfterSomeTries_OffsetCommitted()
        {
            var tryCount = 0;

            var serviceProvider = Host.ConfigureServices(
                services => services
                .AddLogging()
                .AddSilverback()
                .UseModel()
                .WithConnectionToMessageBroker(options => options.AddMockedKafka())
                .AddEndpoints(
                    endpoints => endpoints
                    .AddOutbound <IIntegrationEvent>(new KafkaProducerEndpoint(DefaultTopicName))
                    .AddInbound(
                        new KafkaConsumerEndpoint(DefaultTopicName)
            {
                Configuration = new KafkaConsumerConfig
                {
                    GroupId          = "consumer1",
                    EnableAutoCommit = false,
                    CommitOffsetEach = 1
                },
                ErrorPolicy = ErrorPolicy.Retry().MaxFailedAttempts(10)
            }))
                .AddSingletonBrokerBehavior <SpyBrokerBehavior>()
                .AddDelegateSubscriber(
                    (IIntegrationEvent _) =>
            {
                tryCount++;
                if (tryCount != 3)
                {
                    throw new InvalidOperationException("Retry!");
                }
            }))
                                  .Run();

            var publisher = serviceProvider.GetRequiredService <IEventPublisher>();
            await publisher.PublishAsync(
                new TestEventOne
            {
                Content = "Hello E2E!"
            });

            await KafkaTestingHelper.WaitUntilAllMessagesAreConsumedAsync();

            tryCount.Should().Be(3);
            DefaultTopic.GetCommittedOffsetsCount("consumer1").Should().Be(1);
        }
        public void CanHandle_Whatever_TrueReturned()
        {
            var policy   = ErrorPolicy.Stop().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();
        }
Ejemplo n.º 11
0
        public async Task HandleErrorAsync_SingleMessage_TrueReturned()
        {
            var policy   = ErrorPolicy.Move(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 async Task HandleErrorAsync_Whatever_FalseReturned()
        {
            var policy   = ErrorPolicy.Stop().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();
        }
Ejemplo n.º 13
0
        public async Task WithFailuresAndRetryPolicy_NewScopeCreatedForEachRetry()
        {
            var lastScopeId = Guid.Empty;
            var scopes      = 0;

            var message = new TestEventOne {
                Content = "Hello E2E!"
            };

            Host.ConfigureServices(
                services => services
                .AddLogging()
                .AddScoped <ScopeIdentifier>()
                .AddSilverback()
                .UseModel()
                .WithConnectionToMessageBroker(
                    options => options
                    .AddMockedKafka())
                .AddEndpoints(
                    endpoints => endpoints
                    .AddOutbound <IIntegrationEvent>(new KafkaProducerEndpoint("test-e2e"))
                    .AddInbound(
                        new KafkaConsumerEndpoint("test-e2e")
            {
                ErrorPolicy = ErrorPolicy.Retry().MaxFailedAttempts(10)
            }))
                .AddDelegateSubscriber(
                    (IIntegrationEvent _, IServiceProvider localServiceProvider) =>
            {
                var newScopeId = localServiceProvider.GetRequiredService <ScopeIdentifier>().ScopeId;
                newScopeId.Should().NotBe(lastScopeId);
                lastScopeId = newScopeId;
                scopes++;

                if (scopes != 3)
                {
                    throw new InvalidOperationException("Retry!");
                }
            }))
            .Run();

            var publisher = Host.ScopedServiceProvider.GetRequiredService <IEventPublisher>();
            await publisher.PublishAsync(message);

            scopes.Should().Be(3);
        }
Ejemplo n.º 14
0
        public async Task RetryPolicy_ProcessingRetriedMultipleTimes()
        {
            var message = new TestEventOne
            {
                Content = "Hello E2E!"
            };
            var tryCount = 0;

            var serviceProvider = Host.ConfigureServices(
                services => services
                .AddLogging()
                .AddSilverback()
                .UseModel()
                .WithConnectionToMessageBroker(options => options.AddMockedKafka())
                .AddEndpoints(
                    endpoints => endpoints
                    .AddOutbound <IIntegrationEvent>(new KafkaProducerEndpoint(DefaultTopicName))
                    .AddInbound(
                        new KafkaConsumerEndpoint(DefaultTopicName)
            {
                Configuration = new KafkaConsumerConfig
                {
                    GroupId = "consumer1",
                    AutoCommitIntervalMs = 100
                },
                ErrorPolicy = ErrorPolicy.Retry().MaxFailedAttempts(10)
            }))
                .AddSingletonBrokerBehavior <SpyBrokerBehavior>()
                .AddDelegateSubscriber(
                    (IIntegrationEvent _) =>
            {
                tryCount++;
                throw new InvalidOperationException("Retry!");
            }))
                                  .Run();

            var publisher = serviceProvider.GetRequiredService <IEventPublisher>();
            await publisher.PublishAsync(message);

            await KafkaTestingHelper.WaitUntilAllMessagesAreConsumedAsync();

            SpyBehavior.OutboundEnvelopes.Should().HaveCount(1);
            tryCount.Should().Be(11);
            SpyBehavior.InboundEnvelopes.Should().HaveCount(11);
            SpyBehavior.InboundEnvelopes.ForEach(envelope => envelope.Message.Should().BeEquivalentTo(message));
        }
Ejemplo n.º 15
0
        public void HandleUnexpectedLogsCorrectly()
        {
            try
            {
                throw new ApplicationException("Troll in the Dungeon");
            }
            catch (Exception e)
            {
                const string expectedMessage = "Caught unexpected 'ApplicationException': 'Troll in the Dungeon'";

                var testLogger = new TestLogger(expectedMessage);
                ErrorPolicy.HandleUnexpected(e, testLogger);

                testLogger.MessageSeen.Should().BeTrue();
                testLogger.SeenCount.Should().Be(1);
                testLogger.FullMessage.Should().Be(expectedMessage);
            }
        }
        public async Task HandleError_NotDeserializedInboundMessage_MessagePreserved()
        {
            var policy   = ErrorPolicy.Move(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 HandleError_InboundMessage_MessageMoved()
        {
            var policy   = ErrorPolicy.Move(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);
        }
Ejemplo n.º 18
0
        public async Task HandleErrorAsync_Whatever_ConsumerCommittedButTransactionAborted()
        {
            var policy   = ErrorPolicy.Move(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);
        }
Ejemplo n.º 19
0
#pragma warning default CA1063  // Implement IDisposable correctly.

        /// <summary>
        /// Attempt to query the backlog length of the queue.
        /// </summary>
        /// <param name="count">The (approximate) count of items in the Channel.</param>
        /// <returns>true if it managed to get count.</returns>
        public bool TryGetCount(out int count)
        {
            // get this using the reflection
            try
            {
                var prop = _sendChannel.GetType()
                           .GetProperty("ItemsCountForDebugger", BindingFlags.Instance | BindingFlags.NonPublic);
                if (prop != null)
                {
                    count = (int)prop.GetValue(_sendChannel);
                    return(true);
                }
            }
            catch (Exception e)
            {
                ErrorPolicy.HandleUnexpected(e, Logger);
            }

            count = default(int);
            return(false);
        }
        public async Task HandleErrorAsync_Whatever_TransactionNotCommittedNorAborted()
        {
            /* The consumer will be stopped and the transaction aborted by the consumer/behavior */

            var policy   = ErrorPolicy.Stop().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.ReceivedWithAnyArgs(0).RollbackAsync(Arg.Any <InvalidOperationException>());
        }
        public async Task HandleError_InboundMessage_MessagePreserved()
        {
            var policy = ErrorPolicy.Move(TestProducerEndpoint.GetDefault()).Build(_serviceProvider);

            var message = new TestEventOne {
                Content = "hey oh!"
            };
            var headers = new MessageHeaderCollection
            {
                { "key1", "value1" },
                { "key2", "value2" }
            };
            var rawContent = await TestConsumerEndpoint.GetDefault().Serializer
                             .SerializeAsync(message, headers, MessageSerializationContext.Empty);

            var envelope = new InboundEnvelope(
                message,
                rawContent,
                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 = producer.ProducedMessages.Last();

            var(deserializedMessage, _) =
                await producedMessage.Endpoint.Serializer.DeserializeAsync(
                    producedMessage.Message,
                    producedMessage.Headers,
                    MessageSerializationContext.Empty);

            deserializedMessage.Should().BeEquivalentTo(envelope.Message);
        }
Ejemplo n.º 22
0
        public async Task HandleErrorAsync_Whatever_ConsumerRolledBackAndTransactionAborted()
        {
            var policy   = ErrorPolicy.Retry().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);
        }
Ejemplo n.º 23
0
        public void HandleError_MultiplePoliciesWithMaxFailedAttempts_CorrectPolicyApplied(
            int failedAttempts,
            int expectedAppliedPolicy)
        {
            var rawMessage = new MemoryStream();
            var headers    = new[]
            {
                new MessageHeader(
                    DefaultMessageHeaders.FailedAttempts,
                    failedAttempts.ToString(CultureInfo.InvariantCulture))
            };

            var policies = new[]
            {
                new TestErrorPolicy().MaxFailedAttempts(2),
                new TestErrorPolicy().MaxFailedAttempts(2),
                new TestErrorPolicy().MaxFailedAttempts(2)
            };

            var chain = ErrorPolicy.Chain(policies)
                        .Build(_serviceProvider);

            chain.HandleErrorAsync(
                ConsumerPipelineContextHelper.CreateSubstitute(
                    new InboundEnvelope(
                        rawMessage,
                        headers,
                        new TestOffset(),
                        TestConsumerEndpoint.GetDefault(),
                        TestConsumerEndpoint.GetDefault().Name)),
                new InvalidOperationException("test"));

            for (var i = 0; i < policies.Length; i++)
            {
                policies[i].As <TestErrorPolicy>().Applied.Should().Be(i == expectedAppliedPolicy);
            }
        }
        public async Task HandleError_SingleMessage_SourceEndpointHeaderIsSet()
        {
            var policy   = ErrorPolicy.Move(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");

            await policy.HandleErrorAsync(
                ConsumerPipelineContextHelper.CreateSubstitute(envelope, _serviceProvider),
                new InvalidOperationException("test"));

            var producer = (TestProducer)_broker.GetProducer(TestProducerEndpoint.GetDefault());

            producer.ProducedMessages.Last()
            .Headers
            .Should().ContainEquivalentOf(
                new MessageHeader(
                    DefaultMessageHeaders.SourceEndpoint,
                    "source-endpoint"));
        }
        public async Task HandleError_InboundMessage_HeadersPreserved()
        {
            var policy  = ErrorPolicy.Move(TestProducerEndpoint.GetDefault()).Build(_serviceProvider);
            var headers = new MessageHeaderCollection
            {
                { "key1", "value1" },
                { "key2", "value2" }
            };
            var envelope = new InboundEnvelope(
                "hey oh!",
                new MemoryStream(Encoding.UTF8.GetBytes("hey oh!")),
                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());

            producer.ProducedMessages.Last().Headers.Should().Contain(envelope.Headers);
        }
Ejemplo n.º 26
0
        public async Task RetryPolicy_EncryptedAndChunkedMessage_RetriedMultipleTimes()
        {
            var message = new TestEventOne
            {
                Content = "Hello E2E!"
            };

            var rawMessage = await Endpoint.DefaultSerializer.SerializeAsync(
                message,
                new MessageHeaderCollection(),
                MessageSerializationContext.Empty);

            var tryCount = 0;

            var serviceProvider = Host.ConfigureServices(
                services => services
                .AddLogging()
                .AddSilverback()
                .UseModel()
                .WithConnectionToMessageBroker(options => options.AddMockedKafka())
                .AddEndpoints(
                    endpoints => endpoints
                    .AddOutbound <IIntegrationEvent>(
                        new KafkaProducerEndpoint(DefaultTopicName)
            {
                Chunk = new ChunkSettings
                {
                    Size = 10
                },
                Encryption = new SymmetricEncryptionSettings
                {
                    Key = AesEncryptionKey
                }
            })
                    .AddInbound(
                        new KafkaConsumerEndpoint(DefaultTopicName)
            {
                Configuration = new KafkaConsumerConfig
                {
                    GroupId          = "consumer1",
                    EnableAutoCommit = false,
                    CommitOffsetEach = 1
                },
                Encryption = new SymmetricEncryptionSettings
                {
                    Key = AesEncryptionKey
                },
                ErrorPolicy = ErrorPolicy.Retry().MaxFailedAttempts(10)
            }))
                .AddSingletonBrokerBehavior <SpyBrokerBehavior>()
                .AddDelegateSubscriber(
                    (IIntegrationEvent _) =>
            {
                tryCount++;
                if (tryCount != 3)
                {
                    throw new InvalidOperationException("Retry!");
                }
            }))
                                  .Run();

            var publisher = serviceProvider.GetRequiredService <IEventPublisher>();
            await publisher.PublishAsync(message);

            await KafkaTestingHelper.WaitUntilAllMessagesAreConsumedAsync();

            SpyBehavior.OutboundEnvelopes.Should().HaveCount(6);
            SpyBehavior.OutboundEnvelopes[0].RawMessage.ReReadAll().Should().NotBeEquivalentTo(rawMessage.Read(10));
            SpyBehavior.OutboundEnvelopes.ForEach(
                envelope =>
            {
                envelope.RawMessage.Should().NotBeNull();
                envelope.RawMessage !.Length.Should().BeLessOrEqualTo(10);
            });
            SpyBehavior.InboundEnvelopes.Should().HaveCount(3);
            SpyBehavior.InboundEnvelopes.ForEach(envelope => envelope.Message.Should().BeEquivalentTo(message));
        }
Ejemplo n.º 27
0
        public async Task RetryPolicy_BinaryFileChunkSequenceProcessedAfterSomeTries_RetriedMultipleTimesAndCommitted()
        {
            var message1 = new BinaryFileMessage
            {
                Content = new MemoryStream(
                    new byte[]
                {
                    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10,
                    0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20,
                    0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30
                }),
                ContentType = "application/pdf"
            };

            var message2 = new BinaryFileMessage
            {
                Content = new MemoryStream(
                    new byte[]
                {
                    0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30,
                    0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x40,
                    0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x50
                }),
                ContentType = "text/plain"
            };

            var tryCount      = 0;
            var receivedFiles = new List <byte[]?>();

            var serviceProvider = Host.ConfigureServices(
                services => services
                .AddLogging()
                .AddSilverback()
                .UseModel()
                .WithConnectionToMessageBroker(
                    options => options.AddMockedKafka(
                        mockedKafkaOptions => mockedKafkaOptions.WithDefaultPartitionsCount(1)))
                .AddEndpoints(
                    endpoints => endpoints
                    .AddOutbound <IBinaryFileMessage>(
                        new KafkaProducerEndpoint(DefaultTopicName)
            {
                Chunk = new ChunkSettings
                {
                    Size = 10
                }
            })
                    .AddInbound(
                        new KafkaConsumerEndpoint(DefaultTopicName)
            {
                Configuration = new KafkaConsumerConfig
                {
                    GroupId          = "consumer1",
                    EnableAutoCommit = false,
                    CommitOffsetEach = 1
                },
                ErrorPolicy = ErrorPolicy.Retry().MaxFailedAttempts(10)
            }))
                .AddDelegateSubscriber(
                    (BinaryFileMessage binaryFile) =>
            {
                if (binaryFile.ContentType != "text/plain")
                {
                    tryCount++;

                    if (tryCount != 2)
                    {
                        // Read only first chunk
                        var buffer = new byte[10];
                        binaryFile.Content !.Read(buffer, 0, 10);
                        throw new InvalidOperationException("Retry!");
                    }
                }

                lock (receivedFiles)
                {
                    receivedFiles.Add(binaryFile.Content.ReadAll());
                }
            })
                .AddSingletonBrokerBehavior <SpyBrokerBehavior>())
                                  .Run();

            var publisher = serviceProvider.GetRequiredService <IPublisher>();

            await publisher.PublishAsync(message1);

            await publisher.PublishAsync(message2);

            await KafkaTestingHelper.WaitUntilAllMessagesAreConsumedAsync();

            tryCount.Should().Be(2);

            SpyBehavior.OutboundEnvelopes.Should().HaveCount(6);
            SpyBehavior.OutboundEnvelopes.ForEach(envelope => envelope.RawMessage.ReReadAll() !.Length.Should().Be(10));
            SpyBehavior.InboundEnvelopes.Should().HaveCount(3);

            SpyBehavior.InboundEnvelopes[0].Message.As <BinaryFileMessage>().ContentType.Should().Be("application/pdf");
            SpyBehavior.InboundEnvelopes[1].Message.As <BinaryFileMessage>().ContentType.Should().Be("application/pdf");
            SpyBehavior.InboundEnvelopes[2].Message.As <BinaryFileMessage>().ContentType.Should().Be("text/plain");

            receivedFiles.Should().HaveCount(2);
            receivedFiles[0].Should().BeEquivalentTo(message1.Content.ReReadAll());
            receivedFiles[1].Should().BeEquivalentTo(message2.Content.ReReadAll());

            DefaultTopic.GetCommittedOffsetsCount("consumer1").Should().Be(6);
        }
Ejemplo n.º 28
0
        public async Task RetryPolicy_JsonChunkSequenceProcessedAfterSomeTries_RetriedMultipleTimesAndCommitted()
        {
            var tryCount = 0;

            var serviceProvider = Host.ConfigureServices(
                services => services
                .AddLogging()
                .AddSilverback()
                .UseModel()
                .WithConnectionToMessageBroker(
                    options => options.AddMockedKafka(
                        mockedKafkaOptions => mockedKafkaOptions.WithDefaultPartitionsCount(1)))
                .AddEndpoints(
                    endpoints => endpoints
                    .AddOutbound <IIntegrationEvent>(
                        new KafkaProducerEndpoint(DefaultTopicName)
            {
                Chunk = new ChunkSettings
                {
                    Size = 10
                }
            })
                    .AddInbound(
                        new KafkaConsumerEndpoint(DefaultTopicName)
            {
                Configuration = new KafkaConsumerConfig
                {
                    GroupId          = "consumer1",
                    EnableAutoCommit = false,
                    CommitOffsetEach = 1
                },
                ErrorPolicy = ErrorPolicy.Retry().MaxFailedAttempts(10)
            }))
                .AddSingletonBrokerBehavior <SpyBrokerBehavior>()
                .AddDelegateSubscriber(
                    (IIntegrationEvent _) =>
            {
                tryCount++;
                if (tryCount % 2 != 0)
                {
                    throw new InvalidOperationException("Retry!");
                }
            }))
                                  .Run();

            var publisher = serviceProvider.GetRequiredService <IEventPublisher>();
            await publisher.PublishAsync(
                new TestEventOne
            {
                Content = "Long message one"
            });

            await publisher.PublishAsync(
                new TestEventOne
            {
                Content = "Long message two"
            });

            await KafkaTestingHelper.WaitUntilAllMessagesAreConsumedAsync();

            SpyBehavior.OutboundEnvelopes.Should().HaveCount(6);
            SpyBehavior.OutboundEnvelopes.ForEach(
                envelope =>
            {
                envelope.RawMessage.Should().NotBeNull();
                envelope.RawMessage !.Length.Should().BeLessOrEqualTo(10);
            });

            tryCount.Should().Be(4);
            SpyBehavior.InboundEnvelopes.Should().HaveCount(4);
            SpyBehavior.InboundEnvelopes[0].Message.As <TestEventOne>().Content.Should().Be("Long message one");
            SpyBehavior.InboundEnvelopes[1].Message.As <TestEventOne>().Content.Should().Be("Long message one");
            SpyBehavior.InboundEnvelopes[2].Message.As <TestEventOne>().Content.Should().Be("Long message two");
            SpyBehavior.InboundEnvelopes[3].Message.As <TestEventOne>().Content.Should().Be("Long message two");

            DefaultTopic.GetCommittedOffsetsCount("consumer1").Should().Be(6);
        }
Ejemplo n.º 29
0
        public async Task SkipPolicy_ChunkedJsonDeserializationError_SequenceSkipped()
        {
            var message = new TestEventOne {
                Content = "Hello E2E!"
            };

            byte[] rawMessage = (await Endpoint.DefaultSerializer.SerializeAsync(
                                     message,
                                     new MessageHeaderCollection(),
                                     MessageSerializationContext.Empty)).ReadAll() ??
                                throw new InvalidOperationException("Serializer returned null");

            byte[] invalidRawMessage = Encoding.UTF8.GetBytes("<what?!><what?!><what?!>");

            Host.ConfigureServices(
                services => services
                .AddLogging()
                .AddSilverback()
                .UseModel()
                .WithConnectionToMessageBroker(
                    options => options.AddMockedKafka(
                        mockedKafkaOptions => mockedKafkaOptions.WithDefaultPartitionsCount(1)))
                .AddEndpoints(
                    endpoints => endpoints
                    .AddInbound(
                        new KafkaConsumerEndpoint(DefaultTopicName)
            {
                Configuration =
                {
                    GroupId          = "consumer1",
                    EnableAutoCommit = false,
                    CommitOffsetEach = 1
                },
                ErrorPolicy = ErrorPolicy.Skip()
            }))
                .AddSingletonSubscriber <OutboundInboundSubscriber>())
            .Run();

            var producer = Broker.GetProducer(new KafkaProducerEndpoint(DefaultTopicName));
            await producer.RawProduceAsync(
                invalidRawMessage.Take(10).ToArray(),
                HeadersHelper.GetChunkHeaders("1", 0, typeof(TestEventOne)));

            await producer.RawProduceAsync(
                invalidRawMessage.Skip(10).Take(10).ToArray(),
                HeadersHelper.GetChunkHeaders("1", 1, typeof(TestEventOne)));

            await producer.RawProduceAsync(
                invalidRawMessage.Skip(20).ToArray(),
                HeadersHelper.GetChunkHeaders("1", 2, true, typeof(TestEventOne)));

            await KafkaTestingHelper.WaitUntilAllMessagesAreConsumedAsync();

            Subscriber.InboundEnvelopes.Should().BeEmpty();
            DefaultTopic.GetCommittedOffsetsCount("consumer1").Should().Be(3);

            await producer.RawProduceAsync(
                rawMessage.Take(10).ToArray(),
                HeadersHelper.GetChunkHeaders("2", 0, typeof(TestEventOne)));

            await producer.RawProduceAsync(
                rawMessage.Skip(10).Take(10).ToArray(),
                HeadersHelper.GetChunkHeaders("2", 1, typeof(TestEventOne)));

            await producer.RawProduceAsync(
                rawMessage.Skip(20).ToArray(),
                HeadersHelper.GetChunkHeaders("2", 2, true, typeof(TestEventOne)));

            await KafkaTestingHelper.WaitUntilAllMessagesAreConsumedAsync();

            Subscriber.InboundEnvelopes.Should().HaveCount(1);
            DefaultTopic.GetCommittedOffsetsCount("consumer1").Should().Be(6);
        }