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); } }
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 TestReceiveBlockingGlobalTx() { template.ConvertAndSend(ROUTE, "blockGTXNoTO"); var resourceHolder = ConnectionFactoryUtils .GetTransactionalResourceHolder(template.ConnectionFactory, true); TransactionSynchronizationManager.SetActualTransactionActive(true); ConnectionFactoryUtils.BindResourceToTransaction(resourceHolder, template.ConnectionFactory, true); template.ReceiveTimeout = -1; template.IsChannelTransacted = true; var o = template.ReceiveAndConvert <string>(ROUTE); resourceHolder.CommitAll(); resourceHolder.CloseAll(); Assert.Same(resourceHolder, TransactionSynchronizationManager.UnbindResource(template.ConnectionFactory)); Assert.NotNull(o); Assert.Equal("blockGTXNoTO", o); template.ReceiveTimeout = 0; Assert.Null(template.Receive(ROUTE)); }
/// <summary>Do begin.</summary> /// <param name="transaction">The transaction.</param> /// <param name="definition">The definition.</param> protected override void DoBegin(object transaction, ITransactionDefinition definition) { // https://jira.springsource.org/browse/SPRNET-1444 (SPRNET 2.0) has default TransactionIsolationLevel as IsolationLevel.Unspecified, letting this work. Will not work for SPRNET <= 1.3.2. if (definition.TransactionIsolationLevel != IsolationLevel.Unspecified) { throw new InvalidIsolationLevelException("AMQP does not support an isolation level concept"); } var transactionObject = (RabbitTransactionObject)transaction; RabbitResourceHolder resourceHolder = null; try { resourceHolder = ConnectionFactoryUtils.GetTransactionalResourceHolder(this.ConnectionFactory, true); Logger.Debug(m => m("Created AMQP transaction on channel [{0}]", resourceHolder.Channel)); // resourceHolder.DeclareTransactional(); transactionObject.ResourceHolder = resourceHolder; transactionObject.ResourceHolder.SynchronizedWithTransaction = true; var timeout = this.DetermineTimeout(definition); if (timeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT) { transactionObject.ResourceHolder.TimeoutInSeconds = timeout; } TransactionSynchronizationManager.BindResource(this.ConnectionFactory, transactionObject.ResourceHolder); } catch (AmqpException ex) { if (resourceHolder != null) { ConnectionFactoryUtils.ReleaseResources(resourceHolder); } throw new CannotCreateTransactionException("Could not create AMQP transaction", ex); } }
/// <summary>The start.</summary> public void Start() { Logger.Debug(m => m("Starting consumer {0}", this)); this.channel = ConnectionFactoryUtils.GetTransactionalResourceHolder(this.connectionFactory, this.transactional).Channel; this.consumer = new InternalConsumer(this.channel, this); this.deliveryTags.Clear(); this.activeObjectCounter.Add(this); var passiveDeclareTries = 3; // mirrored queue might be being moved while (passiveDeclareTries > 0) { passiveDeclareTries--; try { if (!this.acknowledgeMode.IsAutoAck()) { // Set basicQos before calling basicConsume (otherwise if we are not acking the broker // will send blocks of 100 messages) // The Java client includes a convenience method BasicQos(ushort prefetchCount), which sets 0 as the prefetchSize and false as global this.channel.BasicQos(0, (ushort)this.prefetchCount, false); } foreach (var t in this.queues) { this.channel.QueueDeclarePassive(t); } passiveDeclareTries = 0; } catch (Exception e) { if (passiveDeclareTries > 0 && this.channel.IsOpen) { Logger.Warn(m => m("Reconnect failed; retries left=" + (passiveDeclareTries - 1)), e); try { Thread.Sleep(5000); } catch (ThreadInterruptedException e1) { Thread.CurrentThread.Interrupt(); } } else { this.activeObjectCounter.Release(this); throw new FatalListenerStartupException("Cannot prepare queue for listener. Either the queue doesn't exist or the broker will not allow us to use it.", e); } } } try { foreach (var t in this.queues) { this.channel.BasicConsume(t, this.acknowledgeMode.IsAutoAck(), this.consumer); Logger.Debug(m => m("Started on queue '{0}': {1}", t, this)); } } catch (Exception e) { throw RabbitUtils.ConvertRabbitAccessException(e); } }
/// <summary> /// Get a transactional resource holder. /// </summary> /// <returns> /// The rabbit resource holder. /// </returns> protected RabbitResourceHolder GetTransactionalResourceHolder() { return(ConnectionFactoryUtils.GetTransactionalResourceHolder(this.connectionFactory, this.ChannelTransacted)); }