protected override void DoBegin(object transaction, ITransactionDefinition definition) { if (definition.IsolationLevel != AbstractTransactionDefinition.ISOLATION_DEFAULT) { throw new InvalidIsolationLevelException("AMQP does not support an isolation level concept"); } var txObject = (RabbitTransactionObject)transaction; RabbitResourceHolder resourceHolder = null; try { resourceHolder = ConnectionFactoryUtils.GetTransactionalResourceHolder(ConnectionFactory, true); _logger?.LogDebug("Created AMQP transaction on channel [" + resourceHolder.GetChannel() + "]"); txObject.ResourceHolder = resourceHolder; txObject.ResourceHolder.SynchronizedWithTransaction = true; var timeout = DetermineTimeout(definition); if (timeout != AbstractTransactionDefinition.TIMEOUT_DEFAULT) { txObject.ResourceHolder.SetTimeoutInSeconds(timeout); } TransactionSynchronizationManager.BindResource(ConnectionFactory, txObject.ResourceHolder); } catch (AmqpException ex) { if (resourceHolder != null) { ConnectionFactoryUtils.ReleaseResources(resourceHolder); } throw new CannotCreateTransactionException("Could not create AMQP transaction", ex); } }
protected virtual void DoInvokeListener(IChannelAwareMessageListener listener, R.IModel channel, object data) { Message message = null; RabbitResourceHolder resourceHolder = null; var channelToUse = channel; var boundHere = false; try { if (!ExposeListenerChannel) { // We need to expose a separate Channel. resourceHolder = GetTransactionalResourceHolder(); channelToUse = resourceHolder.GetChannel(); /* * If there is a real transaction, the resource will have been bound; otherwise * we need to bind it temporarily here. Any work done on this channel * will be committed in the finally block. */ if (IsChannelLocallyTransacted && !TransactionSynchronizationManager.IsActualTransactionActive()) { resourceHolder.SynchronizedWithTransaction = true; TransactionSynchronizationManager.BindResource(ConnectionFactory, resourceHolder); boundHere = true; } } else { // if locally transacted, bind the current channel to make it available to RabbitTemplate if (IsChannelLocallyTransacted) { var localResourceHolder = new RabbitResourceHolder(channelToUse, false); localResourceHolder.SynchronizedWithTransaction = true; TransactionSynchronizationManager.BindResource(ConnectionFactory, localResourceHolder); boundHere = true; } } // Actually invoke the message listener... try { if (data is List <Message> asList) { listener.OnMessageBatch(asList, channelToUse); } else { message = (Message)data; listener.OnMessage(message, channelToUse); } } catch (Exception e) { _logger?.LogError("Exception in OnMessage call", e); throw WrapToListenerExecutionFailedExceptionIfNeeded(e, data); } } finally { CleanUpAfterInvoke(resourceHolder, channelToUse, boundHere); } }