///// <summary>
        /////   The converter to use for translating between AMQP messages and client library
        /////   types.
        ///// </summary>
        //private AmqpMessageConverter MessageConverter { get; }

        ///// <summary>
        /////   The AMQP connection scope responsible for managing transport constructs for this instance.
        ///// </summary>
        /////
        //internal AmqpConnectionScope ConnectionScope { get; }

        ///// <summary>
        /////   The AMQP link intended for use with receiving operations.
        ///// </summary>
        /////
        //internal FaultTolerantAmqpObject<ReceivingAmqpLink> ReceiveLink { get; }

        /// <summary>
        ///   Initializes a new instance of the <see cref="AmqpConsumer"/> class.
        /// </summary>
        ///
        /// <param name="entityName">The name of the Service Bus entity from which events will be consumed.</param>
        /// <param name="prefetchCount">Controls the number of events received and queued locally without regard to whether an operation was requested.  If <c>null</c> a default will be used.</param>
        /// <param name="ownerLevel">The relative priority to associate with the link; for a non-exclusive link, this value should be <c>null</c>.</param>
        /// <param name="connectionScope">The AMQP connection context for operations .</param>
        /// <param name="retryPolicy">The retry policy to consider when an operation fails.</param>
        /// <param name="sessionId"></param>
        ///
        /// <remarks>
        ///   As an internal type, this class performs only basic sanity checks against its arguments.  It
        ///   is assumed that callers are trusted and have performed deep validation.
        ///
        ///   Any parameters passed are assumed to be owned by this instance and safe to mutate or dispose;
        ///   creation of clones or otherwise protecting the parameters is assumed to be the purview of the
        ///   caller.
        /// </remarks>
        ///
        public AmqpConsumer(
            string entityName,
            long?ownerLevel,
            uint?prefetchCount,
            AmqpConnectionScope connectionScope,
            ServiceBusRetryPolicy retryPolicy,
            string sessionId)
        {
            Argument.AssertNotNullOrEmpty(entityName, nameof(entityName));
            Argument.AssertNotNull(connectionScope, nameof(connectionScope));
            Argument.AssertNotNull(retryPolicy, nameof(retryPolicy));
            EntityName      = entityName;
            ConnectionScope = connectionScope;
            RetryPolicy     = retryPolicy;

            ReceiveLink = new FaultTolerantAmqpObject <ReceivingAmqpLink>(
                timeout =>
                ConnectionScope.OpenConsumerLinkAsync(
                    //consumerGroup,
                    //partitionId,
                    timeout,
                    prefetchCount ?? DefaultPrefetchCount,
                    ownerLevel,
                    sessionId,
                    CancellationToken.None),
                link =>
            {
                CloseLink(link);
            });
        }
Example #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="AmqpRuleManager"/> class.
        /// </summary>
        ///
        /// <param name="subscriptionPath">The path of the Service Bus subscription to which the rule manager is bound.</param>
        /// <param name="connectionScope">The AMQP connection context for operations.</param>
        /// <param name="retryPolicy">The retry policy to consider when an operation fails.</param>
        /// <param name="identifier">The identifier for the rule manager.</param>
        ///
        /// <remarks>
        /// As an internal type, this class performs only basic sanity checks against its arguments.  It
        /// is assumed that callers are trusted and have performed deep validation.
        ///
        /// Any parameters passed are assumed to be owned by this instance and safe to mutate or dispose;
        /// creation of clones or otherwise protecting the parameters is assumed to be the purview of the
        /// caller.
        /// </remarks>
        public AmqpRuleManager(
            string subscriptionPath,
            AmqpConnectionScope connectionScope,
            ServiceBusRetryPolicy retryPolicy,
            string identifier)
        {
            Argument.AssertNotNullOrEmpty(subscriptionPath, nameof(subscriptionPath));
            Argument.AssertNotNull(connectionScope, nameof(connectionScope));
            Argument.AssertNotNull(retryPolicy, nameof(retryPolicy));

            _subscriptionPath = subscriptionPath;
            _connectionScope  = connectionScope;
            _retryPolicy      = retryPolicy;
            _identifier       = identifier;

            _managementLink = new FaultTolerantAmqpObject <RequestResponseAmqpLink>(
                timeout => _connectionScope.OpenManagementLinkAsync(
                    _subscriptionPath,
                    _identifier,
                    timeout,
                    CancellationToken.None),
                link =>
            {
                link.Session?.SafeClose();
                link.SafeClose();
            });
        }
Example #3
0
        /// <summary>
        ///   Initializes a new instance of the <see cref="AmqpSender"/> class.
        /// </summary>
        ///
        /// <param name="entityPath">The name of the entity to which messages will be sent.</param>
        /// <param name="connectionScope">The AMQP connection context for operations.</param>
        /// <param name="retryPolicy">The retry policy to consider when an operation fails.</param>
        /// <param name="identifier">The identifier for the sender.</param>
        ///
        /// <remarks>
        ///   As an internal type, this class performs only basic sanity checks against its arguments.  It
        ///   is assumed that callers are trusted and have performed deep validation.
        ///
        ///   Any parameters passed are assumed to be owned by this instance and safe to mutate or dispose;
        ///   creation of clones or otherwise protecting the parameters is assumed to be the purview of the
        ///   caller.
        /// </remarks>
        ///
        public AmqpSender(
            string entityPath,
            AmqpConnectionScope connectionScope,
            ServiceBusRetryPolicy retryPolicy,
            string identifier)
        {
            Argument.AssertNotNullOrEmpty(entityPath, nameof(entityPath));
            Argument.AssertNotNull(connectionScope, nameof(connectionScope));
            Argument.AssertNotNull(retryPolicy, nameof(retryPolicy));

            _entityPath      = entityPath;
            _identifier      = identifier;
            _retryPolicy     = retryPolicy;
            _connectionScope = connectionScope;

            _sendLink = new FaultTolerantAmqpObject <SendingAmqpLink>(
                timeout => CreateLinkAndEnsureSenderStateAsync(timeout, CancellationToken.None),
                link =>
            {
                link.Session?.SafeClose();
                link.SafeClose();
            });

            _managementLink = new FaultTolerantAmqpObject <RequestResponseAmqpLink>(
                timeout => OpenManagementLinkAsync(timeout),
                link =>
            {
                link.Session?.SafeClose();
                link.SafeClose();
            });
        }
Example #4
0
        /// <summary>
        ///   Initializes a new instance of the <see cref="AmqpConsumer"/> class.
        /// </summary>
        ///
        /// <param name="entityName">The name of the Service Bus entity from which events will be consumed.</param>
        /// <param name="prefetchCount">Controls the number of events received and queued locally without regard to whether an operation was requested.  If <c>null</c> a default will be used.</param>
        /// <param name="receiveMode">The <see cref="ReceiveMode"/> used to specify how messages are received. Defaults to PeekLock mode.</param>
        /// <param name="connectionScope">The AMQP connection context for operations .</param>
        /// <param name="retryPolicy">The retry policy to consider when an operation fails.</param>
        /// <param name="sessionId"></param>
        /// <param name="isSessionReceiver"></param>
        ///
        /// <remarks>
        ///   As an internal type, this class performs only basic sanity checks against its arguments.  It
        ///   is assumed that callers are trusted and have performed deep validation.
        ///
        ///   Any parameters passed are assumed to be owned by this instance and safe to mutate or dispose;
        ///   creation of clones or otherwise protecting the parameters is assumed to be the purview of the
        ///   caller.
        /// </remarks>
        ///
        public AmqpConsumer(
            string entityName,
            ReceiveMode receiveMode,
            uint?prefetchCount,
            AmqpConnectionScope connectionScope,
            ServiceBusRetryPolicy retryPolicy,
            string sessionId,
            bool isSessionReceiver)
        {
            Argument.AssertNotNullOrEmpty(entityName, nameof(entityName));
            Argument.AssertNotNull(connectionScope, nameof(connectionScope));
            Argument.AssertNotNull(retryPolicy, nameof(retryPolicy));
            EntityName         = entityName;
            _connectionScope   = connectionScope;
            _retryPolicy       = retryPolicy;
            _isSessionReceiver = isSessionReceiver;
            _receiveMode       = receiveMode;

            ReceiveLink = new FaultTolerantAmqpObject <ReceivingAmqpLink>(
                timeout =>
                _connectionScope.OpenConsumerLinkAsync(
                    timeout: timeout,
                    prefetchCount: prefetchCount ?? DefaultPrefetchCount,
                    receiveMode: receiveMode,
                    sessionId: sessionId,
                    isSessionReceiver: isSessionReceiver,
                    cancellationToken: CancellationToken.None),
                link =>
            {
                CloseLink(link);
            });
        }
        /// <summary>
        ///   Initializes a new instance of the <see cref="AmqpClient"/> class.
        /// </summary>
        ///
        /// <param name="host">The fully qualified host name for the Service Bus namespace.  This is likely to be similar to <c>{yournamespace}.servicebus.windows.net</c>.</param>
        /// <param name="credential">The Azure managed identity credential to use for authorization.  Access controls may be specified by the Service Bus namespace or the requested Service Bus entity, depending on Azure configuration.</param>
        /// <param name="clientOptions">A set of options to apply when configuring the client.</param>
        /// <param name="connectionScope">The optional scope to use for AMQP connection management.  If <c>null</c>, a new scope will be created.</param>
        ///
        /// <remarks>
        ///   As an internal type, this class performs only basic sanity checks against its arguments.  It
        ///   is assumed that callers are trusted and have performed deep validation.
        ///
        ///   Any parameters passed are assumed to be owned by this instance and safe to mutate or dispose;
        ///   creation of clones or otherwise protecting the parameters is assumed to be the purview of the
        ///   caller.
        /// </remarks>
        ///
        protected AmqpClient(
            string host,
            ServiceBusTokenCredential credential,
            ServiceBusClientOptions clientOptions,
            AmqpConnectionScope connectionScope)
        {
            Argument.AssertNotNullOrEmpty(host, nameof(host));
            Argument.AssertNotNull(credential, nameof(credential));
            Argument.AssertNotNull(clientOptions, nameof(clientOptions));

            try
            {
                //TODO add event ServiceBusEventSource.Log.ClientCreateStart(host, entityName);

                ServiceEndpoint = new UriBuilder
                {
                    Scheme = clientOptions.TransportType.GetUriScheme(),
                    Host   = host
                }.Uri;

                Credential      = credential;
                ConnectionScope = connectionScope ?? new AmqpConnectionScope(ServiceEndpoint, credential, clientOptions.TransportType, clientOptions.Proxy);
            }
            finally
            {
                // TODO add event  ServiceBusEventSource.Log.ServiceBusClientCreateComplete(host, entityName);
            }
        }
 public AmqpTransactionEnlistment(
     Transaction transaction,
     AmqpTransactionManager transactionManager,
     AmqpConnectionScope connectionScope,
     TimeSpan timeout)
 {
     _transactionId      = transaction.TransactionInformation.LocalIdentifier;
     _transactionManager = transactionManager;
     _connectionScope    = connectionScope;
     _timeout            = timeout;
 }
Example #7
0
        /// <summary>
        ///   Initializes a new instance of the <see cref="AmqpSender"/> class.
        /// </summary>
        ///
        /// <param name="entityName">The name of the entity to which messages will be sent.</param>
        /// <param name="connectionScope">The AMQP connection context for operations.</param>
        /// <param name="retryPolicy">The retry policy to consider when an operation fails.</param>
        ///
        /// <remarks>
        ///   As an internal type, this class performs only basic sanity checks against its arguments.  It
        ///   is assumed that callers are trusted and have performed deep validation.
        ///
        ///   Any parameters passed are assumed to be owned by this instance and safe to mutate or dispose;
        ///   creation of clones or otherwise protecting the parameters is assumed to be the purview of the
        ///   caller.
        /// </remarks>
        ///
        public AmqpSender(
            string entityName,
            AmqpConnectionScope connectionScope,
            ServiceBusRetryPolicy retryPolicy)
        {
            Argument.AssertNotNullOrEmpty(entityName, nameof(entityName));
            Argument.AssertNotNull(connectionScope, nameof(connectionScope));
            Argument.AssertNotNull(retryPolicy, nameof(retryPolicy));

            EntityName      = entityName;
            RetryPolicy     = retryPolicy;
            ConnectionScope = connectionScope;

            SendLink = new FaultTolerantAmqpObject <SendingAmqpLink>(
                timeout => CreateLinkAndEnsureProducerStateAsync(timeout, CancellationToken.None),
                link =>
            {
                link.Session?.SafeClose();
                link.SafeClose();
            });
        }
        /// <summary>
        ///   Initializes a new instance of the <see cref="AmqpClient"/> class.
        /// </summary>
        ///
        /// <param name="host">The fully qualified host name for the Service Bus namespace.  This is likely to be similar to <c>{yournamespace}.servicebus.windows.net</c>.</param>
        /// <param name="credential">The Azure managed identity credential to use for authorization.  Access controls may be specified by the Service Bus namespace or the requested Service Bus entity, depending on Azure configuration.</param>
        /// <param name="options">A set of options to apply when configuring the client.</param>
        ///
        /// <remarks>
        ///   As an internal type, this class performs only basic sanity checks against its arguments.  It
        ///   is assumed that callers are trusted and have performed deep validation.
        ///
        ///   Any parameters passed are assumed to be owned by this instance and safe to mutate or dispose;
        ///   creation of clones or otherwise protecting the parameters is assumed to be the purview of the
        ///   caller.
        /// </remarks>
        ///
        internal AmqpClient(
            string host,
            ServiceBusTokenCredential credential,
            ServiceBusClientOptions options)
        {
            Argument.AssertNotNullOrEmpty(host, nameof(host));
            Argument.AssertNotNull(credential, nameof(credential));
            Argument.AssertNotNull(options, nameof(options));

            ServiceEndpoint = new UriBuilder
            {
                Scheme = options.TransportType.GetUriScheme(),
                Host   = host
            }.Uri;

            Credential      = credential;
            ConnectionScope = new AmqpConnectionScope(
                ServiceEndpoint,
                credential,
                options.TransportType,
                options.WebProxy);
        }
Example #9
0
        /// <summary>
        ///   Initializes a new instance of the <see cref="AmqpClient"/> class.
        /// </summary>
        ///
        /// <param name="host">The fully qualified host name for the Service Bus namespace.  This is likely to be similar to <c>{yournamespace}.servicebus.windows.net</c>.</param>
        /// <param name="entityName">The name of the specific Service Bus entity to connect the client to.</param>
        /// <param name="credential">The Azure managed identity credential to use for authorization.  Access controls may be specified by the Service Bus namespace or the requested Service Bus entity, depending on Azure configuration.</param>
        /// <param name="clientOptions">A set of options to apply when configuring the client.</param>
        /// <param name="connectionScope">The optional scope to use for AMQP connection management.  If <c>null</c>, a new scope will be created.</param>
        ///
        /// <remarks>
        ///   As an internal type, this class performs only basic sanity checks against its arguments.  It
        ///   is assumed that callers are trusted and have performed deep validation.
        ///
        ///   Any parameters passed are assumed to be owned by this instance and safe to mutate or dispose;
        ///   creation of clones or otherwise protecting the parameters is assumed to be the purview of the
        ///   caller.
        /// </remarks>
        ///
        protected AmqpClient(string host,
                             string entityName,
                             ServiceBusTokenCredential credential,
                             ServiceBusConnectionOptions clientOptions,
                             AmqpConnectionScope connectionScope)
        {
            Argument.AssertNotNullOrEmpty(host, nameof(host));
            Argument.AssertNotNullOrEmpty(entityName, nameof(entityName));
            Argument.AssertNotNull(credential, nameof(credential));
            Argument.AssertNotNull(clientOptions, nameof(clientOptions));

            try
            {
                //TODO add event ServiceBusEventSource.Log.ClientCreateStart(host, entityName);

                ServiceEndpoint = new UriBuilder
                {
                    Scheme = clientOptions.TransportType.GetUriScheme(),
                    Host   = host
                }.Uri;

                EntityName      = entityName;
                Credential      = credential;
                ConnectionScope = connectionScope ?? new AmqpConnectionScope(ServiceEndpoint, entityName, credential, clientOptions.TransportType, clientOptions.Proxy);

                ManagementLink = new FaultTolerantAmqpObject <RequestResponseAmqpLink>(
                    timeout => ConnectionScope.OpenManagementLinkAsync(timeout, CancellationToken.None),
                    link =>
                {
                    link.Session?.SafeClose();
                    link.SafeClose();
                });
            }
            finally
            {
                // TODO add event  ServiceBusEventSource.Log.ServiceBusClientCreateComplete(host, entityName);
            }
        }
        public async Task <ArraySegment <byte> > EnlistAsync(
            Transaction transaction,
            AmqpConnectionScope connectionScope,
            string transactionGroup,
            TimeSpan timeout)
        {
            if (transaction.IsolationLevel != IsolationLevel.Serializable)
            {
                throw new InvalidOperationException($"The only supported IsolationLevel is {nameof(IsolationLevel.Serializable)}");
            }

            string transactionId = transaction.TransactionInformation.LocalIdentifier;
            AmqpTransactionEnlistment transactionEnlistment;

            lock (_syncRoot)
            {
                if (!_enlistmentMap.TryGetValue(transactionId, out transactionEnlistment))
                {
                    transactionEnlistment = new AmqpTransactionEnlistment(
                        transaction,
                        this,
                        connectionScope,
                        transactionGroup,
                        timeout);
                    _enlistmentMap.Add(transactionId, transactionEnlistment);

                    if (!transaction.EnlistPromotableSinglePhase(transactionEnlistment))
                    {
                        _enlistmentMap.Remove(transactionId);
                        throw new InvalidOperationException("Local transactions are not supported with other resource managers/DTC.");
                    }
                }
            }

            transactionEnlistment = await transactionEnlistment.GetOrCreateAsync(timeout).ConfigureAwait(false);

            return(transactionEnlistment.AmqpTransactionId);
        }