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);
        }
        public async Task GetLatestValue_SomeStoredOffsetsWithLegacySerialization_LatestOffsetReturned()
        {
            _dbContext.StoredOffsets.Add(
                new StoredOffset
            {
                Key = "topic1|group1|topic1",
#pragma warning disable 618
                Offset = $"{{\"$type\":\"{typeof(TestOffset).AssemblyQualifiedName}\"," +
                         "\"Key\":\"topic1|group1\",\"Value\":\"42\"}"
#pragma warning restore 618
            });
            await _dbContext.SaveChangesAsync();

            var endpoint = new TestConsumerEndpoint("topic1")
            {
                GroupId = "group1"
            };
            var latestOffset = await _offsetStore.GetLatestValueAsync("topic1", endpoint);

            latestOffset.Should().NotBeNull();
            latestOffset !.Value.Should().Be("42");
        }
示例#3
0
        public async Task Exists_SameIdInDifferentTopic_FalseIsReturned()
        {
            var messageId = Guid.NewGuid();
            var endpoint1 = new TestConsumerEndpoint("topic1")
            {
                GroupId = "same"
            };
            var endpoint2 = new TestConsumerEndpoint("topic2")
            {
                GroupId = "same"
            };
            var envelope1 = GetEnvelope(messageId, endpoint1);
            var envelope2 = GetEnvelope(messageId, endpoint2);

            await _log.AddAsync(envelope1);

            await _log.CommitAsync();

            var result = await _log.ExistsAsync(envelope2);

            result.Should().BeFalse();
        }
        public void HandleAsync_ExceptionThrown_ExceptionRethrown()
        {
            var logger = new SilverbackIntegrationLogger <FatalExceptionLoggerConsumerBehavior>(
                new LoggerSubstitute <FatalExceptionLoggerConsumerBehavior>(),
                new LogTemplates());
            var rawEnvelope = new RawInboundEnvelope(
                new byte[5],
                null,
                TestConsumerEndpoint.GetDefault(),
                TestConsumerEndpoint.GetDefault().Name,
                new TestOffset());

            Func <Task> act = () => new FatalExceptionLoggerConsumerBehavior(logger).HandleAsync(
                new ConsumerPipelineContext(
                    rawEnvelope,
                    Substitute.For <IConsumer>(),
                    Substitute.For <ISequenceStore>(),
                    Substitute.For <IServiceProvider>()),
                _ => throw new InvalidCastException());

            act.Should().ThrowExactly <InvalidCastException>();
        }
示例#5
0
        public void CanHandle_WithApplyToAndExclude_ExpectedResultReturned(
            Exception exception,
            bool mustApply)
        {
            var policy = new TestErrorPolicy()
                         .ApplyTo <ArgumentException>()
                         .Exclude <ArgumentOutOfRangeException>()
                         .ApplyTo <FormatException>()
                         .Build(Substitute.For <IServiceProvider>());

            var canHandle = policy.CanHandle(
                ConsumerPipelineContextHelper.CreateSubstitute(
                    new InboundEnvelope(
                        new MemoryStream(),
                        new[] { new MessageHeader(DefaultMessageHeaders.FailedAttempts, "99") },
                        new TestOffset(),
                        TestConsumerEndpoint.GetDefault(),
                        TestConsumerEndpoint.GetDefault().Name)),
                exception);

            canHandle.Should().Be(mustApply);
        }
示例#6
0
        public async Task HandleErrorAsync_WithPublishReturningNull_NoMessagePublished()
        {
            var publisher = Substitute.For<IPublisher>();
            var serviceProvider = new ServiceCollection().AddScoped(_ => publisher)
                .BuildServiceProvider(new ServiceProviderOptions { ValidateScopes = true });

            var policy = new TestErrorPolicy()
                .Publish(_ => null)
                .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.DidNotReceive().PublishAsync(Arg.Any<object>());
        }
示例#7
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);
        }
        public async Task HandleErrorAsync_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 = new ErrorPolicyChain(policies)
                        .Build(_serviceProvider);

            await 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 Transform_SingleMessage_HeadersProperlyModified()
        {
            var policy = new MoveMessageErrorPolicy(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(4); // key, error, traceparent, message-id
        }
        public async Task HandleErrorAsync_InboundMessage_HeadersPreserved()
        {
            var policy  = new MoveMessageErrorPolicy(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);
        }
示例#11
0
        public async Task HandleErrorAsync_WithPublishForwardingException_MessagePublished()
        {
            var publisher = Substitute.For<IPublisher>();
            var serviceProvider = new ServiceCollection().AddScoped(_ => publisher)
                .BuildServiceProvider(new ServiceProviderOptions { ValidateScopes = true });

            var policy = new TestErrorPolicy()
                .Publish((_, exception) => new TestEventTwo { Content = exception.Message })
                .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 TimeoutException("Exception message."));

            await publisher.Received().PublishAsync(
                Arg.Is<TestEventTwo>(message => message.Content == "Exception message."));
        }
示例#12
0
 public void Configure(IEndpointsConfigurationBuilder builder)
 {
     builder.AddInbound(TestConsumerEndpoint.GetDefault());
 }
示例#13
0
        public void GetDisplayName_NotSet_NameReturned()
        {
            var endpoint = new TestConsumerEndpoint("name");

            endpoint.DisplayName.Should().Be("name");
        }