public static void CloseMessageConsumer(IModel channel, List <string> consumerTags, bool transactional, ILogger logger = null) { if (!channel.IsOpen) { return; } try { foreach (var consumerTag in consumerTags) { Cancel(channel, consumerTag); } if (transactional) { // Re-queue in-flight messages if any (after the consumer is cancelled to prevent the broker from simply // sending them back to us). Does not require a tx.commit. channel.BasicRecover(true); } // If not transactional then we are auto-acking (at least as of 1.0.0.M2) so there is nothing to recover. // Messages are going to be lost in general. } catch (Exception ex) { logger?.LogError(ex, "Exception during CloseMessageConsumer"); throw RabbitExceptionTranslator.ConvertRabbitAccessException(ex); } }
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 void RollbackAll() { foreach (var channel in _channels) { _logger?.LogDebug("Rolling back messages to channel: {channel}", channel); RabbitUtils.RollbackIfNecessary(channel); if (_deliveryTags.TryGetValue(channel, out var tags)) { foreach (var deliveryTag in tags) { try { channel.BasicReject(deliveryTag, RequeueOnRollback); } catch (Exception ex) { _logger?.LogError(ex, "Error Rolling back messages to {channel} ", channel); throw RabbitExceptionTranslator.ConvertRabbitAccessException(ex); } } // Need to commit the reject (=nack) RabbitUtils.CommitIfNecessary(channel); } } }
protected virtual IConnection CreateBareConnection() { try { var connectionName = ObtainNewConnectionName(); var rabbitConnection = Connect(connectionName); var connection = new SimpleConnection(rabbitConnection, CloseTimeout, _logger); _logger?.LogInformation("Created new connection: " + connectionName + "/" + connection); if (rabbitConnection != null && RecoveryListener != null) { rabbitConnection.RecoverySucceeded += RecoveryListener.HandleRecoverySucceeded; rabbitConnection.ConnectionRecoveryError += RecoveryListener.HandleConnectionRecoveryError; } if (rabbitConnection != null && BlockedListener != null) { rabbitConnection.ConnectionBlocked += BlockedListener.HandleBlocked; rabbitConnection.ConnectionUnblocked += BlockedListener.HandleUnblocked; } return(connection); } catch (Exception e) when(e is IOException || e is TimeoutException) { throw RabbitExceptionTranslator.ConvertRabbitAccessException(e); } }
protected void SendResponse(RC.IModel channel, Address replyTo, IMessage <byte[]> messageIn) { var message = messageIn; if (BeforeSendReplyPostProcessors != null) { var processors = BeforeSendReplyPostProcessors; IMessage postProcessed = message; foreach (var postProcessor in processors) { postProcessed = postProcessor.PostProcessMessage(postProcessed); } message = postProcessed as IMessage <byte[]>; if (message == null) { throw new InvalidOperationException("A BeforeSendReplyPostProcessors failed to return IMessage<byte[]>"); } } PostProcessChannel(channel, message); try { _logger?.LogDebug("Publishing response to exchange = [{exchange}], routingKey = [{routingKey}]", replyTo.ExchangeName, replyTo.RoutingKey); if (RetryTemplate == null) { DoPublish(channel, replyTo, message); } else { var messageToSend = message; RetryTemplate.Execute <object>( ctx => { DoPublish(channel, replyTo, messageToSend); return(null); }, ctx => { if (RecoveryCallback != null) { ctx.SetAttribute(SendRetryContextAccessor.MESSAGE, messageToSend); ctx.SetAttribute(SendRetryContextAccessor.ADDRESS, replyTo); RecoveryCallback.Recover(ctx); return(null); } else { throw RabbitExceptionTranslator.ConvertRabbitAccessException(ctx.LastException); } }); } } catch (Exception ex) { throw RabbitExceptionTranslator.ConvertRabbitAccessException(ex); } }
public override void OnMessageBatch(List <IMessage> messages, IModel channel) { IMessage converted = null; if (IsMessageByteArrayList) { var list = new List <IMessage <byte[]> >(); foreach (var m in messages) { list.Add((IMessage <byte[]>)m); } converted = Message.Create(list); } else { if (IsMessageList) { var messagingMessages = CreateMessageList(InferredArgumentType); foreach (var message in messages) { messagingMessages.Add(ToMessagingMessage(message)); } converted = Message.Create(messagingMessages); } else { var payloads = CreateList(InferredArgumentType); foreach (var message in messages) { PreprocesMessage(message); var convertedObject = MessageConverter.FromMessage(message, InferredArgumentType); if (convertedObject == null) { throw new MessageConversionException("Message converter returned null"); } payloads.Add(convertedObject); } converted = Message.Create(payloads); } } try { InvokeHandlerAndProcessResult(null, channel, converted); } catch (Exception e) { throw RabbitExceptionTranslator.ConvertRabbitAccessException(e); } }
protected override object DoReceive() { var connection = ConnectionFactory.CreateConnection(); var channel = connection.CreateChannel(Transacted); try { var resp = channel.BasicGet(QueueName, false); if (resp == null) { RabbitUtils.CloseChannel(channel); RabbitUtils.CloseConnection(connection); return(null); } var callback = AckCallbackFactory.CreateCallback(new RabbitAckInfo(connection, channel, Transacted, resp)); var envelope = new Envelope(resp.DeliveryTag, resp.Redelivered, resp.Exchange, resp.RoutingKey); var messageProperties = MessageHeaderConverter.ToMessageHeaders(resp.BasicProperties, envelope, EncodingUtils.Utf8); var accessor = RabbitHeaderAccessor.GetMutableAccessor(messageProperties); accessor.ConsumerQueue = this.QueueName; // Map<String, Object> headers = this.headerMapper.toHeadersFromRequest(messageProperties); var message = Message.Create <byte[]>(resp.Body, accessor.MessageHeaders); object payload; if (BatchingStrategy.CanDebatch(message.Headers)) { var payloads = new List <object>(); BatchingStrategy.DeBatch(message, fragment => payloads.Add(MessageConverter.FromMessage(fragment, null))); payload = payloads; } else { payload = MessageConverter.FromMessage(message, null); } var builder = MessageBuilderFactory.WithPayload(payload) .CopyHeaders(accessor.MessageHeaders) .SetHeader(IntegrationMessageHeaderAccessor.ACKNOWLEDGMENT_CALLBACK, callback); if (RawMessageHeader) { builder.SetHeader(RabbitMessageHeaderErrorMessageStrategy.AMQP_RAW_MESSAGE, message); builder.SetHeader(IntegrationMessageHeaderAccessor.SOURCE_DATA, message); } return(builder); } catch (Exception e) { RabbitUtils.CloseChannel(channel); RabbitUtils.CloseConnection(connection); throw RabbitExceptionTranslator.ConvertRabbitAccessException(e); } }
public static void DeclareTransactional(IModel channel, ILogger logger = null) { try { channel.TxSelect(); } catch (IOException e) { logger?.LogDebug(e, "Error performing 'txSelect' on {channel}", channel); throw RabbitExceptionTranslator.ConvertRabbitAccessException(e); } }
protected void SendResponse(IModel channel, Address replyTo, Message messageIn) { var message = messageIn; if (BeforeSendReplyPostProcessors != null) { var processors = BeforeSendReplyPostProcessors; foreach (var postProcessor in processors) { message = postProcessor.PostProcessMessage(message); } } PostProcessChannel(channel, message); try { _logger?.LogDebug("Publishing response to exchange = [" + replyTo.ExchangeName + "], routingKey = [" + replyTo.RoutingKey + "]"); if (RetryTemplate == null) { DoPublish(channel, replyTo, message); } else { var messageToSend = message; RetryTemplate.Execute <object>( ctx => { DoPublish(channel, replyTo, messageToSend); return(null); }, ctx => { if (RecoveryCallback != null) { ctx.SetAttribute(SendRetryContextAccessor.MESSAGE, messageToSend); ctx.SetAttribute(SendRetryContextAccessor.ADDRESS, replyTo); RecoveryCallback.Recover(ctx); return(null); } else { throw RabbitExceptionTranslator.ConvertRabbitAccessException(ctx.LastException); } }); } } catch (Exception ex) { throw RabbitExceptionTranslator.ConvertRabbitAccessException(ex); } }
public static void RollbackIfNecessary(IModel channel, ILogger logger = null) { if (channel == null) { throw new ArgumentNullException(nameof(channel)); } try { channel.TxRollback(); } catch (Exception ex) { logger.LogError(ex, "Error during TxCommit"); throw RabbitExceptionTranslator.ConvertRabbitAccessException(ex); } }
public void Close() { try { // _explicitlyClosed = true; // let the physical close time out if necessary _connection.Close(_closeTimeout); } catch (AlreadyClosedException) { // Ignore } catch (Exception e) { throw RabbitExceptionTranslator.ConvertRabbitAccessException(e); } }
public override void OnMessageBatch(List <Message> messages, IModel channel) { IMessage converted; if (ConverterAdapter.IsAmqpMessageList) { converted = new GenericMessage(messages); } else { var messagingMessages = new List <IMessage>(); foreach (var message in messages) { messagingMessages.Add(ToMessagingMessage(message)); } if (ConverterAdapter.IsMessageList) { converted = new GenericMessage(messagingMessages); } else { var payloads = new List <object>(); foreach (var message in messagingMessages) { payloads.Add(message.Payload); } converted = new GenericMessage(payloads); } } try { InvokeHandlerAndProcessResult(null, channel, converted); } catch (Exception e) { throw RabbitExceptionTranslator.ConvertRabbitAccessException(e); } }
public void Acknowledge(Status status) { // logger.trace("acknowledge(" + status + ") for " + this); try { var deliveryTag = AckInfo.Response.DeliveryTag; switch (status) { case Status.ACCEPT: AckInfo.Channel.BasicAck(deliveryTag, false); break; case Status.REJECT: AckInfo.Channel.BasicReject(deliveryTag, false); break; case Status.REQUEUE: AckInfo.Channel.BasicReject(deliveryTag, true); break; default: break; } if (AckInfo.Transacted) { AckInfo.Channel.TxCommit(); } } catch (Exception e) { throw RabbitExceptionTranslator.ConvertRabbitAccessException(e); } finally { RabbitUtils.CloseChannel(AckInfo.Channel); RabbitUtils.CloseConnection(AckInfo.Connection); IsAcknowledged = true; } }
public RC.IModel CreateChannel(bool transactional = false) { try { var result = _connection.CreateModel(); if (result == null) { throw new RabbitResourceNotAvailableException("The channelMax limit is reached. Try later."); } if (transactional) { result.TxSelect(); } return(result); } catch (Exception e) { throw RabbitExceptionTranslator.ConvertRabbitAccessException(e); } }
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(); } }
protected virtual IConnection CreateBareConnection() { try { var connectionName = ObtainNewConnectionName(); var rabbitConnection = Connect(connectionName); var connection = new SimpleConnection(rabbitConnection, CloseTimeout, _loggerFactory?.CreateLogger <SimpleConnection>()); _logger?.LogInformation("Created new connection: {connectionName}/{connection}", connectionName, connection); if (rabbitConnection != null && RecoveryListener != null) { rabbitConnection.RecoverySucceeded += RecoveryListener.HandleRecoverySucceeded; rabbitConnection.ConnectionRecoveryError += RecoveryListener.HandleConnectionRecoveryError; } if (rabbitConnection != null && BlockedListener != null) { rabbitConnection.ConnectionBlocked += BlockedListener.HandleBlocked; rabbitConnection.ConnectionUnblocked += BlockedListener.HandleUnblocked; } if (rabbitConnection != null) { rabbitConnection.ConnectionShutdown += ConnectionShutdownCompleted; } return(connection); } catch (Exception e) { throw RabbitExceptionTranslator.ConvertRabbitAccessException(e); } }
private void HandleDeclarationException(int passiveDeclareRetries, DeclarationException e) { if (passiveDeclareRetries > 0 && Channel.IsOpen) { Logger?.LogWarning(e, "Queue declaration failed; retries left={retries}", passiveDeclareRetries); try { Thread.Sleep(FailedDeclarationRetryInterval); } catch (Exception e1) { Declaring = false; ActiveObjectCounter.Release(this); throw RabbitExceptionTranslator.ConvertRabbitAccessException(e1); } } else if (e.FailedQueues.Count < Queues.Count) { Logger?.LogWarning("Not all queues are available; only listening on those that are - configured: {queues}; not available: {notavail}", string.Join(',', Queues), string.Join(',', e.FailedQueues)); lock (MissingQueues) { foreach (var q in e.FailedQueues) { MissingQueues.Add(q); } } LastRetryDeclaration = DateTimeOffset.Now.ToUnixTimeMilliseconds(); } else { Declaring = false; ActiveObjectCounter.Release(this); throw new QueuesNotAvailableException("Cannot prepare queue for listener. Either the queue doesn't exist or the broker will not allow us to use it.", e); } }
protected virtual Exception ConvertRabbitAccessException(Exception ex) { return(RabbitExceptionTranslator.ConvertRabbitAccessException(ex)); }
private static RabbitResourceHolder DoGetTransactionalResourceHolder(IConnectionFactory connectionFactory, IResourceFactory resourceFactory) { if (connectionFactory == null) { throw new ArgumentNullException(nameof(connectionFactory)); } if (resourceFactory == null) { throw new ArgumentNullException(nameof(resourceFactory)); } var resourceHolder = (RabbitResourceHolder)TransactionSynchronizationManager.GetResource(connectionFactory); if (resourceHolder != null) { var model = resourceFactory.GetChannel(resourceHolder); if (model != null) { return(resourceHolder); } } var resourceHolderToUse = resourceHolder; if (resourceHolderToUse == null) { resourceHolderToUse = new RabbitResourceHolder(); } var connection = resourceFactory.GetConnection(resourceHolderToUse); IModel channel; try { /* * If we are in a listener container, first see if there's a channel registered * for this consumer and the consumer is using the same connection factory. */ channel = ConsumerChannelRegistry.GetConsumerChannel(connectionFactory); if (channel == null && connection == null) { connection = resourceFactory.CreateConnection2(); if (resourceHolder == null) { /* * While creating a connection, a connection listener might have created a * transactional channel and bound it to the transaction. */ resourceHolder = (RabbitResourceHolder)TransactionSynchronizationManager.GetResource(connectionFactory); if (resourceHolder != null) { channel = resourceHolder.GetChannel(); resourceHolderToUse = resourceHolder; } } resourceHolderToUse.AddConnection(connection); } if (channel == null) { channel = resourceFactory.CreateChannel(connection); } resourceHolderToUse.AddChannel(channel, connection); if (!resourceHolderToUse.Equals(resourceHolder)) { BindResourceToTransaction(resourceHolderToUse, connectionFactory, resourceFactory.IsSynchedLocalTransactionAllowed); } return(resourceHolderToUse); } catch (Exception ex) { RabbitUtils.CloseConnection(connection); throw RabbitExceptionTranslator.ConvertRabbitAccessException(ex); } }
private void CheckMissingQueues() { var now = DateTimeOffset.Now.ToUnixTimeMilliseconds(); if (now - RetryDeclarationInterval > LastRetryDeclaration) { lock (MissingQueues) { List <string> toRemove = new List <string>(); Exception error = null; foreach (var queueToCheck in MissingQueues) { bool available = true; IConnection connection = null; RC.IModel channelForCheck = null; try { channelForCheck = ConnectionFactory.CreateConnection().CreateChannel(false); channelForCheck.QueueDeclarePassive(queueToCheck); Logger?.LogInformation("Queue '{queue}' is now available", queueToCheck); } catch (Exception e) { available = false; Logger?.LogWarning(e, "Queue '{queue}' is not available", queueToCheck); } finally { RabbitUtils.CloseChannel(channelForCheck); RabbitUtils.CloseConnection(connection); } if (available) { try { ConsumeFromQueue(queueToCheck); toRemove.Add(queueToCheck); } catch (Exception e) { error = e; break; } } } if (toRemove.Count > 0) { foreach (var remove in toRemove) { MissingQueues.Remove(remove); } } if (error != null) { throw RabbitExceptionTranslator.ConvertRabbitAccessException(error); } } LastRetryDeclaration = now; } }