예제 #1
0
        private async Task ProvisionQueueAsync(ServiceBus manager, string queueName)
        {
            if (!(await manager.QueueExistsAsync(queueName)))
            {
                _logger.LogDebug($"Provisioning queue: '{queueName}'");

                // TODO :: Implement retry policies
                try
                {
                    await manager.CreateQueueAsync(new QueueDescription(queueName)
                    {
                        AutoDeleteOnIdle         = _options.AutoDeleteOnIdle,
                        DefaultMessageTimeToLive = _options.MessageTimeToLive,
                        EnableBatchedOperations  = _options.EnableServerSideBatchedOperations,
                        EnableExpress            = _options.EnableExpress,
                        EnablePartitioning       = _options.EnablePartitioning,
                        LockDuration             = _options.MessageLockDuration,
                        MaxDeliveryCount         = _options.MaximumDeliveryCount
                    });

                    _logger.LogInformation($"Provisioned queue: '{queueName}'");
                }
                catch (Exception ex)
                {
                    _logger.LogError($"An error occured whilst provisioning queue: '{queueName}'", ex);
                }
            }
            else
            {
                _logger.LogDebug($"Queue '{queueName}' already exists, no need to provision.");
            }

            RemoveOperation(queueName);
        }
예제 #2
0
        private async Task ProvisionTopicAsync(ServiceBus manager, string topicName, bool keepOperationPending = false)
        {
            if (!(await manager.TopicExistsAsync(topicName)))
            {
                _logger.LogDebug($"Provisioning topic: '{topicName}'");

                // TODO :: Implement retry policies
                try
                {
                    await manager.CreateTopicAsync(new TopicDescription(topicName)
                    {
                        AutoDeleteOnIdle         = _options.AutoDeleteOnIdle,
                        DefaultMessageTimeToLive = _options.MessageTimeToLive,
                        EnableBatchedOperations  = _options.EnableServerSideBatchedOperations,
                        EnableExpress            = _options.EnableExpress,
                        EnablePartitioning       = _options.EnablePartitioning
                    });

                    _logger.LogInformation($"Provisioned topic: '{topicName}'");
                }
                catch (Exception ex)
                {
                    _logger.LogError($"An error occured whilst provisioning topic: '{topicName}'", ex);
                }
            }
            else
            {
                _logger.LogDebug($"Topic '{topicName}' already exists, no need to provision.");
            }

            if (!keepOperationPending)
            {
                RemoveOperation(topicName);
            }
        }
예제 #3
0
        private ServiceBus CreateServiceBusManager()
        {
            var manager = ServiceBus.CreateFromConnectionString(_options.ConnectionString);

            manager.Settings.OperationTimeout = _options.RemoteOperationTimeout;
            return(manager);
        }
예제 #4
0
        /// <summary>
        /// Checks if a topic by the provided <paramref name="topicName"/> exists and
        /// Checks if a subscription name by the provided <paramref name="subscriptionName"/> exists.
        /// </summary>
        protected virtual void CheckTopicExists(Manager manager, string topicName, string subscriptionName)
        {
            // Configure Queue Settings
            var eventTopicDescription = new TopicDescription(topicName)
            {
#if NET452
                MaxSizeInMegabytes = 5120,
#endif
#if NETSTANDARD2_0
                MaxSizeInMB = 5120,
#endif
                DefaultMessageTimeToLive = new TimeSpan(0, 25, 0),
                EnablePartitioning       = true,
                EnableBatchedOperations  = true,
            };

#if NETSTANDARD2_0
            Task <bool> checkTask = manager.TopicExistsAsync(topicName);
            checkTask.Wait(1500);
            if (!checkTask.Result)
            {
                Task <TopicDescription> createTopicTask = manager.CreateTopicAsync(eventTopicDescription);
                createTopicTask.Wait(1500);
            }

            checkTask = manager.SubscriptionExistsAsync(topicName, subscriptionName);
            checkTask.Wait(1500);
            if (!checkTask.Result)
            {
                var subscriptionDescription = new SubscriptionDescription(topicName, subscriptionName)
                {
                    DefaultMessageTimeToLive = eventTopicDescription.DefaultMessageTimeToLive,
                    EnableBatchedOperations  = eventTopicDescription.EnableBatchedOperations,
                };
                Task <SubscriptionDescription> createTask = manager.CreateSubscriptionAsync(subscriptionDescription);
                createTask.Wait(1500);
            }
#endif

#if NET452
            // Create the topic if it does not exist already
            if (!manager.TopicExists(eventTopicDescription.Path))
            {
                manager.CreateTopic(eventTopicDescription);
            }

            if (!manager.SubscriptionExists(eventTopicDescription.Path, subscriptionName))
            {
                manager.CreateSubscription
                (
                    new SubscriptionDescription(eventTopicDescription.Path, subscriptionName)
                {
                    DefaultMessageTimeToLive = new TimeSpan(0, 25, 0),
                    EnableBatchedOperations  = true,
                    EnableDeadLetteringOnFilterEvaluationExceptions = true
                }
                );
            }
#endif
        }
예제 #5
0
        private async Task ProvisionSubscriptionAsync(ServiceBus manager, string topicName, string subscriptionName)
        {
            await ProvisionTopicAsync(manager, topicName, true);

            if (!(await manager.SubscriptionExistsAsync(topicName, subscriptionName)))
            {
                _logger.LogDebug($"Provisioning subscription: '{topicName}/{subscriptionName}'");

                // TODO :: Implement retry policies
                try
                {
                    await manager.CreateSubscriptionAsync(new SubscriptionDescription(topicName, subscriptionName)
                    {
                        AutoDeleteOnIdle         = _options.AutoDeleteOnIdle,
                        DefaultMessageTimeToLive = _options.MessageTimeToLive,
                        EnableBatchedOperations  = _options.EnableServerSideBatchedOperations,
                        LockDuration             = _options.MessageLockDuration,
                        MaxDeliveryCount         = _options.MaximumDeliveryCount
                    });

                    _logger.LogInformation($"Provisioned subscription: '{topicName}/{subscriptionName}'");
                }
                catch (Exception ex)
                {
                    _logger.LogError($"An error occured whilst provisioning subscription: '{topicName}/{subscriptionName}'", ex);
                }
            }
            else
            {
                _logger.LogDebug($"Subscription '{topicName}/{subscriptionName}' already exists, no need to provision.");
            }

            RemoveOperation(topicName);
        }
예제 #6
0
        /// <summary>
        /// Creates <see cref="AzureBus{TAuthenticationToken}.NumberOfReceiversCount"/> <see cref="IMessageReceiver"/>.
        /// If flushing is required, any flushed <see cref="IMessageReceiver"/> has <see cref="ClientEntity.Close()"/> called on it first.
        /// </summary>
        /// <param name="manager">The <see cref="Manager"/>.</param>
        /// <param name="serviceBusReceivers">The receivers collection to place <see cref="IMessageReceiver"/> instances into.</param>
        /// <param name="topicName">The topic name.</param>
        /// <param name="topicSubscriptionName">The topic subscription name.</param>
#endif
#if NETSTANDARD2_0
        /// <summary>
        /// Creates <see cref="AzureBus{TAuthenticationToken}.NumberOfReceiversCount"/> <see cref="IMessageReceiver"/>.
        /// If flushing is required, any flushed <see cref="IMessageReceiver"/> has <see cref="ClientEntity.CloseAsync()"/> called on it first.
        /// </summary>
        /// <param name="manager">The <see cref="Manager"/>.</param>
        /// <param name="serviceBusReceivers">The receivers collection to place <see cref="IMessageReceiver"/> instances into.</param>
        /// <param name="topicName">The topic name.</param>
        /// <param name="topicSubscriptionName">The topic subscription name.</param>
#endif
        protected virtual void InstantiateReceiving(Manager manager, IDictionary <int, IMessageReceiver> serviceBusReceivers, string topicName, string topicSubscriptionName)
        {
            for (int i = 0; i < NumberOfReceiversCount; i++)
            {
#if NET452
                IMessageReceiver serviceBusReceiver = SubscriptionClient.CreateFromConnectionString(ConnectionString, topicName, topicSubscriptionName);
#endif
#if NETSTANDARD2_0
                IMessageReceiver serviceBusReceiver = new MessageReceiver(ConnectionString, EntityNameHelper.FormatSubscriptionPath(topicName, topicSubscriptionName));
#endif
                if (serviceBusReceivers.ContainsKey(i))
                {
                    serviceBusReceivers[i] = serviceBusReceiver;
                }
                else
                {
                    serviceBusReceivers.Add(i, serviceBusReceiver);
                }
            }
            // Remove any if the number has decreased
            for (int i = NumberOfReceiversCount; i < serviceBusReceivers.Count; i++)
            {
                IMessageReceiver serviceBusReceiver;
                if (serviceBusReceivers.TryGetValue(i, out serviceBusReceiver))
                {
#if NET452
                    serviceBusReceiver.Close();
#endif
#if NETSTANDARD2_0
                    serviceBusReceiver.CloseAsync().Wait(1500);
#endif
                }
                serviceBusReceivers.Remove(i);
            }
        }
예제 #7
0
        /// <summary>
        /// Instantiate receiving on this bus by
        /// calling <see cref="CheckPrivateTopicExists"/> and <see cref="CheckPublicTopicExists"/>
        /// then InstantiateReceiving for private and public topics,
        /// calls <see cref="CleanUpDeadLetters"/> for the private and public topics,
        /// then calling <see cref="AzureBus{TAuthenticationToken}.StartSettingsChecking"/>
        /// </summary>
        protected override void InstantiateReceiving()
        {
#if NET452
            Manager manager = Manager.CreateFromConnectionString(ConnectionString);
#endif
#if NETSTANDARD2_0
            var manager = new Manager(ConnectionString);
#endif

            CheckPrivateTopicExists(manager);
            CheckPublicTopicExists(manager);

            try
            {
                InstantiateReceiving(manager, PrivateServiceBusReceivers, PrivateTopicName, PrivateTopicSubscriptionName);
            }
            catch (UriFormatException exception)
            {
                throw new InvalidConfigurationException("The connection string for one of the private Service Bus receivers may be invalid.", exception);
            }
            try
            {
                InstantiateReceiving(manager, PublicServiceBusReceivers, PublicTopicName, PublicTopicSubscriptionName);
            }
            catch (UriFormatException exception)
            {
                throw new InvalidConfigurationException("The connection string for one of the public Service Bus receivers may be invalid.", exception);
            }

            bool   enableDeadLetterCleanUp;
            string enableDeadLetterCleanUpValue = ConfigurationManager.GetSetting("Cqrs.Azure.Servicebus.EnableDeadLetterCleanUp");
            if (bool.TryParse(enableDeadLetterCleanUpValue, out enableDeadLetterCleanUp) && enableDeadLetterCleanUp)
            {
                CleanUpDeadLetters(PrivateTopicName, PrivateTopicSubscriptionName);
                CleanUpDeadLetters(PublicTopicName, PublicTopicSubscriptionName);
            }

            // If this is also a publisher, then it will the check over there and that will handle this
            // we only need to check one of these
            if (PublicServiceBusPublisher != null)
            {
                return;
            }

            StartSettingsChecking();
        }
예제 #8
0
        /// <summary>
        /// Instantiate publishing on this bus by
        /// calling <see cref="CheckPrivateTopicExists"/> and <see cref="CheckPublicTopicExists"/>
        /// then calling <see cref="AzureBus{TAuthenticationToken}.StartSettingsChecking"/>
        /// </summary>
        protected override void InstantiatePublishing()
        {
#if NET452
            Manager manager = Manager.CreateFromConnectionString(ConnectionString);
#endif
#if NETSTANDARD2_0
            var manager = new Manager(ConnectionString);
#endif
            CheckPrivateTopicExists(manager);
            CheckPublicTopicExists(manager);

#if NET452
            PrivateServiceBusPublisher = TopicClient.CreateFromConnectionString(ConnectionString, PrivateTopicName);
            PublicServiceBusPublisher  = TopicClient.CreateFromConnectionString(ConnectionString, PublicTopicName);
#endif
#if NETSTANDARD2_0
            PrivateServiceBusPublisher = new TopicClient(ConnectionString, PrivateTopicName);
            PublicServiceBusPublisher  = new TopicClient(ConnectionString, PublicTopicName);
#endif
            StartSettingsChecking();
        }
예제 #9
0
        /// <summary>
        /// Instantiate receiving on this bus by
        /// calling <see cref="CheckPrivateHubExists"/> and <see cref="CheckPublicHubExists"/>
        /// then InstantiateReceiving for private and public topics,
        /// then calling <see cref="AzureBus{TAuthenticationToken}.StartSettingsChecking"/>
        /// </summary>
        protected override void InstantiateReceiving()
        {
#if NET452
            Manager manager = Manager.CreateFromConnectionString(ConnectionString);
#endif
#if NETSTANDARD2_0
            var manager = new Manager(ConnectionString);
#endif

            CheckPrivateHubExists(manager);
            CheckPublicHubExists(manager);

            EventHubReceiver = new EventProcessorHost(PublicEventHubName, PublicEventHubConsumerGroupName, ConnectionString, StorageConnectionString, "Cqrs");

            // If this is also a publisher, then it will the check over there and that will handle this
            if (EventHubPublisher != null)
            {
                return;
            }

            StartSettingsChecking();
        }
예제 #10
0
        /// <summary>
        /// Checks if a event hub by the provided <paramref name="hubName"/> exists and
        /// Checks if a consumer group by the provided <paramref name="consumerGroupNames"/> exists.
        /// </summary>
        protected virtual void CheckHubExists(Manager manager, string hubName, string consumerGroupNames)
        {
#if NET452
            // Configure Queue Settings
            var eventHubDescription = new EventHubDescription(hubName)
            {
                MessageRetentionInDays = long.MaxValue,
            };

            // Create the topic if it does not exist already
            manager.CreateEventHubIfNotExists(eventHubDescription);

            var subscriptionDescription = new SubscriptionDescription(eventHubDescription.Path, consumerGroupNames);

            if (!manager.SubscriptionExists(eventHubDescription.Path, consumerGroupNames))
            {
                manager.CreateSubscription(subscriptionDescription);
            }
#endif
#if NETSTANDARD2_0
            /*
             * // Configure Queue Settings
             * var eventHubDescription = new EventHubDescription(hubName)
             * {
             *      MessageRetentionInDays = long.MaxValue,
             * };
             *
             * // Create the topic if it does not exist already
             * manager.CreateEventHubIfNotExists(eventHubDescription);
             *
             * Task<bool> checkTask = manager.SubscriptionExistsAsync(eventHubDescription.Path, consumerGroupNames);
             * checkTask.Wait(1500);
             * if (!checkTask.Result)
             *      manager.CreateSubscriptionAsync(subscriptionDescription).Wait(1500);
             */
            Logger.LogWarning($"Checking EventHubs and subscriptions is not currently implemented until the Azure libraries provide management facilities. You will need to check these objects exist manually: EventHub {hubName}, Subscription/Consumer Group {consumerGroupNames}", "AzureEventHub");
#endif
        }
예제 #11
0
        /// <summary>
        /// Instantiate publishing on this bus by
        /// calling <see cref="CheckPrivateHubExists"/> and <see cref="CheckPublicHubExists"/>
        /// then calling <see cref="AzureBus{TAuthenticationToken}.StartSettingsChecking"/>
        /// </summary>
        protected override void InstantiatePublishing()
        {
#if NET452
            Manager manager = Manager.CreateFromConnectionString(ConnectionString);
#endif
#if NETSTANDARD2_0
            var manager = new Manager(ConnectionString);
#endif
            CheckPrivateHubExists(manager);
            CheckPublicHubExists(manager);

#if NET452
            EventHubPublisher = EventHubClient.CreateFromConnectionString(ConnectionString, PublicEventHubName);
#endif
#if NETSTANDARD2_0
            var connectionStringBuilder = new EventHubsConnectionStringBuilder(ConnectionString)
            {
                EntityPath = PublicEventHubName
            };
            EventHubPublisher = EventHubClient.Create(connectionStringBuilder);
#endif
            StartSettingsChecking();
        }
예제 #12
0
        /// <summary>
        /// Calls <see cref="AzureServiceBus{TAuthenticationToken}.InstantiateReceiving()"/>
        /// then uses a <see cref="Task"/> to apply the <see cref="FilterKey"/> as a <see cref="RuleDescription"/>
        /// to the <see cref="IMessageReceiver"/> instances in <paramref name="serviceBusReceivers"/>.
        /// </summary>
        /// <param name="manager">The <see cref="Manager"/>.</param>
        /// <param name="serviceBusReceivers">The receivers collection to place <see cref="IMessageReceiver"/> instances into.</param>
        /// <param name="topicName">The topic name.</param>
        /// <param name="topicSubscriptionName">The topic subscription name.</param>
        protected override void InstantiateReceiving(Manager manager, IDictionary <int, IMessageReceiver> serviceBusReceivers, string topicName, string topicSubscriptionName)
        {
            base.InstantiateReceiving(manager, serviceBusReceivers, topicName, topicSubscriptionName);

            Task.Factory.StartNewSafely
                (() =>
            {
                // Because refreshing the rule can take a while, we only want to do this when the value changes
                string filter;
                if (!ConfigurationManager.TryGetSetting(FilterKeyConfigurationKey, out filter))
                {
                    return;
                }
                if (FilterKey.ContainsKey(topicName) && FilterKey[topicName] == filter)
                {
                    return;
                }
                FilterKey[topicName] = filter;

                // https://docs.microsoft.com/en-us/azure/application-insights/app-insights-analytics-reference#summarize-operator
                // http://www.summa.com/blog/business-blog/everything-you-need-to-know-about-azure-service-bus-brokered-messaging-part-2#rulesfiltersactions
                // https://github.com/Azure-Samples/azure-servicebus-messaging-samples/tree/master/TopicFilters
#if NET452
                SubscriptionClient client = serviceBusReceivers[0];
#endif
#if NETSTANDARD2_0
                // Since the IMessageReceiver and it's concrete implementation doesn't allow for the management of rules, we're creating a SubscriptionClient just to do the rules... it gets cleaned up somewhat below.
                SubscriptionClient client = new SubscriptionClient(ConnectionString, topicName, topicSubscriptionName);
#endif
                bool reAddRule = false;
                try
                {
#if NET452
                    IEnumerable <RuleDescription> rules = manager.GetRules(client.TopicPath, client.Name).ToList();
#endif
#if NETSTANDARD2_0
                    Task <IList <RuleDescription> > getRulesTask = manager.GetRulesAsync(client.TopicPath, client.SubscriptionName);
                    getRulesTask.Wait();
                    IEnumerable <RuleDescription> rules = getRulesTask.Result;
#endif
                    RuleDescription ruleDescription = rules.SingleOrDefault(rule => rule.Name == "CqrsConfiguredFilter");
                    if (ruleDescription != null)
                    {
                        var sqlFilter = ruleDescription.Filter as SqlFilter;
                        if (sqlFilter == null && !string.IsNullOrWhiteSpace(filter))
                        {
                            reAddRule = true;
                        }
                        else if (sqlFilter != null && sqlFilter.SqlExpression != filter)
                        {
                            reAddRule = true;
                        }
                        if (sqlFilter != null && reAddRule)
                        {
#if NET452
                            client.RemoveRule("CqrsConfiguredFilter");
#endif
#if NETSTANDARD2_0
                            client.RemoveRuleAsync("CqrsConfiguredFilter").Wait();
#endif
                        }
                    }
                    else if (!string.IsNullOrWhiteSpace(filter))
                    {
                        reAddRule = true;
                    }

                    ruleDescription = rules.SingleOrDefault(rule => rule.Name == "$Default");
                    // If there is a default rule and we have a rule, it will cause issues
                    if (!string.IsNullOrWhiteSpace(filter) && ruleDescription != null)
                    {
#if NET452
                        client.RemoveRule("$Default");
#endif
#if NETSTANDARD2_0
                        client.RemoveRuleAsync("$Default").Wait();
#endif
                    }
                    // If we don't have a rule and there is no longer a default rule, it will cause issues
                    else if (string.IsNullOrWhiteSpace(filter) && !rules.Any())
                    {
                        ruleDescription = new RuleDescription
                                          (
                            "$Default",
                            new SqlFilter("1=1")
                                          );
#if NET452
                        client.AddRule(ruleDescription);
#endif
#if NETSTANDARD2_0
                        client.AddRuleAsync(ruleDescription).Wait();
#endif
                    }
                }
                catch (AggregateException ex)
                {
                    if (!(ex.InnerException is MessagingEntityNotFoundException))
                    {
                        throw;
                    }
                }
                catch (MessagingEntityNotFoundException)
                {
                }

                if (!reAddRule)
                {
                    return;
                }

                int loopCounter = 0;
                while (loopCounter < 10)
                {
                    try
                    {
                        RuleDescription ruleDescription = new RuleDescription
                                                          (
                            "CqrsConfiguredFilter",
                            new SqlFilter(filter)
                                                          );
#if NET452
                        client.AddRule(ruleDescription);
#endif
#if NETSTANDARD2_0
                        client.AddRuleAsync(ruleDescription).Wait();
#endif
                        break;
                    }
                    catch (MessagingEntityAlreadyExistsException exception)
                    {
                        loopCounter++;
                        // Still waiting for the delete to complete
                        Thread.Sleep(1000);
                        if (loopCounter == 9)
                        {
                            Logger.LogError("Setting the filter failed as it already exists.", exception: exception);
                            TelemetryHelper.TrackException(exception);
                        }
                    }
                    catch (Exception exception)
                    {
                        Logger.LogError("Setting the filter failed.", exception: exception);
                        TelemetryHelper.TrackException(exception);
                        break;
                    }
                }

#if NETSTANDARD2_0
                client.CloseAsync();
#endif
            });
        }
예제 #13
0
 /// <summary>
 /// Checks if the public topic and subscription name exists as per <see cref="PublicTopicName"/> and <see cref="PublicTopicSubscriptionName"/>.
 /// </summary>
 /// <param name="manager">The <see cref="Manager"/>.</param>
 protected virtual void CheckPublicTopicExists(Manager manager)
 {
     CheckTopicExists(manager, PublicTopicName = ConfigurationManager.GetSetting(PublicTopicNameConfigurationKey) ?? DefaultPublicTopicName, PublicTopicSubscriptionName = ConfigurationManager.GetSetting(PublicTopicSubscriptionNameConfigurationKey) ?? DefaultPublicTopicSubscriptionName);
 }
예제 #14
0
 /// <summary>
 /// Checks if the public hub and consumer group name exists as per <see cref="PublicEventHubName"/> and <see cref="PublicEventHubConsumerGroupName"/>.
 /// </summary>
 /// <param name="manager">The <see cref="Manager"/>.</param>
 protected virtual void CheckPublicHubExists(Manager manager)
 {
     CheckHubExists(manager, PublicEventHubName = ConfigurationManager.GetSetting(PublicEventHubNameConfigurationKey) ?? DefaultPublicEventHubName, PublicEventHubConsumerGroupName = ConfigurationManager.GetSetting(PublicEventHubConsumerGroupNameConfigurationKey) ?? DefaultPublicEventHubConsumerGroupName);
 }
 /// <summary>
 /// Checks if the public topic and subscription name exists as per <see cref="PublicTopicName"/> and <see cref="PublicTopicSubscriptionName"/>.
 /// </summary>
 /// <param name="manager">The <see cref="Manager"/>.</param>
 /// <param name="createSubscriptionIfNotExists">Create a subscription if there isn't one</param>
 protected virtual void CheckPublicTopicExists(Manager manager, bool createSubscriptionIfNotExists = true)
 {
     CheckTopicExists(manager, PublicTopicName = ConfigurationManager.GetSetting(PublicTopicNameConfigurationKey) ?? DefaultPublicTopicName, PublicTopicSubscriptionName = ConfigurationManager.GetSetting(PublicTopicSubscriptionNameConfigurationKey) ?? DefaultPublicTopicSubscriptionName, createSubscriptionIfNotExists);
 }