/// <summary> /// Rollback all. /// </summary> public void RollbackAll() { foreach (var channel in this.channels) { Logger.Debug(m => m("Rollingback messages to channel: {0}", channel)); RabbitUtils.RollbackIfNecessary(channel); if (this.deliveryTags.ContainsKey(channel)) { foreach (var deliveryTag in this.deliveryTags[channel]) { try { channel.BasicReject((ulong)deliveryTag, true); } catch (Exception ex) { throw new AmqpException(ex); } } // Need to commit the reject (=nack) RabbitUtils.CommitIfNecessary(channel); } } }
/// <summary> /// Close all channels and connections. /// </summary> public void CloseAll() { foreach (var channel in this.channels) { try { if (channel != ConnectionFactoryUtils.GetConsumerChannel()) { channel.Close(); } else { Logger.Debug(m => m("Skipping close of consumer channel: {0}", channel.ToString())); } } catch (Exception ex) { Logger.Debug("Could not close synchronized Rabbit Channel after transaction", ex); } } foreach (var connection in this.connections) { RabbitUtils.CloseConnection(connection); } this.connections.Clear(); this.channels.Clear(); this.channelsPerConnection.Clear(); }
/// <summary>Obtain a RabbitMQ Channel that is synchronized with the current transaction, if any.</summary> /// <param name="connectionFactory">The connection factory.</param> /// <param name="resourceFactory">The resource factory.</param> /// <returns>The transactional Channel, or null if none found.</returns> private static RabbitResourceHolder DoGetTransactionalResourceHolder(IConnectionFactory connectionFactory, IResourceFactory resourceFactory) { AssertUtils.ArgumentNotNull(connectionFactory, "ConnectionFactory must not be null"); AssertUtils.ArgumentNotNull(resourceFactory, "ResourceFactory must not be null"); var resourceHolder = (RabbitResourceHolder)TransactionSynchronizationManager.GetResource(connectionFactory); if (resourceHolder != null) { var tempchannel = resourceFactory.GetChannel(resourceHolder); if (tempchannel != null) { return(resourceHolder); } } var resourceHolderToUse = resourceHolder; if (resourceHolderToUse == null) { resourceHolderToUse = new RabbitResourceHolder(); } var connection = resourceFactory.GetConnection(resourceHolderToUse); IModel channel = null; try { var isExistingCon = connection != null; if (!isExistingCon) { connection = resourceFactory.CreateConnection(); resourceHolderToUse.AddConnection(connection); } channel = consumerChannel.Value; if (channel == null) { channel = resourceFactory.CreateChannel(connection); } resourceHolderToUse.AddChannel(channel, connection); if (resourceHolderToUse != resourceHolder) { BindResourceToTransaction(resourceHolderToUse, connectionFactory, resourceFactory.IsSynchedLocalTransactionAllowed); } return(resourceHolderToUse); } catch (Exception ex) { RabbitUtils.CloseChannel(channel); RabbitUtils.CloseConnection(connection); throw new AmqpIOException(ex); } }
/// <summary>Release the resources.</summary> /// <param name="resourceHolder">The resource holder.</param> public static void ReleaseResources(RabbitResourceHolder resourceHolder) { if (resourceHolder == null || resourceHolder.SynchronizedWithTransaction) { return; } RabbitUtils.CloseChannel(resourceHolder.Channel); RabbitUtils.CloseConnection(resourceHolder.Connection); }
/// <summary>The dispose.</summary> public void Dispose() { this.outer.Reset(); if (this.target != null) { this.outer.ConnectionListener.OnClose(this.target); RabbitUtils.CloseConnection(this.target); } this.target = null; }
/// <summary> /// Close the channel. /// </summary> public void Close() { try { this.connectionDelegate.Close(); } catch (Exception e) { throw RabbitUtils.ConvertRabbitAccessException(e); } }
/// <summary>Create a channel, given a flag indicating whether it should be transactional or not.</summary> /// <param name="transactional">The transactional.</param> /// <returns>The channel.</returns> public IModel CreateChannel(bool transactional) { try { var channel = this.connectionDelegate.CreateModel(); if (transactional) { // Just created so we want to start the transaction channel.TxSelect(); } return(channel); } catch (Exception e) { throw RabbitUtils.ConvertRabbitAccessException(e); } }
/// <summary> /// Create a connection. /// </summary> /// <returns>The connection.</returns> public virtual IConnection CreateBareConnection() { try { if (this.addresses != null) { // TODO: Waiting on RabbitMQ.Client to catch up to the Java equivalent here. // return new SimpleConnection(this.rabbitConnectionFactory.CreateConnection(this.executorService, this.addresses)); return(new SimpleConnection(this.rabbitConnectionFactory.CreateConnection())); } else { // TODO: Waiting on RabbitMQ.Client to catch up to the Java equivalent here. // return new SimpleConnection(this.rabbitConnectionFactory.CreateConnection(this.executorService)); return(new SimpleConnection(this.rabbitConnectionFactory.CreateConnection())); } } catch (Exception ex) { throw RabbitUtils.ConvertRabbitAccessException(ex); } }
/// <summary>Implement this method to perform extra treatments before and after /// the call to the supplied <paramref name="invocation"/>.</summary> /// <param name="invocation">The method invocation that is being intercepted.</param> /// <returns>The result of the call to the<see cref="M:AopAlliance.Intercept.IJoinpoint.Proceed"/> method of /// the supplied <paramref name="invocation"/>; this return value may /// well have been intercepted by the interceptor.</returns> /// <exception cref="T:System.Exception">If any of the interceptors in the chain or the target object itself /// throws an exception.</exception> public object Invoke(IMethodInvocation invocation) { Logger.Trace(m => m("Method Intercepted: {0}", invocation.Method.Name)); var methodName = invocation.Method.Name; if (methodName == "TxSelect" && !this.transactional) { throw new InvalidOperationException("Cannot start transaction on non-transactional channel"); } if (methodName == "Equals") { // Only consider equal when proxies are identical. return(invocation.Proxy == invocation.Arguments[0]); } else if (methodName == "GetHashCode") { // Use hashCode of Channel proxy. return(invocation.Proxy.GetHashCode()); } else if (methodName == "ToString") { return("Cached Rabbit Channel: " + this.target); } else if (methodName == "GetTargetChannel") { return(this.target); } else if (methodName == "GetConnection") { return(((ModelBase)this.target).m_session.Connection); } else if (methodName == "Close") { // Handle close method: don't pass the call on. if (this.outer.Active) { lock (this.channelList) { if (!RabbitUtils.IsPhysicalCloseRequired() && this.channelList.Count < this.outer.ChannelCacheSize) { this.LogicalClose((IChannelProxy)invocation.Proxy); // Remain open in the channel list. return(null); } } } // If we get here, we're supposed to shut down. this.PhysicalClose(); return(null); } else if (methodName == "GetTargetChannel") { // Handle getTargetChannel method: return underlying Channel. return(this.target); } else if (methodName == "get_IsOpen") { // Handle isOpen method: we are closed if the target is closed return(this.target != null && this.target.IsOpen); } try { if (this.target == null || !this.target.IsOpen) { this.target = null; } lock (this.targetMonitor) { if (this.target == null) { this.target = this.outer.CreateBareChannel(this.transactional); } return(invocation.Method.Invoke(this.target, invocation.Arguments)); } } catch (TargetInvocationException ex) { if (this.target == null || !this.target.IsOpen) { // Basic re-connection logic... Logger.Debug(m => m("Detected closed channel on exception. Re-initializing: {0}", this.target)); this.target = null; lock (this.targetMonitor) { if (this.target == null) { this.target = this.outer.CreateBareChannel(this.transactional); } } } throw ex.GetBaseException(); } }