Example #1
0
 public NoTransactionReceiveStrategy(string connectionString, TableBasedQueue errorQueue, Func <TransportMessage, bool> tryProcessMessageCallback, ConnectionFactory sqlConnectionFactory)
 {
     this.connectionString          = connectionString;
     this.errorQueue                = errorQueue;
     this.tryProcessMessageCallback = tryProcessMessageCallback;
     this.sqlConnectionFactory      = sqlConnectionFactory;
 }
Example #2
0
        public ReceiveResult TryReceiveFrom(TableBasedQueue queue)
        {
            MessageReadResult readResult;

            using (var connection = sqlConnectionFactory.OpenNewConnection(connectionString))
            {
                readResult = queue.TryReceive(connection);
                if (readResult.IsPoison)
                {
                    errorQueue.Send(readResult.DataRecord, connection);
                    return(ReceiveResult.NoMessage());
                }
            }

            if (!readResult.Successful)
            {
                return(ReceiveResult.NoMessage());
            }

            var result = ReceiveResult.Received(readResult.Message);

            try
            {
                tryProcessMessageCallback(readResult.Message);
                return(result);
            }
            catch (Exception ex)
            {
                return(result.FailedProcessing(ex));
            }
        }
 public NativeTransactionReceiveStrategy(string connectionString, TableBasedQueue errorQueue, Func <TransportMessage, bool> tryProcessMessageCallback, PipelineExecutor pipelineExecutor, TransactionSettings transactionSettings)
 {
     this.pipelineExecutor          = pipelineExecutor;
     this.tryProcessMessageCallback = tryProcessMessageCallback;
     this.errorQueue       = errorQueue;
     this.connectionString = connectionString;
     isolationLevel        = GetSqlIsolationLevel(transactionSettings.IsolationLevel);
 }
        public ReceiveResult TryReceiveFrom(TableBasedQueue queue)
        {
            using (var connection = new SqlConnection(connectionString))
            {
                connection.Open();
                using (pipelineExecutor.SetConnection(connectionString, connection))
                {
                    using (var transaction = connection.BeginTransaction(isolationLevel))
                    {
                        using (pipelineExecutor.SetTransaction(connectionString, transaction))
                        {
                            MessageReadResult readResult;
                            try
                            {
                                readResult = queue.TryReceive(connection, transaction);
                            }
                            catch (Exception)
                            {
                                transaction.Rollback();
                                throw;
                            }

                            if (readResult.IsPoison)
                            {
                                errorQueue.Send(readResult.DataRecord, connection, transaction);
                                transaction.Commit();
                                return(ReceiveResult.NoMessage());
                            }

                            if (!readResult.Successful)
                            {
                                transaction.Commit();
                                return(ReceiveResult.NoMessage());
                            }

                            var result = ReceiveResult.Received(readResult.Message);
                            try
                            {
                                if (tryProcessMessageCallback(result.Message))
                                {
                                    transaction.Commit();
                                }
                                else
                                {
                                    transaction.Rollback();
                                }
                                return(result);
                            }
                            catch (Exception ex)
                            {
                                transaction.Rollback();
                                return(result.FailedProcessing(ex));
                            }
                        }
                    }
                }
            }
        }
 public NativeTransactionReceiveStrategy(string connectionString, TableBasedQueue errorQueue, Func <TransportMessage, bool> tryProcessMessageCallback, ConnectionFactory sqlConnectionFactory, IConnectionStore connectionStore, TransactionSettings transactionSettings)
 {
     this.tryProcessMessageCallback = tryProcessMessageCallback;
     this.errorQueue           = errorQueue;
     this.connectionString     = connectionString;
     this.sqlConnectionFactory = sqlConnectionFactory;
     this.connectionStore      = connectionStore;
     isolationLevel            = GetSqlIsolationLevel(transactionSettings.IsolationLevel);
 }
Example #6
0
 public AmbientTransactionReceiveStrategy(string connectionString, TableBasedQueue errorQueue, Func <TransportMessage, bool> tryProcessMessageCallback, PipelineExecutor pipelineExecutor, TransactionSettings transactionSettings)
 {
     this.pipelineExecutor          = pipelineExecutor;
     this.tryProcessMessageCallback = tryProcessMessageCallback;
     this.errorQueue       = errorQueue;
     this.connectionString = connectionString;
     transactionOptions    = new TransactionOptions
     {
         IsolationLevel = transactionSettings.IsolationLevel,
         Timeout        = transactionSettings.TransactionTimeout
     };
 }
Example #7
0
 public AdaptivePollingReceiver(
     IReceiveStrategy receiveStrategy,
     TableBasedQueue queue,
     Action <TransportMessage, Exception> endProcessMessage,
     RepeatedFailuresOverTimeCircuitBreaker circuitBreaker,
     TransportNotifications transportNotifications)
     : base(circuitBreaker)
 {
     this.receiveStrategy        = receiveStrategy;
     this.queue                  = queue;
     this.endProcessMessage      = endProcessMessage;
     this.transportNotifications = transportNotifications;
 }
 public AdaptivePollingReceiver(
     IReceiveStrategy receiveStrategy,
     TableBasedQueue queue,
     Action <TransportMessage, Exception> endProcessMessage,
     RepeatedFailuresOverTimeCircuitBreaker circuitBreaker,
     TransportNotifications transportNotifications)
     : base(queue.ToString(), circuitBreaker, transportNotifications, TimeSpan.FromMilliseconds(SlowTaskThresholdInMilliseconds))
 {
     this.receiveStrategy        = receiveStrategy;
     this.queue                  = queue;
     this.endProcessMessage      = endProcessMessage;
     this.transportNotifications = transportNotifications;
 }
        public AmbientTransactionReceiveStrategy(string connectionString, TableBasedQueue errorQueue, Func <TransportMessage, bool> tryProcessMessageCallback, ConnectionFactory sqlConnectionFactory, IConnectionStore connectionStore, TransactionSettings transactionSettings)
        {
            this.tryProcessMessageCallback = tryProcessMessageCallback;
            this.errorQueue           = errorQueue;
            this.connectionString     = connectionString;
            this.sqlConnectionFactory = sqlConnectionFactory;
            this.connectionStore      = connectionStore;

            transactionOptions = new TransactionOptions
            {
                IsolationLevel = transactionSettings.IsolationLevel,
                Timeout        = transactionSettings.TransactionTimeout
            };
        }
        public IReceiveStrategy Create(TransactionSettings settings, Func <TransportMessage, bool> tryProcessMessageCallback)
        {
            var errorQueue = new TableBasedQueue(errorQueueAddress, localConnectionParams.Schema);

            if (settings.IsTransactional)
            {
                if (settings.SuppressDistributedTransactions)
                {
                    return(new NativeTransactionReceiveStrategy(localConnectionParams.ConnectionString, errorQueue, tryProcessMessageCallback, sqlConnectionFactory, connectionStore, settings));
                }
                return(new AmbientTransactionReceiveStrategy(localConnectionParams.ConnectionString, errorQueue, tryProcessMessageCallback, sqlConnectionFactory, connectionStore, settings));
            }
            return(new NoTransactionReceiveStrategy(localConnectionParams.ConnectionString, errorQueue, tryProcessMessageCallback, sqlConnectionFactory));
        }
Example #11
0
        public ReceiveResult TryReceiveFrom(TableBasedQueue queue)
        {
            using (var scope = new TransactionScope(TransactionScopeOption.Required, transactionOptions))
            {
                using (var connection = new SqlConnection(connectionString))
                {
                    connection.Open();
                    using (pipelineExecutor.SetConnection(connectionString, connection))
                    {
                        var readResult = queue.TryReceive(connection);
                        if (readResult.IsPoison)
                        {
                            errorQueue.Send(readResult.DataRecord, connection);
                            scope.Complete();
                            return(ReceiveResult.NoMessage());
                        }

                        if (!readResult.Successful)
                        {
                            scope.Complete();
                            return(ReceiveResult.NoMessage());
                        }

                        var result = ReceiveResult.Received(readResult.Message);

                        try
                        {
                            if (tryProcessMessageCallback(readResult.Message))
                            {
                                scope.Complete();
                                scope.Dispose(); // We explicitly calling Dispose so that we force any exception to not bubble, eg Concurrency/Deadlock exception.
                            }
                            return(result);
                        }
                        catch (Exception ex)
                        {
                            return(result.FailedProcessing(ex));
                        }
                    }
                }
            }
        }
        /// <summary>
        ///     Initializes the <see cref="IDequeueMessages" />.
        /// </summary>
        /// <param name="primaryAddress">The address to listen on.</param>
        /// <param name="transactionSettings">
        ///     The <see cref="TransactionSettings" /> to be used by <see cref="IDequeueMessages" />.
        /// </param>
        /// <param name="tryProcessMessage">Called when a message has been dequeued and is ready for processing.</param>
        /// <param name="endProcessMessage">
        ///     Needs to be called by <see cref="IDequeueMessages" /> after the message has been processed regardless if the
        ///     outcome was successful or not.
        /// </param>
        public void Init(Address primaryAddress, TransactionSettings transactionSettings,
                         Func <TransportMessage, bool> tryProcessMessage, Action <TransportMessage, Exception> endProcessMessage)
        {
            queuePurger.Purge(primaryAddress);

            secondaryReceiveSettings = secondaryReceiveConfiguration.GetSettings(primaryAddress.Queue);
            var receiveStrategy = receiveStrategyFactory.Create(transactionSettings, tryProcessMessage);

            primaryReceiver = new AdaptivePollingReceiver(receiveStrategy, new TableBasedQueue(primaryAddress, locaConnectionParams.Schema), endProcessMessage, circuitBreaker, transportNotifications);

            if (secondaryReceiveSettings.IsEnabled)
            {
                var secondaryQueue = new TableBasedQueue(SecondaryReceiveSettings.ReceiveQueue.GetTableName(), locaConnectionParams.Schema);
                secondaryReceiver = new AdaptivePollingReceiver(receiveStrategy, secondaryQueue, endProcessMessage, circuitBreaker, transportNotifications);
            }
            else
            {
                secondaryReceiver = new NullExecutor();
            }
        }
        public void Send(TransportMessage message, SendOptions sendOptions)
        {
            Address destination = null;

            try
            {
                destination = DetermineDestination(sendOptions);

                var connectionInfo = connectionStringProvider.GetForDestination(sendOptions.Destination);
                var queue          = new TableBasedQueue(destination, connectionInfo.Schema);
                if (sendOptions.EnlistInReceiveTransaction)
                {
                    SqlTransaction currentTransaction;
                    if (connectionStore.TryGetTransaction(connectionInfo.ConnectionString, out currentTransaction))
                    {
                        queue.Send(message, sendOptions, currentTransaction.Connection, currentTransaction);
                    }
                    else
                    {
                        SqlConnection currentConnection;
                        if (connectionStore.TryGetConnection(connectionInfo.ConnectionString, out currentConnection))
                        {
                            queue.Send(message, sendOptions, currentConnection);
                        }
                        else
                        {
                            using (var connection = sqlConnectionFactory.OpenNewConnection(connectionInfo.ConnectionString))
                            {
                                queue.Send(message, sendOptions, connection);
                            }
                        }
                    }
                }
                else
                {
                    // Suppress so that even if DTC is on, we won't escalate
                    using (var tx = new TransactionScope(TransactionScopeOption.Suppress))
                    {
                        using (var connection = sqlConnectionFactory.OpenNewConnection(connectionInfo.ConnectionString))
                        {
                            queue.Send(message, sendOptions, connection);
                        }

                        tx.Complete();
                    }
                }
            }
            catch (SqlException ex)
            {
                if (ex.Number == 208)
                {
                    ThrowQueueNotFoundException(destination, ex);
                }

                ThrowFailedToSendException(destination, ex);
            }
            catch (Exception ex)
            {
                ThrowFailedToSendException(destination, ex);
            }
        }
 public ExpiredMessagesPurger(TableBasedQueue queue, Func <SqlConnection> openConnection, PurgeExpiredMessagesParams parameters)
 {
     this.queue          = queue;
     this.openConnection = openConnection;
     this.parameters     = parameters;
 }