private void SetQosAndCreateConsumers()
        {
            if (!AcknowledgeMode.IsAutoAck() && !Cancelled)
            {
                // Set basicQos before calling basicConsume (otherwise if we are not acking the broker
                // will send blocks of 100 messages)
                try
                {
                    Channel.BasicQos(0, PrefetchCount, true);
                }
                catch (Exception e)
                {
                    ActiveObjectCounter.Release(this);
                    throw new RabbitIOException(e);
                }
            }

            try
            {
                if (!Cancelled)
                {
                    foreach (var queueName in Queues)
                    {
                        if (!MissingQueues.Contains(queueName))
                        {
                            ConsumeFromQueue(queueName);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                throw RabbitExceptionTranslator.ConvertRabbitAccessException(e);
            }
        }
        public bool CommitIfNecessary(bool localTx)
        {
            if (DeliveryTags.Count == 0)
            {
                return(false);
            }

            var isLocallyTransacted = localTx || (Transactional && TransactionSynchronizationManager.GetResource(ConnectionFactory) == null);

            try
            {
                var ackRequired = !AcknowledgeMode.IsAutoAck() && !AcknowledgeMode.IsManual();
                if (ackRequired && (!Transactional || isLocallyTransacted))
                {
                    var deliveryTag = new List <ulong>(DeliveryTags)[DeliveryTags.Count - 1];
                    Channel.BasicAck(deliveryTag, true);
                }

                if (isLocallyTransacted)
                {
                    // For manual acks we still need to commit
                    RabbitUtils.CommitIfNecessary(Channel);
                }
            }
            finally
            {
                DeliveryTags.Clear();
            }

            return(true);
        }
示例#3
0
        private SimpleConsumer Consume(string queue, Connection.IConnection connection)
        {
            R.IModel       channel  = null;
            SimpleConsumer consumer = null;

            try
            {
                channel = connection.CreateChannel(IsChannelTransacted);
                channel.BasicQos(0, (ushort)PrefetchCount, false);  // TODO: Verify this
                consumer = new SimpleConsumer(this, connection, channel, queue);
                channel.QueueDeclarePassive(queue);
                consumer.ConsumerTag = channel.BasicConsume(
                    queue,
                    AcknowledgeMode.IsAutoAck(),
                    ConsumerTagStrategy != null ? ConsumerTagStrategy.CreateConsumerTag(queue) : string.Empty,
                    NoLocal,
                    Exclusive,
                    ConsumerArguments,
                    consumer);
            }

            // catch (AmqpApplicationContextClosedException e)
            // {
            //    throw new AmqpConnectException(e);
            // }
            catch (Exception e)
            {
                RabbitUtils.CloseChannel(channel, _logger);
                RabbitUtils.CloseConnection(connection, _logger);

                consumer = HandleConsumeException(queue, consumer, e);
            }

            return(consumer);
        }
示例#4
0
        protected virtual void ValidateConfiguration()
        {
            if (!(ExposeListenerChannel || !AcknowledgeMode.IsManual()))
            {
                throw new ArgumentException(
                          "You cannot acknowledge messages manually if the channel is not exposed to the listener "
                          + "(please check your configuration and set exposeListenerChannel=true or " +
                          "acknowledgeMode!=MANUAL)");
            }

            if (IsChannelTransacted && AcknowledgeMode.IsAutoAck())
            {
                throw new ArgumentException(
                          "The acknowledgeMode is NONE (autoack in Rabbit terms) which is not consistent with having a "
                          + "transactional channel. Either use a different AcknowledgeMode or make sure " +
                          "channelTransacted=false");
            }
        }
        private void ConsumeFromQueue(string queue)
        {
            var consumer    = new InternalConsumer(this, Channel, queue);
            var consumerTag = Channel.BasicConsume(
                queue,
                AcknowledgeMode.IsAutoAck(),
                TagStrategy != null ? TagStrategy.CreateConsumerTag(queue) : string.Empty,
                NoLocal,
                Exclusive,
                ConsumerArgs,
                consumer);

            if (consumerTag != null)
            {
                Logger?.LogDebug("Started on queue '{queue}' with tag {consumerTag} : {consumer}", queue, consumerTag, ToString());
            }
            else
            {
                Logger?.LogError("Null consumer tag received for queue: {queue} ", queue);
            }
        }
        public void RollbackOnExceptionIfNecessary(Exception ex)
        {
            bool ackRequired = !AcknowledgeMode.IsAutoAck() && (!AcknowledgeMode.IsManual() || ContainerUtils.IsRejectManual(ex));

            try
            {
                if (Transactional)
                {
                    Logger?.LogDebug(ex, "Initiating transaction rollback on application exception");
                    RabbitUtils.RollbackIfNecessary(Channel);
                }

                if (ackRequired)
                {
                    if (DeliveryTags.Count > 0)
                    {
                        ulong deliveryTag = DeliveryTags.Max();
                        Channel.BasicNack(deliveryTag, true, ContainerUtils.ShouldRequeue(DefaultRequeueRejected, ex, Logger));
                    }

                    if (Transactional)
                    {
                        // Need to commit the reject (=nack)
                        RabbitUtils.CommitIfNecessary(Channel);
                    }
                }
            }
            catch (Exception e)
            {
                Logger?.LogError(ex, "Application exception overridden by rollback exception");
                throw RabbitExceptionTranslator.ConvertRabbitAccessException(e); // NOSONAR stack trace loss
            }
            finally
            {
                DeliveryTags.Clear();
            }
        }