Exemple #1
0
        /// <summary>
        /// 消费者收到消息之后,处理方法。
        /// </summary>
        /// <param name="context"></param>
        public void InvokeOnMessageHandler(ConsumerExecutionContext context)
        {
            Preconditions.CheckNotNull(context, "context");

            ConsoleLogger.DebugWrite("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 = context.OnMessageHandler(context.Body, context.Properties, context.Info);
            }
            catch (Exception exception)
            {
                completionTask = TaskHelpers.FromException(exception);
            }

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

            completionTask.ContinueWith(task => this.DoAck(context, this.GetAckStrategy(context, task)));
        }
Exemple #2
0
        /// <summary>
        /// 发送ack回执
        /// </summary>
        /// <param name="context"></param>
        /// <param name="ackStrategy"></param>
        private void DoAck(ConsumerExecutionContext context, AckStrategy ackStrategy)
        {
            const string failedToAckMessage =
                "Basic ack failed because channel was closed with message '{0}'." +
                " Message remains on RabbitMQ and will be retried." +
                " ConsumerTag: {1}, DeliveryTag: {2}";

            AckResult ackResult = AckResult.Exception;

            try
            {
                Preconditions.CheckNotNull(context.Consumer.Model, "context.Consumer.Model");

                ackResult = ackStrategy(context.Consumer.Model, context.Info.DeliverTag);
            }
            catch (AlreadyClosedException alreadyClosedException)
            {
                ConsoleLogger.InfoWrite(failedToAckMessage, alreadyClosedException.Message, context.Info.ConsumerTag, context.Info.DeliverTag);
            }
            catch (IOException ioException)
            {
                ConsoleLogger.InfoWrite(failedToAckMessage, ioException.Message, context.Info.ConsumerTag, context.Info.DeliverTag);
            }
            catch (Exception exception)
            {
                ConsoleLogger.ErrorWrite("Unexpected exception when attempting to ACK or NACK\n{0}", exception);
            }
            finally
            {
                EventBus.Instance.Publish(new AckEvent(context, ackResult));
            }
        }
        private string DeclareErrorExchangeAndBindToDefaultErrorQueue(IModel model, ConsumerExecutionContext context)
        {
            var originalRoutingKey = context.Info.RoutingKey;

            return(this._errorExchanges.GetOrAdd(originalRoutingKey, _ =>
            {
                var exchangeName = Conventions.ErrorExchangeNamingConvention(context.Info);
                model.ExchangeDeclare(exchangeName, ExchangeType.Direct, durable: true);
                model.QueueBind(Conventions.ErrorQueueNamingConvention(), exchangeName, originalRoutingKey);
                return exchangeName;
            }));
        }
        private byte[] CreateErrorMessage(ConsumerExecutionContext context, Exception exception)
        {
            var messageAsString = Encoding.UTF8.GetString(context.Body);
            var error           = new FAN.RabbitMQ.Topology.Error
            {
                RoutingKey      = context.Info.RoutingKey,
                Exchange        = context.Info.Exchange,
                Exception       = exception.ToString(),
                Message         = messageAsString,
                DateTime        = DateTime.Now,
                BasicProperties = context.Properties
            };

            return(MessageToBytes(error));
        }
        public virtual AckStrategy HandleConsumerError(ConsumerExecutionContext context, Exception exception)
        {
            Preconditions.CheckNotNull(context, "context");
            Preconditions.CheckNotNull(exception, "exception");

            try
            {
                this.Connect();

                using (var model = this._connection.CreateModel())
                {
                    var errorExchange = DeclareErrorExchangeQueueStructure(model, context);

                    var messageBody = CreateErrorMessage(context, exception);
                    var properties  = model.CreateBasicProperties();
                    properties.SetPersistent(true);
                    properties.Type = TypeNameSerializer.Serialize(typeof(FAN.RabbitMQ.Topology.Error));

                    model.BasicPublish(errorExchange, context.Info.RoutingKey, properties, messageBody);
                }
            }
            catch (BrokerUnreachableException)
            {
                // thrown if the broker is unreachable during initial creation.
                ConsoleLogger.ErrorWrite("RabbitMQ Consumer Error Handler cannot connect to Broker\n" +
                                         CreateConnectionCheckMessage());
            }
            catch (OperationInterruptedException interruptedException)
            {
                // thrown if the broker connection is broken during declare or publish.
                ConsoleLogger.ErrorWrite("RabbitMQ Consumer Error Handler: Broker connection was closed while attempting to publish Error message.\n" +
                                         string.Format("Message was: '{0}'\n", interruptedException.Message) +
                                         CreateConnectionCheckMessage());
            }
            catch (Exception unexpectedException)
            {
                // Something else unexpected has gone wrong :(
                ConsoleLogger.ErrorWrite("RabbitMQ Consumer Error Handler: Failed to publish error message\nException is:\n"
                                         + unexpectedException);
            }
            return(AckStrategies.Ack);
        }
Exemple #6
0
        private string BuildErrorMessage(ConsumerExecutionContext context, Exception exception)
        {
            var message = Encoding.UTF8.GetString(context.Body);

            var properties        = context.Properties;
            var propertiesMessage = new StringBuilder();

            if (properties != null)
            {
                properties.AppendPropertyDebugStringTo(propertiesMessage);
            }

            return("Exception thrown by subscription callback.\n" +
                   string.Format("\tExchange:    '{0}'\n", context.Info.Exchange) +
                   string.Format("\tRouting Key: '{0}'\n", context.Info.RoutingKey) +
                   string.Format("\tRedelivered: '{0}'\n", context.Info.Redelivered) +
                   string.Format("Message:\n{0}\n", message) +
                   string.Format("BasicProperties:\n{0}\n", propertiesMessage) +
                   string.Format("Exception:\n{0}\n", exception));
        }
Exemple #7
0
        /// <summary>
        /// 消费者处理交付。IBasicConsumer接口自动完成调用。
        /// </summary>
        /// <param name="consumerTag"></param>
        /// <param name="deliveryTag"></param>
        /// <param name="redelivered"></param>
        /// <param name="exchange"></param>
        /// <param name="routingKey"></param>
        /// <param name="properties"></param>
        /// <param name="body"></param>
        public void HandleBasicDeliver(string consumerTag, ulong deliveryTag, bool redelivered, string exchange, string routingKey, IBasicProperties properties, byte[] body)
        {
            ConsoleLogger.DebugWrite("HandleBasicDeliver on consumer: {0}, deliveryTag: {1}", consumerTag, deliveryTag);

            if (this._disposed)
            {
                // this message's consumer has stopped, so just return
                ConsoleLogger.InfoWrite("Consumer has stopped running. Consumer '{0}' on queue '{1}'. Ignoring message", this.ConsumerTag, queue.Name);
                return;
            }

            if (this._onMessage == null)
            {
                ConsoleLogger.ErrorWrite("User consumer callback, 'onMessage' has not been set for consumer '{0}'. Please call InternalConsumer.StartConsuming before passing the consumer to basic.consume", this.ConsumerTag);
                return;
            }

            var messageReceivedInfo = new MessageReceivedInfo(consumerTag, deliveryTag, redelivered, exchange, routingKey, queue.Name);
            var messsageProperties  = new MessageProperties(properties);
            var context             = new ConsumerExecutionContext(this._onMessage, messageReceivedInfo, messsageProperties, body, this);

            this._consumerDispatcher.QueueAction(() => this._handlerRunner.InvokeOnMessageHandler(context));
        }
Exemple #8
0
        /// <summary>
        /// 得到ack的策略
        /// </summary>
        /// <param name="context"></param>
        /// <param name="task"></param>
        /// <returns></returns>
        private AckStrategy GetAckStrategy(ConsumerExecutionContext context, Task task)
        {
            var ackStrategy = AckStrategies.Ack;//默认返回ack

            try
            {
                if (task.IsFaulted)
                {
                    ConsoleLogger.ErrorWrite(BuildErrorMessage(context, task.Exception));
                    ackStrategy = _consumerErrorStrategy.HandleConsumerError(context, task.Exception);
                }
                else if (task.IsCanceled)
                {
                    ackStrategy = this._consumerErrorStrategy.HandleConsumerCancelled(context);
                }
            }
            catch (Exception consumerErrorStrategyError)
            {
                ConsoleLogger.ErrorWrite("Exception in ConsumerErrorStrategy:\n{0}", consumerErrorStrategyError);
                return(AckStrategies.Nothing);
            }
            return(ackStrategy);
        }
 public AckStrategy HandleConsumerCancelled(ConsumerExecutionContext context)
 {
     return(AckStrategies.Ack);
 }
 private string DeclareErrorExchangeQueueStructure(IModel model, ConsumerExecutionContext context)
 {
     this.DeclareDefaultErrorQueue(model);
     return(DeclareErrorExchangeAndBindToDefaultErrorQueue(model, context));
 }
Exemple #11
0
 public AckEvent(ConsumerExecutionContext consumerExecutionContext, AckResult ackResult)
 {
     ConsumerExecutionContext = consumerExecutionContext;
     AckResult = ackResult;
 }