public async Task CopyTo_MessageStreamCopied() { var streamProvider = new MessageStreamProvider <IRawInboundEnvelope>(); var chunkStream = new ChunkStream(streamProvider.CreateStream <IRawInboundEnvelope>()); var output = new MemoryStream(Encoding.UTF8.GetBytes("some junk-")); var copyTask = Task.Run(() => chunkStream.CopyTo(output)); await streamProvider.PushAsync( new RawInboundEnvelope( Encoding.UTF8.GetBytes("Silver"), null, TestConsumerEndpoint.GetDefault(), "test", new TestOffset())); await streamProvider.PushAsync( new RawInboundEnvelope( Encoding.UTF8.GetBytes("back"), null, TestConsumerEndpoint.GetDefault(), "test", new TestOffset())); await streamProvider.CompleteAsync(); await copyTask; chunkStream.Close(); Encoding.UTF8.GetString(output.ToArray()).Should().Be("Silverback"); }
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 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 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 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 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_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_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 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 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 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 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 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 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 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 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 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 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 LogCreatingNewConsumer_Logged() { var expectedMessage = "Creating new consumer for endpoint 'test'."; _silverbackLogger.LogCreatingNewConsumer(TestConsumerEndpoint.GetDefault()); _loggerSubstitute.Received(LogLevel.Information, null, expectedMessage, 1015); }
public void Constructor_NullRawMessage_NoExceptionIsThrown() { var envelope = new RawInboundEnvelope( (Stream?)null, null, TestConsumerEndpoint.GetDefault(), "test", new TestOffset("a", "b")); envelope.Should().NotBeNull(); }
public void LogConsumerLowLevelTrace_NoArguments_Logged() { var consumer = _serviceProvider.GetRequiredService <TestBroker>() .AddConsumer(TestConsumerEndpoint.GetDefault()); var expectedMessage = $"Message | consumerId: {consumer.Id}, endpointName: test"; _silverbackLogger.LogConsumerLowLevelTrace(consumer, "Message"); _loggerSubstitute.Received(LogLevel.Trace, null, expectedMessage, 1999); }
public void LogConsumerStopError_Logged() { var consumer = _serviceProvider.GetRequiredService <TestBroker>() .AddConsumer(TestConsumerEndpoint.GetDefault()); var expectedMessage = "Error occurred while stopping the consumer. " + $"| consumerId: {consumer.Id}, endpointName: test"; _silverbackLogger.LogConsumerStopError(consumer, new InvalidCastException()); _loggerSubstitute.Received(LogLevel.Error, typeof(InvalidCastException), expectedMessage, 1130); }
public void LogConsumerFatalError_Logged() { var consumer = _serviceProvider.GetRequiredService <TestBroker>() .AddConsumer(TestConsumerEndpoint.GetDefault()); var expectedMessage = "Fatal error occurred processing the consumed message. The consumer will be stopped. " + $"| consumerId: {consumer.Id}, endpointName: test"; _silverbackLogger.LogConsumerFatalError(consumer, new AggregateException()); _loggerSubstitute.Received(LogLevel.Critical, typeof(AggregateException), expectedMessage, 1023); }
public void LogConsumerDisconnected_Logged() { var consumer = _serviceProvider.GetRequiredService <TestBroker>() .AddConsumer(TestConsumerEndpoint.GetDefault()); var expectedMessage = "Disconnected consumer from endpoint. " + $"| consumerId: {consumer.Id}, endpointName: test"; _silverbackLogger.LogConsumerDisconnected(consumer); _loggerSubstitute.Received(LogLevel.Debug, null, expectedMessage, 1022); }
public void AddConsumer_SomeEndpoint_ConsumerIsReturned() { var serviceProvider = ServiceProviderHelper.GetServiceProvider( services => services .AddSilverback() .WithConnectionToMessageBroker( options => options .AddBroker <TestBroker>())); var broker = serviceProvider.GetRequiredService <IBroker>(); var consumer = broker.AddConsumer(TestConsumerEndpoint.GetDefault()); consumer.Should().NotBeNull(); }
public void AddConsumer_SameEndpoint_DifferentInstanceIsReturned() { var serviceProvider = ServiceProviderHelper.GetServiceProvider( services => services .AddSilverback() .WithConnectionToMessageBroker( options => options .AddBroker <TestBroker>())); var broker = serviceProvider.GetRequiredService <IBroker>(); var consumer = broker.AddConsumer(TestConsumerEndpoint.GetDefault()); var consumer2 = broker.AddConsumer(new TestConsumerEndpoint("test2")); consumer2.Should().NotBeSameAs(consumer); }
public void LogErrorReconnectingConsumer_Logged() { var consumer = _serviceProvider.GetRequiredService <TestBroker>() .AddConsumer(TestConsumerEndpoint.GetDefault()); var expectedMessage = "Failed to reconnect the consumer. Will retry in 42000 milliseconds. | " + $"consumerId: {consumer.Id}, endpointName: test"; _silverbackLogger.LogErrorReconnectingConsumer( TimeSpan.FromSeconds(42), consumer, new InvalidProgramException()); _loggerSubstitute.Received(LogLevel.Warning, typeof(InvalidProgramException), expectedMessage, 1131); }
public void LogConsumerLowLevelTrace_Logged() { var consumer = _serviceProvider.GetRequiredService <TestBroker>() .AddConsumer(TestConsumerEndpoint.GetDefault()); var expectedMessage = "Message A 42 True " + $"| consumerId: {consumer.Id}, endpointName: test"; _silverbackLogger.LogConsumerLowLevelTrace( consumer, "Message {string} {int} {bool}", () => new object[] { "A", 42, true }); _loggerSubstitute.Received(LogLevel.Trace, null, expectedMessage, 1999); }
private static IRawInboundEnvelope GetEnvelope(Guid?messageId = null, IConsumerEndpoint?endpoint = null) { endpoint ??= TestConsumerEndpoint.GetDefault(); var headers = new[] { new MessageHeader("x-message-id", messageId ?? Guid.NewGuid()) }; return(new RawInboundEnvelope( Array.Empty <byte>(), headers, endpoint, endpoint.Name, new TestOffset())); }