private async Task CloseReceiver(CancellationToken cancellationToken)
        {
            if (_receiver == null || _receiver.IsDisposed)
            {
                return;
            }
            try
            {
                if (_sessionCloseHandler != null)
                {
                    var args = new ProcessSessionEventArgs(_receiver, cancellationToken);
                    await _sessionCloseHandler(args).ConfigureAwait(false);
                }
            }
            catch (Exception exception)
            {
                await RaiseExceptionReceived(
                    new ProcessErrorEventArgs(
                        exception,
                        ServiceBusErrorSource.CloseMessageSession,
                        _fullyQualifiedNamespace,
                        _entityPath))
                .ConfigureAwait(false);
            }
            finally
            {
                // cancel the automatic session lock renewal
                await CancelTask(_sessionLockRenewalCancellationSource, _sessionLockRenewalTask).ConfigureAwait(false);

                // Always at least attempt to dispose. If this fails, it won't be retried.
                await _receiver.DisposeAsync().ConfigureAwait(false);

                _receiver = null;
            }
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="ProcessSessionMessageEventArgs"/> class.
 /// </summary>
 ///
 /// <param name="message">The current <see cref="ServiceBusReceivedMessage"/>.</param>
 /// <param name="receiver">The <see cref="ServiceBusSessionReceiver"/> that will be used for all settlement methods
 /// for the args.</param>
 /// <param name="cancellationToken">The processor's <see cref="System.Threading.CancellationToken"/> instance which will be cancelled in the event that <see cref="ServiceBusProcessor.StopProcessingAsync"/> is called.</param>
 public ProcessSessionMessageEventArgs(
     ServiceBusReceivedMessage message,
     ServiceBusSessionReceiver receiver,
     CancellationToken cancellationToken) : this(message, manager : null, cancellationToken)
 {
     _sessionReceiver = receiver;
 }
        private async Task CreateReceiver(CancellationToken processorCancellationToken)
        {
            bool releaseSemaphore = false;

            try
            {
                await _concurrentAcceptSessionsSemaphore.WaitAsync(processorCancellationToken).ConfigureAwait(false);

                // only attempt to release semaphore if WaitAsync is successful,
                // otherwise SemaphoreFullException can occur.
                releaseSemaphore = true;
                _receiver        = await ServiceBusSessionReceiver.CreateSessionReceiverAsync(
                    entityPath : _entityPath,
                    connection : _connection,
                    plugins : _plugins,
                    options : _sessionReceiverOptions,
                    cancellationToken : processorCancellationToken).ConfigureAwait(false);
            }
            catch (OperationCanceledException)
            {
                // propagate as TCE so it will be handled by the outer catch block
                throw new TaskCanceledException();
            }
            finally
            {
                if (releaseSemaphore)
                {
                    _concurrentAcceptSessionsSemaphore.Release();
                }
            }
        }
        /// <summary>
        /// Creates a session receiver which can be used to interact with all messages with the same sessionId.
        /// </summary>
        ///
        /// <param name="entityPath">The name of the specific queue to associate the receiver with.</param>
        /// <param name="connection">The <see cref="ServiceBusConnection" /> connection to use for communication with the Service Bus service.</param>
        /// <param name="plugins">The set of plugins to apply to incoming messages.</param>
        /// <param name="options">A set of options to apply when configuring the receiver.</param>
        /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param>
        ///
        ///<returns>Returns a new instance of the <see cref="ServiceBusSessionReceiver"/> class.</returns>
        internal static async Task <ServiceBusSessionReceiver> CreateSessionReceiverAsync(
            string entityPath,
            ServiceBusConnection connection,
            IList <ServiceBusPlugin> plugins,
            ServiceBusSessionReceiverOptions options = default,
            CancellationToken cancellationToken      = default)
        {
            var receiver = new ServiceBusSessionReceiver(
                connection: connection,
                entityPath: entityPath,
                plugins: plugins,
                options: options);

            try
            {
                await receiver.OpenLinkAsync(cancellationToken).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                receiver.Logger.ClientCreateException(typeof(ServiceBusSessionReceiver), receiver.FullyQualifiedNamespace, entityPath, ex);
                throw;
            }
            receiver.Logger.ClientCreateComplete(typeof(ServiceBusSessionReceiver), receiver.Identifier);
            return(receiver);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="ProcessSessionEventArgs"/> class.
 /// </summary>
 ///
 /// <param name="receiver">The <see cref="ServiceBusSessionReceiver"/> that will be used for all settlement methods
 /// for the args.</param>
 /// <param name="cancellationToken">The processor's <see cref="System.Threading.CancellationToken"/> instance which will be cancelled in the event that <see cref="ServiceBusProcessor.StopProcessingAsync"/> is called.
 /// </param>
 public ProcessSessionEventArgs(
     ServiceBusSessionReceiver receiver,
     CancellationToken cancellationToken)
 {
     _sessionReceiver  = receiver;
     CancellationToken = cancellationToken;
 }
Example #6
0
 internal ProcessSessionMessageEventArgs(
     ServiceBusReceivedMessage message,
     ServiceBusSessionReceiver receiver,
     SessionReceiverManager receiverManager,
     CancellationToken cancellationToken) : this(message, receiver, cancellationToken)
 {
     _receiverManager = receiverManager;
 }
Example #7
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ProcessSessionMessageEventArgs"/> class.
 /// </summary>
 ///
 /// <param name="message">The current <see cref="ServiceBusReceivedMessage"/>.</param>
 /// <param name="receiver">The <see cref="ServiceBusSessionReceiver"/> that will be used for all settlement methods
 /// for the args.</param>
 /// <param name="cancellationToken">The processor's <see cref="System.Threading.CancellationToken"/> instance which will be cancelled in the event that <see cref="ServiceBusProcessor.StopProcessingAsync"/> is called.</param>
 internal ProcessSessionMessageEventArgs(
     ServiceBusReceivedMessage message,
     ServiceBusSessionReceiver receiver,
     CancellationToken cancellationToken)
 {
     Message           = message;
     _sessionReceiver  = receiver;
     CancellationToken = cancellationToken;
 }
Example #8
0
        private async Task CloseReceiver(CancellationToken cancellationToken)
        {
            if (_receiver == null)
            {
                return;
            }

            try
            {
                if (Processor._sessionClosingAsync != null)
                {
                    var args = new ProcessSessionEventArgs(_receiver, cancellationToken);
                    await Processor.OnSessionClosingAsync(args).ConfigureAwait(false);
                }
            }
            catch (Exception exception)
            {
                await RaiseExceptionReceived(
                    new ProcessErrorEventArgs(
                        exception,
                        ServiceBusErrorSource.CloseSession,
                        Processor.FullyQualifiedNamespace,
                        Processor.EntityPath,
                        cancellationToken))
                .ConfigureAwait(false);
            }
            finally
            {
                // cancel the automatic session lock renewal
                try
                {
                    if (_sessionLockRenewalCancellationSource != null)
                    {
                        _sessionLockRenewalCancellationSource.Cancel();
                        _sessionLockRenewalCancellationSource.Dispose();
                        await _sessionLockRenewalTask.ConfigureAwait(false);
                    }
                }
                catch (Exception ex) when(ex is TaskCanceledException)
                {
                    // Nothing to do here.  These exceptions are expected.
                }

                try
                {
                    // Always at least attempt to dispose. If this fails, it won't be retried.
                    await _receiver.DisposeAsync().ConfigureAwait(false);
                }
                finally
                {
                    // If we call DisposeAsync, we need to reset to null even if DisposeAsync throws, otherwise we can
                    // end up in a bad state.
                    _receiver       = null;
                    _receiveTimeout = false;
                }
            }
        }
        internal ProcessSessionMessageEventArgs(
            ServiceBusReceivedMessage message,
            SessionReceiverManager manager,
            CancellationToken cancellationToken)
        {
            Message  = message;
            _manager = manager;

            // manager would be null in scenarios where customers are using the public constructor for testing purposes.
            _sessionReceiver  = (ServiceBusSessionReceiver)_manager?.Receiver;
            _receiveActions   = new ProcessorReceiveActions(message, manager, false);
            CancellationToken = cancellationToken;
        }
        /// <summary>
        /// Creates a <see cref="ServiceBusSessionReceiver"/> instance that can be used for receiving
        /// and settling messages from a specific session-enabled queue. It uses <see cref="ReceiveMode"/> to specify
        /// how messages are received. Defaults to PeekLock mode. The <see cref="ReceiveMode"/> is set in <see cref="ServiceBusReceiverOptions"/>.
        /// </summary>
        ///
        /// <param name="queueName">The session-enabled queue to create a <see cref="ServiceBusSessionReceiver"/> for.</param>
        /// <param name="options">The set of <see cref="ServiceBusReceiverOptions"/> to use for configuring the
        /// <see cref="ServiceBusSessionReceiver"/>.</param>
        /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param>
        ///
        /// <remarks>Because this is establishing a session lock, this method performs a service call. If the
        /// sessionId parameter is not specified, and there are no available messages in the queue, this will
        /// throw a <see cref="ServiceBusException"/> with <see cref="ServiceBusException.Reason"/> of <see cref="ServiceBusException.FailureReason.ServiceTimeout"/>.
        /// </remarks>
        ///
        /// <returns>A <see cref="ServiceBusSessionReceiver"/> scoped to the specified queue and a specific session.</returns>
        public virtual async Task <ServiceBusSessionReceiver> CreateSessionReceiverAsync(
            string queueName,
            ServiceBusSessionReceiverOptions options = default,
            CancellationToken cancellationToken      = default)
        {
            ValidateEntityName(queueName);

            return(await ServiceBusSessionReceiver.CreateSessionReceiverAsync(
                       entityPath : queueName,
                       connection : Connection,
                       options : options,
                       cancellationToken : cancellationToken).ConfigureAwait(false));
        }
        /// <summary>
        /// Creates a <see cref="ServiceBusSessionReceiver"/> instance that can be used for receiving
        /// and settling messages from a specific session-enabled subscription. It uses <see cref="ReceiveMode"/> to specify
        /// how messages are received. Defaults to PeekLock mode. The <see cref="ReceiveMode"/> is set in <see cref="ServiceBusReceiverOptions"/>.
        /// </summary>
        ///
        /// <param name="topicName">The topic to create a <see cref="ServiceBusSessionReceiver"/> for.</param>
        /// <param name="subscriptionName">The session-enabled subscription to create a <see cref="ServiceBusSessionReceiver"/> for.</param>
        /// <param name="options">The set of <see cref="ServiceBusReceiverOptions"/> to use for configuring the
        /// <see cref="ServiceBusSessionReceiver"/>.</param>
        /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param>
        ///
        /// <remarks>Because this is establishing a session lock, this method performs a service call. If the
        /// sessionId parameter is not specified, and there are no available messages in the queue, this will
        /// throw a <see cref="ServiceBusException"/> with <see cref="ServiceBusException.Reason"/> of <see cref="ServiceBusException.FailureReason.ServiceTimeout"/>.
        /// </remarks>
        ///
        /// <returns>A <see cref="ServiceBusSessionReceiver"/> scoped to the specified queue and a specific session.</returns>
        public virtual async Task <ServiceBusSessionReceiver> CreateSessionReceiverAsync(
            string topicName,
            string subscriptionName,
            ServiceBusSessionReceiverOptions options = default,
            CancellationToken cancellationToken      = default)
        {
            ValidateEntityName(topicName);

            return(await ServiceBusSessionReceiver.CreateSessionReceiverAsync(
                       entityPath : EntityNameFormatter.FormatSubscriptionPath(topicName, subscriptionName),
                       connection : Connection,
                       options : options,
                       cancellationToken : cancellationToken).ConfigureAwait(false));
        }
        /// <summary>
        /// Creates a <see cref="ServiceBusSessionReceiver"/> instance that can be used for receiving
        /// and settling messages from a specific session-enabled queue. It uses <see cref="ReceiveMode"/> to specify
        /// how messages are received. Defaults to PeekLock mode. The <see cref="ReceiveMode"/> is set in <see cref="ServiceBusReceiverOptions"/>.
        /// </summary>
        ///
        /// <param name="queueName">The session-enabled queue to create a <see cref="ServiceBusSessionReceiver"/> for.</param>
        /// <param name="sessionId">Gets or sets a session ID to scope the <see cref="ServiceBusSessionReceiver"/> to.</param>
        /// <param name="options">The set of <see cref="ServiceBusReceiverOptions"/> to use for configuring the
        /// <see cref="ServiceBusSessionReceiver"/>.</param>
        /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param>
        ///
        /// <remarks>Because this is establishing a session lock, this method performs a service call. If the
        /// sessionId parameter is null, and there are no available messages in the queue, this will
        /// throw a <see cref="ServiceBusException"/> with <see cref="ServiceBusException.Reason"/> of <see cref="ServiceBusFailureReason.ServiceTimeout"/>.
        /// </remarks>
        ///
        /// <returns>A <see cref="ServiceBusSessionReceiver"/> scoped to the specified queue and a specific session.</returns>
        public virtual async Task <ServiceBusSessionReceiver> AcceptSessionAsync(
            string queueName,
            string sessionId,
            ServiceBusSessionReceiverOptions options = default,
            CancellationToken cancellationToken      = default)
        {
            ValidateEntityName(queueName);
            options ??= new ServiceBusSessionReceiverOptions();
            options.SessionId = sessionId;

            return(await ServiceBusSessionReceiver.CreateSessionReceiverAsync(
                       entityPath : queueName,
                       connection : Connection,
                       plugins : Plugins,
                       options : options,
                       cancellationToken : cancellationToken).ConfigureAwait(false));
        }
Example #13
0
        /// <summary>
        /// Creates a session receiver which can be used to interact with all messages with the same sessionId.
        /// </summary>
        ///
        /// <param name="entityPath">The name of the specific queue to associate the receiver with.</param>
        /// <param name="connection">The <see cref="ServiceBusConnection" /> connection to use for communication with the Service Bus service.</param>
        /// <param name="sessionId">The sessionId for this receiver</param>
        /// <param name="options">A set of options to apply when configuring the receiver.</param>
        /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param>
        ///
        ///<returns>Returns a new instance of the <see cref="ServiceBusSessionReceiver"/> class.</returns>
        internal static async Task <ServiceBusSessionReceiver> CreateSessionReceiverAsync(
            string entityPath,
            ServiceBusConnection connection,
            string sessionId = default,
            ServiceBusReceiverOptions options   = default,
            CancellationToken cancellationToken = default)
        {
            var receiver = new ServiceBusSessionReceiver(
                connection: connection,
                entityPath: entityPath,
                options: options,
                sessionId: sessionId);

            await receiver.OpenLinkAsync(cancellationToken).ConfigureAwait(false);

            return(receiver);
        }
        ///  <summary>
        ///  Creates a session receiver which can be used to interact with all messages with the same sessionId.
        ///  </summary>
        ///  <param name="entityPath">The name of the specific queue to associate the receiver with.</param>
        ///  <param name="connection">The <see cref="ServiceBusConnection" /> connection to use for communication with the Service Bus service.</param>
        ///  <param name="plugins">The set of plugins to apply to incoming messages.</param>
        ///  <param name="options">A set of options to apply when configuring the receiver.</param>
        ///  <param name="sessionId">The Session Id to receive from or null to receive from the next available session.</param>
        ///  <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param>
        ///  <param name="isProcessor">True if called from the session processor.</param>
        ///  <returns>Returns a new instance of the <see cref="ServiceBusSessionReceiver"/> class.</returns>
        internal static async Task <ServiceBusSessionReceiver> CreateSessionReceiverAsync(
            string entityPath,
            ServiceBusConnection connection,
            IList <ServiceBusPlugin> plugins,
            ServiceBusSessionReceiverOptions options,
            string sessionId,
            CancellationToken cancellationToken,
            bool isProcessor = false)
        {
            var receiver = new ServiceBusSessionReceiver(
                connection: connection,
                entityPath: entityPath,
                plugins: plugins,
                options: options,
                cancellationToken: cancellationToken,
                sessionId: sessionId,
                isProcessor: isProcessor);

            try
            {
                await receiver.OpenLinkAsync(isProcessor, cancellationToken).ConfigureAwait(false);
            }
            catch (ServiceBusException e)
                when(e.Reason == ServiceBusFailureReason.ServiceTimeout && isProcessor)
                {
                    receiver.Logger.ProcessorAcceptSessionTimeout(receiver.FullyQualifiedNamespace, entityPath, e.ToString());
                    throw;
                }
            catch (TaskCanceledException exception)
                when(isProcessor)
                {
                    receiver.Logger.ProcessorStoppingAcceptSessionCanceled(receiver.FullyQualifiedNamespace, entityPath, exception.ToString());
                    throw;
                }
            catch (Exception ex)
            {
                receiver.Logger.ClientCreateException(typeof(ServiceBusSessionReceiver), receiver.FullyQualifiedNamespace, entityPath, ex);
                throw;
            }
            receiver.Logger.ClientCreateComplete(typeof(ServiceBusSessionReceiver), receiver.Identifier);
            return(receiver);
        }
        private async Task CreateAndInitializeSessionReceiver(
            CancellationToken cancellationToken)
        {
            _receiver = await ServiceBusSessionReceiver.CreateSessionReceiverAsync(
                entityPath : _entityPath,
                connection : _connection,
                options : _sessionReceiverOptions,
                cancellationToken : cancellationToken).ConfigureAwait(false);

            if (AutoRenewLock)
            {
                _sessionLockRenewalTask = RenewSessionLock(cancellationToken);
            }

            if (_sessionInitHandler != null)
            {
                var args = new ProcessSessionEventArgs(_receiver, cancellationToken);
                await _sessionInitHandler(args).ConfigureAwait(false);
            }
        }