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; }
internal ProcessSessionMessageEventArgs( ServiceBusReceivedMessage message, ServiceBusSessionReceiver receiver, SessionReceiverManager receiverManager, CancellationToken cancellationToken) : this(message, receiver, cancellationToken) { _receiverManager = receiverManager; }
/// <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; }
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)); }
/// <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); } }