private IMessage Handle(Delivery delivery)
        {
            if (delivery == null && Shutdown != null)
            {
                throw new ShutdownSignalException(Shutdown);
            }

            if (delivery == null)
            {
                return(null);
            }

            var body = delivery.Body;
            var messageProperties = MessageHeadersConverter.ToMessageHeaders(delivery.Properties, delivery.Envelope, EncodingUtils.Utf8);
            var accesor           = RabbitHeaderAccessor.GetMutableAccessor(messageProperties);

            accesor.ConsumerTag   = delivery.ConsumerTag;
            accesor.ConsumerQueue = delivery.Queue;
            var message = Message.Create(body, accesor.MessageHeaders);

            Logger?.LogDebug("Received message: {message}", message);
            if (messageProperties.DeliveryTag() != null)
            {
                DeliveryTags.Add(messageProperties.DeliveryTag().Value);
            }

            if (Transactional && !LocallyTransacted)
            {
                ConnectionFactoryUtils.RegisterDeliveryTag(ConnectionFactory, Channel, delivery.Envelope.DeliveryTag);
            }

            return(message);
        }
        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);
        }
        public void Stop()
        {
            if (AbortStarted == 0)
            {
                AbortStarted = DateTimeOffset.Now.ToUnixTimeMilliseconds();
            }

            if (!Cancelled)
            {
                try
                {
                    RabbitUtils.CloseMessageConsumer(Channel, GetConsumerTags(), Transactional);
                }
                catch (Exception e)
                {
                    Logger?.LogDebug(e, "Error closing consumer: {consumer}", ToString());
                }
            }

            Logger?.LogDebug("Closing Rabbit Channel : {channel}", Channel);
            RabbitUtils.SetPhysicalCloseRequired(Channel, true);
            ConnectionFactoryUtils.ReleaseResources(ResourceHolder);
            DeliveryTags.Clear();
            _ = Consumers.TakeWhile((kvp) => Consumers.Count > 0);
            _ = Queue.TakeWhile((d) => Queue.Count > 0);
        }
        public void Start()
        {
            Logger?.LogDebug("Starting consumer {consumer}", ToString());
            try
            {
                ResourceHolder = ConnectionFactoryUtils.GetTransactionalResourceHolder(ConnectionFactory, Transactional);
                Channel        = ResourceHolder.GetChannel();

                // ClosingRecoveryListener.AddRecoveryListenerIfNecessary(Channel);
            }
            catch (RabbitAuthenticationException e)
            {
                throw new FatalListenerStartupException("Authentication failure", e);
            }

            DeliveryTags.Clear();
            ActiveObjectCounter.Add(this);
            PassiveDeclarations();
            SetQosAndCreateConsumers();
        }
        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();
            }
        }
 public void ClearDeliveryTags()
 {
     DeliveryTags.Clear();
 }