コード例 #1
0
        public async override Task <AckStrategy> InvokeUserMessageHandlerAsync(ConsumerExecutionContext context)
        {
            if (logger.IsDebugEnabled())
            {
                logger.DebugFormat("Received message with receivedInfo={receivedInfo}", context.Info);
            }

            var ackStrategy = await InvokeUserMessageHandlerInternalAsync(context).ConfigureAwait(false);

            return((model, tag) =>
            {
                try
                {
                    return ackStrategy(model, tag);
                }
                catch (Exception exception)
                {
                    logger.Error(
                        exception,
                        "Unexpected exception when attempting to ACK or NACK, receivedInfo={receivedInfo}",
                        context.Info);
                }

                return AckResult.Exception;
            });
        }
コード例 #2
0
        public When_a_user_handler_is_executed()
        {
            var consumerErrorStrategy = Substitute.For <IConsumerErrorStrategy>();
            var eventBus = new EventBus();

            var handlerRunner = new HandlerRunner(consumerErrorStrategy, eventBus);

            Func <byte[], MessageProperties, MessageReceivedInfo, Task> userHandler = (body, properties, info) =>
                                                                                      Task.Factory.StartNew(() =>
            {
                deliveredBody       = body;
                deliveredProperties = properties;
                deliveredInfo       = info;
            });

            var consumer = Substitute.For <IBasicConsumer>();

            channel = Substitute.For <IModel>();
            consumer.Model.Returns(channel);

            var context = new ConsumerExecutionContext(
                userHandler, messageInfo, messageProperties, messageBody, consumer);

            var autoResetEvent = new AutoResetEvent(false);

            eventBus.Subscribe <AckEvent>(x => autoResetEvent.Set());

            handlerRunner.InvokeUserMessageHandler(context);

            autoResetEvent.WaitOne(1000);
        }
コード例 #3
0
        public override AckStrategy HandleConsumerError(ConsumerExecutionContext context, Exception exception)
        {
            var ex = exception.InnerException;

            if (ex.GetType() == typeof(HBFlowException))
            {
                return(AckStrategies.NackWithRequeue);
            }

            var count = 0;
            var id    = context.Properties.CorrelationId;

            if (!Keys.ContainsKey(id))
            {
                Keys.Add(id, 0);
            }

            Keys.TryGetValue(id, out count);

            if (count == 0)
            {
                LoggerHelper.Error(ex);
            }

            count++;
            Keys[id] = count;

            return(AckStrategies.NackWithRequeue);
        }
コード例 #4
0
        public override AckStrategy HandleConsumerError(ConsumerExecutionContext context, Exception exception)
        {
            string message;

            if (!_disposed && !_disposing)
            {
                ConsumerException consumerException;
                switch (exception)
                {
                case ConsumerException ce:
                    consumerException = ce;
                    break;

                case var other:
                    consumerException = new ConsumerException(other);
                    break;
                }

                switch (consumerException.InnerException)
                {
                case OperationCanceledException _:
                    return(AckStrategies.NackWithRequeue);

                case UnhandledMessageTypeException _:
                    _logger?.LogError($"Unhandled message type: {context.Properties.Type}");

                    return(AckStrategies.NackWithoutRequeue);

                default:
                    var innerException      = consumerException.InnerException;
                    var innerInnerException = consumerException.InnerException?.InnerException;

                    if (!string.IsNullOrWhiteSpace(innerException?.Message) || innerInnerException != null)
                    {
                        message = $"Consumer exception: {innerException?.Message}\n{innerException?.StackTrace}";

                        _logger?.LogError(consumerException, message);
                    }

                    switch (consumerException.InnerException)
                    {
                    case IAckException _:
                        return(AckStrategies.Ack);

                    case INackWithRequeueException _:
                        return(AckStrategies.NackWithRequeue);

                    default:
                        return(AckStrategies.NackWithoutRequeue);
                    }
                }
            }

            message = $"The {nameof(ConsumerErrorStrategy)} has already been disposed, while attempting to handle a " +
                      "consumer error, and the received message ({info}) will be requeued.";

            _logger?.LogError(message, context.ReceivedInfo);

            return(AckStrategies.NackWithRequeue);
        }
コード例 #5
0
        public void Should_not_reconnect_if_has_been_disposed()
        {
            const string originalMessage     = "{ Text:\"Hello World\"}";
            var          originalMessageBody = Encoding.UTF8.GetBytes(originalMessage);

            var exception = new Exception("I just threw!");

            var context = new ConsumerExecutionContext(
                (bytes, properties, arg3) => null,
                new MessageReceivedInfo("consumertag", 0, false, "orginalExchange", "originalRoutingKey", "queue"),
                new MessageProperties
            {
                CorrelationId = "123",
                AppId         = "456"
            },
                originalMessageBody
                );

            connectionFactory = Substitute.For <IConnectionFactory>();

            consumerErrorStrategy = new DefaultConsumerErrorStrategy(
                connectionFactory,
                Substitute.For <ISerializer>(),
                Substitute.For <IConventions>(),
                Substitute.For <ITypeNameSerializer>(),
                Substitute.For <IErrorMessageSerializer>());

            consumerErrorStrategy.Dispose();

            var ackStrategy = consumerErrorStrategy.HandleConsumerError(context, exception);

            connectionFactory.DidNotReceive().CreateConnection();

            Assert.Equal(AckStrategies.NackWithRequeue, ackStrategy);
        }
        public override AckStrategy HandleConsumerError(ConsumerExecutionContext context, Exception exception)
        {
            object deathHeaderObject;

            if (!context.Properties.Headers.TryGetValue("x-death", out deathHeaderObject))
            {
                return(AckStrategies.NackWithoutRequeue);
            }

            var deathHeaders = deathHeaderObject as IList;

            if (deathHeaders == null)
            {
                return(AckStrategies.NackWithoutRequeue);
            }

            var retries = 0;

            foreach (IDictionary header in deathHeaders)
            {
                var count = int.Parse(header["count"].ToString());
                retries += count;
            }

            if (retries < 3)
            {
                return(AckStrategies.NackWithoutRequeue);
            }

            return(base.HandleConsumerError(context, exception));
        }
コード例 #7
0
        /// <inheritdoc />
        public override Task <AckStrategy> InvokeUserMessageHandlerAsync(ConsumerExecutionContext context)
        {
            _logger.Debug("Received \n\tRoutingKey: '{0}'\n\tCorrelationId: '{1}'\n\tConsumerTag: '{2}'\n\tDeliveryTag: {3}\n\tRedelivered: {4}",
                          context.Info.RoutingKey,
                          context.Properties.CorrelationId,
                          context.Info.ConsumerTag,
                          context.Info.DeliverTag,
                          context.Info.Redelivered);

            Task completionTask;

            try {
                completionTask = _policy.Execute(() => {
                    var task = context.UserHandler(context.Body, context.Properties, context.Info);

                    if (task.IsFaulted)
                    {
                        throw task.Exception.GetBaseException();
                    }

                    return(task);
                });
            }
            catch (Exception exception) {
                completionTask = Task.FromException(exception);
            }

            if (completionTask.Status == TaskStatus.Created)
            {
                _logger.Error("Task returned from consumer callback is not started. ConsumerTag: '{0}'", context.Info.ConsumerTag);
                return(null);
            }

            return(completionTask.ContinueWith(task => AckStrategies.Ack));
        }
コード例 #8
0
        public void SetUp()
        {
            //var logger = new ConsoleLogger();
            var logger = MockRepository.GenerateStub <IEasyNetQLogger>();
            var consumerErrorStrategy = MockRepository.GenerateStub <IConsumerErrorStrategy>();
            var eventBus = new EventBus();

            handlerRunner = new HandlerRunner(logger, consumerErrorStrategy, eventBus);

            Func <byte[], MessageProperties, MessageReceivedInfo, Task> userHandler = (body, properties, info) =>
                                                                                      Task.Factory.StartNew(() =>
            {
                deliveredBody       = body;
                deliveredProperties = properties;
                deliveredInfo       = info;
            });

            var consumer = MockRepository.GenerateStub <IBasicConsumer>();

            channel = MockRepository.GenerateStub <IModel>();
            consumer.Stub(x => x.Model).Return(channel).Repeat.Any();

            var context = new ConsumerExecutionContext(
                userHandler, messageInfo, messageProperties, messageBody, consumer);

            var autoResetEvent = new AutoResetEvent(false);

            eventBus.Subscribe <AckEvent>(x => autoResetEvent.Set());

            handlerRunner.InvokeUserMessageHandler(context);

            autoResetEvent.WaitOne(1000);
        }
コード例 #9
0
        private string DeclareErrorExchangeQueueStructure(IModel model, ConsumerExecutionContext context)
        {
            return("ErrorExchange_" + context.Info.RoutingKey);

            //   DeclareDefaultErrorQueue(model);
            return(DeclareErrorExchangeAndBindToDefaultErrorQueue(model, context));
        }
コード例 #10
0
        public When_a_user_handler_is_failed()
        {
            consumerErrorStrategy = Substitute.For <IConsumerErrorStrategy>();
            consumerErrorStrategy.HandleConsumerError(null, null).ReturnsForAnyArgs(AckStrategies.Ack);

            var handlerRunner = new HandlerRunner(consumerErrorStrategy);

            var consumer = Substitute.For <IBasicConsumer>();

            channel = Substitute.For <IModel>();
            consumer.Model.Returns(channel);

            context = new ConsumerExecutionContext(
                async(body, properties, info) => throw new Exception(),
                messageInfo,
                messageProperties,
                messageBody
                );

            var handlerTask = handlerRunner.InvokeUserMessageHandlerAsync(context)
                              .ContinueWith(async x =>
            {
                var ackStrategy = await x.ConfigureAwait(false);
                return(ackStrategy(channel, 42));
            }, TaskContinuationOptions.ExecuteSynchronously)
                              .Unwrap();

            if (!handlerTask.Wait(5000))
            {
                throw new TimeoutException();
            }
        }
コード例 #11
0
        public When_a_user_handler_is_cancelled()
        {
            consumerErrorStrategy = Substitute.For <IConsumerErrorStrategy>();
            var eventBus = new EventBus();

            var handlerRunner = new HandlerRunner(consumerErrorStrategy, eventBus);

            Func <byte[], MessageProperties, MessageReceivedInfo, Task> userHandler = (body, properties, info) =>
                                                                                      Task.Run(() => throw new OperationCanceledException());

            var consumer = Substitute.For <IBasicConsumer>();
            var channel  = Substitute.For <IModel>();

            consumer.Model.Returns(channel);

            context = new ConsumerExecutionContext(userHandler, messageInfo, messageProperties, messageBody, consumer);

            var autoResetEvent = new AutoResetEvent(false);

            eventBus.Subscribe <AckEvent>(x => autoResetEvent.Set());

            handlerRunner.InvokeUserMessageHandler(context);

            autoResetEvent.WaitOne(1000);
        }
コード例 #12
0
        public void SetUp()
        {
            var conventions = new Conventions
            {
                ConsumerTagConvention = () => consumerTag
            };

            consumerErrorStrategy = MockRepository.GenerateStub <IConsumerErrorStrategy>();
            consumerErrorStrategy.Stub(x => x.HandleConsumerError(null, null))
            .IgnoreArguments()
            .WhenCalled(i =>
            {
                basicDeliverEventArgs = (ConsumerExecutionContext)i.Arguments[0];
                raisedException       = (Exception)i.Arguments[1];
            });
            consumerErrorStrategy.Stub(x => x.PostExceptionAckStrategy()).Return(PostExceptionAckStrategy.ShouldAck);

            mockBuilder = new MockBuilder(x => x
                                          .Register <IConventions>(_ => conventions)
                                          .Register(_ => consumerErrorStrategy)
                                          //.Register<IEasyNetQLogger>(_ => new ConsoleLogger())
                                          );

            mockBuilder.Bus.Subscribe <MyMessage>(subscriptionId, message =>
            {
                throw originalException;
            });


            const string text = "Hello there, I am the text!";

            originalMessage = new MyMessage {
                Text = text
            };

            var body = new JsonSerializer().MessageToBytes(originalMessage);

            // deliver a message
            mockBuilder.Consumers[0].HandleBasicDeliver(
                consumerTag,
                deliveryTag,
                false, // redelivered
                typeName,
                "#",
                new BasicProperties
            {
                Type          = typeName,
                CorrelationId = correlationId
            },
                body);

            // wait for the subscription thread to handle the message ...
            var autoResetEvent          = new AutoResetEvent(false);
            var handlerExecutionContext = (HandlerRunner)mockBuilder.ServiceProvider.Resolve <IHandlerRunner>();

            handlerExecutionContext.SynchronisationAction = () => autoResetEvent.Set();
            autoResetEvent.WaitOne(1000);
        }
コード例 #13
0
        /// <summary>
        /// 声明重试队列
        /// </summary>
        /// <param name="model"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        private string DeclareReTryExchangeWithQueue(IModel model, ConsumerExecutionContext context)
        {
            var reTryExchangeName = $"ReTry_{context.Info.Exchange}";
            var reTryQueueName    = $"ReTry_{context.Info.Queue}";
            var routingKey        = string.IsNullOrEmpty(context.Info.RoutingKey) ? context.Info.Queue.Substring(context.Info.Exchange.Length + 1) : context.Info.RoutingKey;

            DeclareAndBindExchangeWithQueue(model, reTryExchangeName, reTryQueueName, routingKey);
            return(reTryExchangeName);
        }
コード例 #14
0
 public AckStrategy HandleConsumerError(ConsumerExecutionContext context, Exception exception)
 {
     //FileNotFoundException
     if (exception.GetType().Equals(typeof(FileNotFoundException)))
     {
         return(AckStrategies.NackWithoutRequeue);
     }
     return(AckStrategies.NackWithRequeue);
 }
コード例 #15
0
        public When_the_handler_throws_an_exception()
        {
            var conventions = new Conventions(new TypeNameSerializer())
            {
                ConsumerTagConvention = () => consumerTag
            };

            consumerErrorStrategy = Substitute.For <IConsumerErrorStrategy>();
            consumerErrorStrategy.HandleConsumerError(null, null)
            .ReturnsForAnyArgs(i =>
            {
                basicDeliverEventArgs = (ConsumerExecutionContext)i[0];
                raisedException       = (Exception)i[1];
                return(AckStrategies.Ack);
            });

            mockBuilder = new MockBuilder(x => x
                                          .Register <IConventions>(_ => conventions)
                                          .Register(_ => consumerErrorStrategy)
                                          //.Register<IEasyNetQLogger>(_ => new ConsoleLogger())
                                          );

            mockBuilder.Bus.Subscribe <MyMessage>(subscriptionId, message =>
            {
                throw originalException;
            });


            const string text = "Hello there, I am the text!";

            originalMessage = new MyMessage {
                Text = text
            };

            var body = new JsonSerializer(new TypeNameSerializer()).MessageToBytes(originalMessage);

            // deliver a message
            mockBuilder.Consumers[0].HandleBasicDeliver(
                consumerTag,
                deliveryTag,
                false, // redelivered
                typeName,
                "#",
                new BasicProperties
            {
                Type          = typeName,
                CorrelationId = correlationId
            },
                body);

            // wait for the subscription thread to handle the message ...
            var autoResetEvent = new AutoResetEvent(false);

            mockBuilder.EventBus.Subscribe <AckEvent>(x => autoResetEvent.Set());
            autoResetEvent.WaitOne(1000);
        }
コード例 #16
0
        private byte[] CreateErrorMessage(ConsumerExecutionContext context, Exception exception)
        {
            var error = new Error
            {
                ErrorMessage = exception.Message,
                RawMessage   = context.Body
            };

            return(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(error)));
        }
コード例 #17
0
        public AckStrategy HandleConsumerError(ConsumerExecutionContext context, Exception exception)
        {
            logger.Error(
                exception,
                "Exception thrown by subscription callback, receivedInfo={receivedInfo}, properties={properties}",
                context.Info,
                context.Properties
                );

            return(AckStrategies.NackWithRequeue);
        }
コード例 #18
0
        private string DeclareErrorExchangeAndBindToDefaultErrorQueue(IModel model, ConsumerExecutionContext context)
        {
            var originalRoutingKey = context.Info.RoutingKey;

            return(this.errorExchanges.GetOrAdd(originalRoutingKey, (Func <string, string>)(_ =>
            {
                var exchange = this.conventions.ErrorExchangeNamingConvention(context.Info);
                model.ExchangeDeclare(exchange, "direct", true);
                model.QueueBind(this.conventions.ErrorQueueNamingConvention(), exchange, originalRoutingKey);
                return exchange;
            })));
        }
コード例 #19
0
        private string DeclareErrorExchangeAndBindToDefaultErrorQueue(IModel model, ConsumerExecutionContext context)
        {
            var originalRoutingKey = context.Info.RoutingKey;

            return(errorExchanges.GetOrAdd(originalRoutingKey, _ =>
            {
                var exchangeName = conventions.ErrorExchangeNamingConvention(context.Info);
                model.ExchangeDeclare(exchangeName, ExchangeType.Direct, durable: true);
                model.QueueBind(conventions.ErrorQueueNamingConvention(), exchangeName, originalRoutingKey);
                return exchangeName;
            }));
        }
コード例 #20
0
        private string DeclareErrorExchangeAndBindToDefaultErrorQueue(IModel model, ConsumerExecutionContext context)
        {
            var originalRoutingKey = context.Info.RoutingKey;

            return(_errorExchanges.GetOrAdd(originalRoutingKey, _ =>
            {
                var exchangeName = _conventions.ErrorExchangeNamingConvention(context.Info);
                model.ExchangeDeclare(exchangeName, ExchangeType.Direct, durable: true);
                model.QueueBind(
                    $"{(string.IsNullOrEmpty(context.Info.Queue) ? context.Info.RoutingKey : context.Info.ConsumerTag)}_deadletter", exchangeName, originalRoutingKey);
                return exchangeName;
            }));
        }
コード例 #21
0
        public override AckStrategy HandleConsumerError(ConsumerExecutionContext context, Exception exception)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (exception == null)
            {
                throw new ArgumentNullException(nameof(exception));
            }

            try
            {
                if (context.Properties.Headers.ContainsKey(RetryConstants.RetryCountKey))
                {
                    var retryCount = Convert.ToInt32((long)context.Properties.Headers[RetryConstants.RetryCountKey]);
                    if (retryCount > this.maxAttemptsCount)
                    {
                        this.logger.ErrorWrite(
                            "EasyNetQ Consumer Error Handler: Skip republish to dead-letter queue - max attempts count exceeded.");
                        //LOG MESSAGE HERE
                        return(AckStrategies.Ack);
                    }
                }

                this.Connect();
                using (var model = this.connection.CreateModel())
                {
                    var exchange        = this.DeclareErrorExchangeQueueStructure(model, context);
                    var errorMessage    = this.CreateErrorMessage(context, exception);
                    var basicProperties = model.CreateBasicProperties();
                    basicProperties.SetPersistent(true);
                    basicProperties.Type = this.typeNameSerializer.Serialize(typeof(Error));
                    model.BasicPublish(exchange, context.Info.RoutingKey, basicProperties, errorMessage);
                }
            }
            catch (BrokerUnreachableException ex)
            {
                this.logger.ErrorWrite("EasyNetQ Consumer Error Handler cannot connect to Broker\n" + this.CreateConnectionCheckMessage(), new object[0]);
            }
            catch (OperationInterruptedException ex)
            {
                this.logger.ErrorWrite("EasyNetQ Consumer Error Handler: Broker connection was closed while attempting to publish Error message.\n" +
                                       $"Message was: '{(object)ex.Message}'\n" + this.CreateConnectionCheckMessage(), new object[0]);
            }
            catch (Exception ex)
            {
                this.logger.ErrorWrite("EasyNetQ Consumer Error Handler: Failed to publish error message\nException is:\n" + (object)ex, new object[0]);
            }
            return(AckStrategies.Ack);
        }
コード例 #22
0
        private static void RetryMessage(ConsumerExecutionContext context, IModel model, MessageProperties properties, int flrRetry)
        {
            // Ensure and update the retrycount
            properties.Headers.Remove("easynetq.retry.count");
            properties.Headers.Add("easynetq.retry.count", flrRetry);

            // Copy all properties to BasicProperties for the Rabbit
            var basicProperties = model.CreateBasicProperties();

            properties.CopyTo(basicProperties);

            // Resend the message
            model.BasicPublish(context.Info.Exchange, context.Info.RoutingKey, basicProperties, context.Body);
        }
コード例 #23
0
        private byte[] CreateErrorMessage(ConsumerExecutionContext context, Exception exception)
        {
            var messageAsString = Encoding.UTF8.GetString(context.Body);
            var error           = new Error
            {
                RoutingKey      = context.Info.RoutingKey,
                Exchange        = context.Info.Exchange,
                Exception       = exception.ToString(),
                Message         = messageAsString,
                DateTime        = DateTime.UtcNow,
                BasicProperties = context.Properties
            };

            return(serializer.MessageToBytes(error));
        }
コード例 #24
0
        private void SendMessageToErrorQueue(ConsumerExecutionContext context, Exception exception, IModel model, MessageProperties properties)
        {
            var errorExchange = DeclareErrorExchangeQueueStructure(model, context);

            _logger.InfoWrite(
                $"(DEAD LETTERED) Second Level Retry max reached for message of type [{properties.Type}], message is sent to dead letter queue: [{errorExchange}].");

            var messageBody = CreateDefaultErrorMessage(context, exception.InnerException);

            var errorProperties = model.CreateBasicProperties();

            properties.CopyTo(errorProperties);
            errorProperties.Persistent = true;
            errorProperties.Type       = _typeNameSerializer.Serialize(typeof(RabbitErrorMessage));

            model.BasicPublish(errorExchange, context.Info.RoutingKey, errorProperties, messageBody);
        }
コード例 #25
0
        private async Task <AckStrategy> InvokeUserMessageHandlerInternalAsync(ConsumerExecutionContext context)
        {
            try
            {
                await _policy.ExecuteAsync(async() =>
                {
                    await context.UserHandler(context.Body, context.Properties, context.Info).ConfigureAwait(false);
                });
            }
            catch (Exception exception)
            {
                logger.Error(exception, "Consumer error strategy has failed");
                return(AckStrategies.NackWithoutRequeue);
            }

            return(AckStrategies.Ack);
        }
コード例 #26
0
        public When_using_default_consumer_error_strategy()
        {
            var customConventions = new Conventions(new DefaultTypeNameSerializer())
            {
                ErrorQueueNamingConvention    = info => "CustomEasyNetQErrorQueueName",
                ErrorExchangeNamingConvention = info => "CustomErrorExchangePrefixName." + info.RoutingKey
            };

            mockBuilder = new MockBuilder();

            var connectionConfiguration = new ConnectionConfiguration();
            var connection = new PersistentConnection(connectionConfiguration, mockBuilder.ConnectionFactory, new EventBus());

            errorStrategy = new DefaultConsumerErrorStrategy(
                connection,
                new JsonSerializer(),
                customConventions,
                new DefaultTypeNameSerializer(),
                new DefaultErrorMessageSerializer(),
                connectionConfiguration
                );

            const string originalMessage     = "";
            var          originalMessageBody = Encoding.UTF8.GetBytes(originalMessage);

            var context = new ConsumerExecutionContext(
                (bytes, properties, info, cancellation) => Task.FromResult(AckStrategies.Ack),
                new MessageReceivedInfo("consumerTag", 0, false, "orginalExchange", "originalRoutingKey", "queue"),
                new MessageProperties
            {
                CorrelationId = string.Empty,
                AppId         = string.Empty
            },
                originalMessageBody
                );

            try
            {
                errorAckStrategy  = errorStrategy.HandleConsumerError(context, new Exception());
                cancelAckStrategy = errorStrategy.HandleConsumerCancelled(context);
            }
            catch (Exception)
            {
                // swallow
            }
        }
コード例 #27
0
        public void Should_handle_an_exception_by_writing_to_the_error_queue()
        {
            const string originalMessage     = "{ Text:\"Hello World\"}";
            var          originalMessageBody = Encoding.UTF8.GetBytes(originalMessage);

            var exception = new Exception("I just threw!");

            var context = new ConsumerExecutionContext(
                (bytes, properties, arg3) => null,
                new MessageReceivedInfo("consumertag", 0, false, "orginalExchange", "originalRoutingKey", "queue"),
                new MessageProperties
            {
                CorrelationId = "123",
                AppId         = "456"
            },
                originalMessageBody,
                MockRepository.GenerateStub <IBasicConsumer>()
                );

            consumerErrorStrategy.HandleConsumerError(context, exception);

            Thread.Sleep(100);

            // Now get the error message off the error queue and assert its properties
            using (var connection = connectionFactory.CreateConnection())
                using (var model = connection.CreateModel())
                {
                    var getArgs = model.BasicGet(conventions.ErrorQueueNamingConvention(), true);
                    if (getArgs == null)
                    {
                        Assert.Fail("Nothing on the error queue");
                    }
                    else
                    {
                        var message = serializer.BytesToMessage <Error>(getArgs.Body);

                        message.RoutingKey.ShouldEqual(context.Info.RoutingKey);
                        message.Exchange.ShouldEqual(context.Info.Exchange);
                        message.Message.ShouldEqual(originalMessage);
                        message.Exception.ShouldEqual("System.Exception: I just threw!");
                        message.DateTime.Date.ShouldEqual(DateTime.Now.Date);
                        message.BasicProperties.CorrelationId.ShouldEqual(context.Properties.CorrelationId);
                        message.BasicProperties.AppId.ShouldEqual(context.Properties.AppId);
                    }
                }
        }
コード例 #28
0
        private byte[] CreateErrorMessage(ConsumerExecutionContext context, Exception exception)
        {
            var @string = Encoding.UTF8.GetString(context.Body);

            if (context.Properties?.Headers != null)
            {
                if (context.Properties.Headers.ContainsKey(RetryConstants.RetryCountKey))
                {
                    var retryCount = Convert.ToInt32((long)context.Properties.Headers[RetryConstants.RetryCountKey]);
                    context.Properties.Headers[RetryConstants.RetryCountKey] = ++retryCount;
                }
                else
                {
                    context.Properties.Headers.Add(RetryConstants.RetryCountKey, 0);
                }
            }
            var aggregateException = exception as AggregateException;
            var resultException    = aggregateException != null
                ? aggregateException.InnerException
                : exception;

            try
            {
                var message = new Error()
                {
                    RoutingKey      = context.Info.RoutingKey,
                    Exchange        = context.Info.Exchange,
                    Exception       = resultException.ToString(),
                    Message         = @string,
                    DateTime        = DateTime.Now,
                    BasicProperties = context.Properties
                };
                return(this.serializer.MessageToBytes(message));
            }
            catch (JsonSerializationException ex)
            {
                this.logger.ErrorWrite(ex);
                throw;
            }
            catch (Exception ex)
            {
                this.logger.ErrorWrite(ex);
                throw;
            }
        }
コード例 #29
0
        public override AckStrategy HandleConsumerError(ConsumerExecutionContext context, Exception exception)
        {
            var ex = exception;

            if (ex is AggregateException)
            {
                ex = ex.InnerException;
            }
            if (ex is NoAckWithRequeueException)
            {
                return(AckStrategies.NackWithRequeue);
            }
            if (ex is NoAckWithoutRequeueException)
            {
                return(AckStrategies.NackWithoutRequeue);
            }
            return(base.HandleConsumerError(context, exception));
        }
コード例 #30
0
        public void SetUp()
        {
            var customConventions = new Conventions(new TypeNameSerializer())
            {
                ErrorQueueNamingConvention    = () => "CustomEasyNetQErrorQueueName",
                ErrorExchangeNamingConvention = info => "CustomErrorExchangePrefixName." + info.RoutingKey
            };

            mockBuilder = new MockBuilder();

            errorStrategy = new DefaultConsumerErrorStrategy(
                mockBuilder.ConnectionFactory,
                new JsonSerializer(new TypeNameSerializer()),
                MockRepository.GenerateStub <IEasyNetQLogger>(),
                customConventions,
                new TypeNameSerializer(),
                new DefaultErrorMessageSerializer());

            const string originalMessage     = "";
            var          originalMessageBody = Encoding.UTF8.GetBytes(originalMessage);

            var context = new ConsumerExecutionContext(
                (bytes, properties, arg3) => null,
                new MessageReceivedInfo("consumerTag", 0, false, "orginalExchange", "originalRoutingKey", "queue"),
                new MessageProperties
            {
                CorrelationId = string.Empty,
                AppId         = string.Empty
            },
                originalMessageBody,
                MockRepository.GenerateStub <IBasicConsumer>()
                );

            try
            {
                errorAckStrategy  = errorStrategy.HandleConsumerError(context, new Exception());
                cancelAckStrategy = errorStrategy.HandleConsumerCancelled(context);
            }
            catch (Exception)
            {
                // swallow
            }
        }