public async Task EnsureSubscriptionIsSetup(string subscriptionName)
        {
            try
            {
                // The hash lookup works only when this class is registered in DI as a singleton
                if (subscriptionsThatHaveBeenSetup.Contains(subscriptionName))
                {
                    return;
                }

                subscriptionsThatHaveBeenSetup.Add(subscriptionName);
                if (!await managementClient.SubscriptionExistsAsync(topicName, subscriptionName))
                {
                    await managementClient.CreateSubscriptionAsync(new SubscriptionDescription(topicName, subscriptionName), MakeRule(subscriptionName));
                }
                else
                {
                    // The default rule is to accept everything, so delete it and replace it with the subscriptionName filter
                    await managementClient.DeleteRuleAsync(topicName, subscriptionName, "$Default");

                    await managementClient.CreateRuleAsync(topicName, subscriptionName, MakeRule(subscriptionName));
                }
            }
            catch (Exception e)
            {
                logger.LogError(e, $"Error setting up subscription for subscriptionName: {subscriptionName}");
            }
        }
        /// <summary>
        /// Ensures the subscription filter exists.
        /// </summary>
        /// <param name="manager">The manager.</param>
        /// <param name="topicName">Name of the topic.</param>
        /// <param name="subscriptionName">Name of the subscription.</param>
        /// <param name="filter">The filter.</param>
        /// <returns>Task&lt;RuleDescription&gt;.</returns>
        private static async Task <RuleDescription> EnsureSubscriptionFilter(ManagementClient manager, string topicName, string subscriptionName, KeyValuePair <string, string> filter)
        {
            // Get the rule, if it doesn't exist then create it.
            RuleDescription rule;
            var             ruleName       = filter.Key;
            var             ruleExpression = filter.Value;

            try
            {
                rule = await manager.GetRuleAsync(topicName, subscriptionName, ruleName);
            }
            catch (Exception)
            {
                // Has failed as the filter rule does not exist, therefore, create!

                // And go ahead, create the rule.
                rule = await manager.CreateRuleAsync(topicName, subscriptionName, new RuleDescription { Name = ruleName, Filter = new SqlFilter(ruleExpression) });

                try
                {
                    // If we're applying a rule it means we DON'T want the default rule to exist.  Therefore, remove.
                    await manager.DeleteRuleAsync(topicName, subscriptionName, "$Default");
                }
                catch (Exception)
                {
                    // Do nothing.
                }
            }

            return(rule);
        }
Exemple #3
0
        public async Task <SubscriptionDescriptionWithRuleDto> CreateSubscriptionWithRuleAsync(string topicName, string subsName, RuleDescription rule)
        {
            var subs = await _managementClient
                       .CreateSubscriptionAsync(topicName, subsName);

            await _managementClient.DeleteRuleAsync(topicName, subsName, RuleDescription.DefaultRuleName);

            await _managementClient.CreateRuleAsync(topicName, subsName, rule);

            _logger.LogInformation($"Created Subscription {subsName} with a Rule named {rule.Name} for Topic {topicName}");

            var correlationFilter  = ((CorrelationFilter)rule.Filter);
            var ruleDescriptionDto = new RuleDescriptionDto()
            {
                Name   = rule.Name,
                Filter = new CorrelationFilterDto()
                {
                    Label            = correlationFilter.Label,
                    ContentType      = correlationFilter.ContentType,
                    CorrelationId    = correlationFilter.CorrelationId,
                    MessageId        = correlationFilter.MessageId,
                    ReplyTo          = correlationFilter.ReplyTo,
                    ReplyToSessionId = correlationFilter.ReplyToSessionId,
                    SessionId        = correlationFilter.SessionId,
                    To = correlationFilter.To
                }
            };

            return(new SubscriptionDescriptionWithRuleDto(subs, ruleDescriptionDto));
        }
Exemple #4
0
        private static async Task UpdateSubscriptionRules <TPayload>(
            ManagementClient managementClient,
            string channelName,
            string subscriptionName,
            RuleDescription ruleDescription,
            IMessageFactory <TPayload> messageFactory)
            where TPayload : class, IReceivedServiceBusMessage
        {
            var currentRules = await managementClient.GetRulesAsync(channelName, subscriptionName);

            if (currentRules.All(rule => ParseRuleName(rule) < messageFactory.CurrentVersion))
            {
                // First we add a rule so new messages can qualify
                await managementClient.CreateRuleAsync(channelName, subscriptionName, ruleDescription)
                .IgnoreRaceConditionException <MessagingEntityAlreadyExistsException>();

                // Remove each rule that are older than the one we just added
                currentRules = await managementClient.GetRulesAsync(channelName, subscriptionName);

                foreach (var rule in currentRules)
                {
                    if (ParseRuleName(rule) < messageFactory.CurrentVersion)
                    {
                        await managementClient.DeleteRuleAsync(channelName, subscriptionName, rule.Name)
                        .IgnoreRaceConditionException <MessagingEntityNotFoundException>();
                    }
                }
            }
        }
        public async Task Subscribe(Type eventType, ContextBag context)
        {
            await CheckForManagePermissions().ConfigureAwait(false);

            var ruleName = eventType.FullName.Length > maxNameLength?ruleShortener(eventType.FullName) : eventType.FullName;

            var sqlExpression = $"[{Headers.EnclosedMessageTypes}] LIKE '%{eventType.FullName}%'";
            var rule          = new RuleDescription(ruleName, new SqlFilter(sqlExpression));

            var client = new ManagementClient(connectionStringBuilder, tokenProvider);

            try
            {
                var existingRule = await client.GetRuleAsync(topicPath, subscriptionName, rule.Name).ConfigureAwait(false);

                if (existingRule.Filter.ToString() != rule.Filter.ToString())
                {
                    rule.Action = existingRule.Action;

                    await client.UpdateRuleAsync(topicPath, subscriptionName, rule).ConfigureAwait(false);
                }
            }
            catch (MessagingEntityNotFoundException)
            {
                try
                {
                    await client.CreateRuleAsync(topicPath, subscriptionName, rule).ConfigureAwait(false);
                }
                catch (MessagingEntityAlreadyExistsException)
                {
                }
            }

            await client.CloseAsync().ConfigureAwait(false);
        }
Exemple #6
0
        public static Task Create(ManagementClient client, CommandArgument endpointName, CommandOption topicName, CommandOption subscriptionName, CommandArgument eventType, CommandOption ruleName)
        {
            var topicNameToUse        = topicName.HasValue() ? topicName.Value() : Topic.DefaultTopicName;
            var subscriptionNameToUse = subscriptionName.HasValue() ? subscriptionName.Value() : endpointName.Value;
            var eventToSubscribeTo    = eventType.Value;
            var ruleNameToUse         = ruleName.HasValue() ? ruleName.Value() : eventToSubscribeTo;
            var description           = new RuleDescription(ruleNameToUse, new SqlFilter($"[NServiceBus.EnclosedMessageTypes] LIKE '%{eventToSubscribeTo}%'"));

            return(client.CreateRuleAsync(topicNameToUse, subscriptionNameToUse, description));
        }
Exemple #7
0
        private async Task EnsureRulesUpToDate(SimpleSubscriptionDescription subscription, ManagementClient client, CancellationToken cancellationToken)
        {
            var newRules = BuildRules(subscription)
                           .ToArray();

            var existingRules = await client
                                .GetRulesAsync(settings.SafeEffectiveTopicName, subscription.SafeSubscriptionName(), cancellationToken : cancellationToken)
                                .ConfigureAwait(false);

            foreach (var newRule in newRules)
            {
                if (existingRules.Any(existingRule => existingRule.Name == newRule.Name))
                {
                    continue;
                }

                logger.LogInformation(
                    $"Rule {newRule.Name} doesn't exist on the subscription; creating the rule.");

                try
                {
                    await client
                    .CreateRuleAsync(settings.SafeEffectiveTopicName, subscription.SafeSubscriptionName(), newRule, cancellationToken)
                    .ConfigureAwait(false);
                }
                catch (MessagingEntityAlreadyExistsException)
                {
                    logger.LogWarning(
                        $"Rule {newRule.Name} has been created by another process that is competing with this process.");
                }
            }

            foreach (var existingRule in existingRules)
            {
                if (newRules.Any(newRule => newRule.Name == existingRule.Name))
                {
                    continue;
                }

                logger.LogInformation(
                    $"Rule {existingRule.Name} is no longer neeed; deleting the rule.");

                try
                {
                    await client
                    .DeleteRuleAsync(settings.SafeEffectiveTopicName, subscription.SafeSubscriptionName(), existingRule.Name, cancellationToken)
                    .ConfigureAwait(false);
                }
                catch (MessagingEntityNotFoundException)
                {
                    logger.LogWarning(
                        $"Rule {existingRule.Name} has already been removed by another process that is competing with this process.");
                }
            }
        }
        private void CreateNewSubscriptionRule(Type type, string endpointName, CancellationToken cancellationToken)
        {
            var manageClient    = new ManagementClient(connectionString);
            var ruleDescription = new RuleDescription
            {
                Filter = new SqlFilter($"[NServiceBus.EnclosedMessageTypes] LIKE '%{type.FullName}%'"),
                Name   = type.Name
            };

            manageClient.CreateRuleAsync(TopicPath, endpointName, ruleDescription, cancellationToken);
        }
Exemple #9
0
        private async Task CreateSubscriptionAsync(string connectionString, string topic, string subscription)
        {
            var client = new ManagementClient(connectionString);

            if (!await client.SubscriptionExistsAsync(topic, subscription))
            {
                await client.CreateSubscriptionAsync(topic, subscription);

                await client.CreateRuleAsync(topic, subscription, _rule);

                await _topicBus.SendAsync(_option.ServiceBus.TopicLog, $"Create Subscription {topic}");
            }
        }
Exemple #10
0
        public async Task SqlFilterParamsTest()
        {
            var client           = new ManagementClient(new ServiceBusConnectionStringBuilder(TestUtility.NamespaceConnectionString));
            var topicName        = Guid.NewGuid().ToString("D").Substring(0, 8);
            var subscriptionName = Guid.NewGuid().ToString("D").Substring(0, 8);

            try
            {
                await client.CreateTopicAsync(topicName);

                await client.CreateSubscriptionAsync(topicName, subscriptionName);

                SqlFilter sqlFilter = new SqlFilter(
                    "PROPERTY(@propertyName) = @stringPropertyValue " +
                    "AND PROPERTY(intProperty) = @intPropertyValue " +
                    "AND PROPERTY(longProperty) = @longPropertyValue " +
                    "AND PROPERTY(boolProperty) = @boolPropertyValue " +
                    "AND PROPERTY(doubleProperty) = @doublePropertyValue ")
                {
                    Parameters =
                    {
                        { "@propertyName",        "MyProperty" },
                        { "@stringPropertyValue", "string"     },
                        { "@intPropertyValue",               3 },
                        { "@longPropertyValue",             3L },
                        { "@boolPropertyValue",   true         },
                        { "@doublePropertyValue", (double)3.0  },
                    }
                };

                var rule = await client.CreateRuleAsync(topicName, subscriptionName, new RuleDescription("rule1", sqlFilter));

                Assert.Equal(sqlFilter, rule.Filter);

                await client.DeleteTopicAsync(topicName);
            }
            catch
            {
                await SafeDeleteTopic(client, topicName);

                throw;
            }
            finally
            {
                await client.CloseAsync();
            }
        }
Exemple #11
0
        public static async Task EnsureSubscriptionRuleExistsAsync(string topicName, string subscriptionName, RuleDescription ruleDescription)
        {
            var sbManagement = new ManagementClient(Configs.SbFailoverConnectionString);

            var rules = await sbManagement.GetRulesAsync(topicName, subscriptionName);

            var defaultRule = rules.SingleOrDefault(x => x.Name.Equals(RuleDescription.DefaultRuleName));

            if (defaultRule != null)
            {
                Console.WriteLine($"Removing subscription rule: {defaultRule.Name}");
                await sbManagement.DeleteRuleAsync(topicName, subscriptionName, defaultRule.Name);
            }

            if (!rules.Any(x => x.Name.Equals(ruleDescription.Name)))
            {
                Console.WriteLine($"Creating subscription rule: {ruleDescription.Name}");
                await sbManagement.CreateRuleAsync(topicName, subscriptionName, ruleDescription);
            }
        }
        private async Task UpdateSubscriptionRules <TMessageType>(
            string channelName,
            string subscriptionName,
            RuleDescription ruleDescription,
            IMessageHandler <TMessageType> messageHandler)
            where TMessageType : class, IMessageContract
        {
            var currentRules = await _managementClient.GetRulesAsync(channelName, subscriptionName);

            if (currentRules.All(rule => ParseRuleName(rule) < messageHandler.CurrentVersion))
            {
                try
                {
                    // First we add a rule so new messages can qualify
                    await _managementClient.CreateRuleAsync(channelName, subscriptionName, ruleDescription);
                }
                catch (MessagingEntityAlreadyExistsException)
                {
                    // noop
                }

                // Remove each rule that are older than the one we just added
                currentRules = await _managementClient.GetRulesAsync(channelName, subscriptionName);

                foreach (var rule in currentRules)
                {
                    if (ParseRuleName(rule) < messageHandler.CurrentVersion)
                    {
                        try
                        {
                            await _managementClient.DeleteRuleAsync(channelName, subscriptionName, rule.Name);
                        }
                        catch (MessagingEntityNotFoundException)
                        {
                            // noop
                        }
                    }
                }
            }
        }
Exemple #13
0
        public async Task CreateRuleAsync(string ruleName, string subscriptionName, string topicName)
        {
            if (string.IsNullOrWhiteSpace(ruleName))
            {
                throw new ArgumentException($"'{nameof(ruleName)}' cannot be null or empty.", nameof(ruleName));
            }
            if (string.IsNullOrWhiteSpace(topicName))
            {
                throw new ArgumentException($"'{nameof(topicName)}' cannot be null or empty.", nameof(topicName));
            }
            if (string.IsNullOrWhiteSpace(subscriptionName))
            {
                throw new ArgumentException($"'{nameof(subscriptionName)}' cannot be null or empty.", nameof(subscriptionName));
            }

            var topicExists = await TopicExistsAsync(topicName);

            if (!topicExists)
            {
                throw new TopicNotFoundException(topicName);
            }

            var subscriptionExists = await SubscriptionExistsAsync(subscriptionName, topicName);

            if (!subscriptionExists)
            {
                throw new SubscriptionNotFoundException(subscriptionName);
            }

            var ruleExists = await RuleExistsAsync(ruleName, subscriptionName, topicName);

            if (ruleExists)
            {
                throw new RuleAlreadyExistsException(ruleName);
            }

            await _client.CreateRuleAsync(topicName, subscriptionName, new RuleDescription(filter : new CorrelationFilter {
                Label = ruleName
            }, name : ruleName));
        }
Exemple #14
0
        public async Task CreateSubscription(string topicName, string subscriptionName, IList <Type> filters = null)
        {
            if (!await _managementClient.SubscriptionExistsAsync(topicName, subscriptionName))
            {
                // Configure Topic Settings.
                SubscriptionDescription topicDescription = new SubscriptionDescription(topicName, subscriptionName)
                {
                    EnableDeadLetteringOnMessageExpiration = true,
                    DefaultMessageTimeToLive = TimeSpan.FromDays(10),
                    AutoDeleteOnIdle         = TimeSpan.FromDays(1)
                };
                await _managementClient.CreateSubscriptionAsync(topicDescription);
            }

            if (filters != null && filters.Any())
            {
                IList <RuleDescription> rules = await _managementClient.GetRulesAsync(topicName, subscriptionName);

                if (rules.Any(x => x.Name == RuleDescription.DefaultRuleName))
                {
                    await _managementClient.DeleteRuleAsync(topicName, subscriptionName, RuleDescription.DefaultRuleName);
                }

                foreach (Type filter in filters)
                {
                    if (rules.Any(x => x.Name == filter.Name))
                    {
                        continue;
                    }

                    await _managementClient.CreateRuleAsync(topicName, subscriptionName,
                                                            new RuleDescription(filter.Name, new CorrelationFilter {
                        Label = filter.FullName
                    }));
                }
            }
        }
Exemple #15
0
        public async Task Subscribe(Type eventType, ContextBag context)
        {
            await CheckForManagePermissions().ConfigureAwait(false);

            var ruleName      = ruleNameFactory(eventType);
            var sqlExpression = sqlExpressionFactory(eventType);
            var rule          = new RuleDescription(ruleName, new SqlFilter(sqlExpression));

            var client = new ManagementClient(connectionStringBuilder, tokenProvider);

            try
            {
                var existingRule = await client.GetRuleAsync(topicPath, subscriptionName, rule.Name).ConfigureAwait(false);

                if (existingRule.Filter.ToString() != rule.Filter.ToString())
                {
                    rule.Action = existingRule.Action;

                    await client.UpdateRuleAsync(topicPath, subscriptionName, rule).ConfigureAwait(false);
                }
            }
            catch (MessagingEntityNotFoundException)
            {
                try
                {
                    await client.CreateRuleAsync(topicPath, subscriptionName, rule).ConfigureAwait(false);
                }
                catch (MessagingEntityAlreadyExistsException)
                {
                }
            }
            finally
            {
                await client.CloseAsync().ConfigureAwait(false);
            }
        }
Exemple #16
0
        public async Task CorrelationFilterPropertiesTest()
        {
            var topicName        = Guid.NewGuid().ToString("D").Substring(0, 8);
            var subscriptionName = Guid.NewGuid().ToString("D").Substring(0, 8);
            var client           = new ManagementClient(new ServiceBusConnectionStringBuilder(TestUtility.NamespaceConnectionString));

            try
            {
                await client.CreateTopicAsync(topicName);

                await client.CreateSubscriptionAsync(topicName, subscriptionName);

                var sClient = new SubscriptionClient(TestUtility.NamespaceConnectionString, topicName, subscriptionName);
                var filter  = new CorrelationFilter();
                filter.Properties.Add("stringKey", "stringVal");
                filter.Properties.Add("intKey", 5);
                filter.Properties.Add("dateTimeKey", DateTime.UtcNow);

                var rule = await client.CreateRuleAsync(topicName, subscriptionName, new RuleDescription("rule1", filter));

                Assert.True(filter.Properties.Count == 3);
                Assert.Equal(filter, rule.Filter);

                await client.DeleteTopicAsync(topicName);
            }
            catch
            {
                await SafeDeleteTopic(client, topicName);

                throw;
            }
            finally
            {
                await client.CloseAsync();
            }
        }
Exemple #17
0
        public async Task BasicRulesCrudTest()
        {
            var topicName        = Guid.NewGuid().ToString("D").Substring(0, 8);
            var subscriptionName = Guid.NewGuid().ToString("D").Substring(0, 8);
            var client           = new ManagementClient(new ServiceBusConnectionStringBuilder(TestUtility.NamespaceConnectionString));

            try
            {
                await client.CreateTopicAsync(topicName);

                await client.CreateSubscriptionAsync(
                    new SubscriptionDescription(topicName, subscriptionName),
                    new RuleDescription("rule0", new FalseFilter()));

                var sqlFilter = new SqlFilter("stringValue = @stringParam AND intValue = @intParam AND longValue = @longParam AND dateValue = @dateParam AND timeSpanValue = @timeSpanParam");
                sqlFilter.Parameters.Add("@stringParam", "string");
                sqlFilter.Parameters.Add("@intParam", (int)1);
                sqlFilter.Parameters.Add("@longParam", (long)12);
                sqlFilter.Parameters.Add("@dateParam", DateTime.UtcNow);
                sqlFilter.Parameters.Add("@timeSpanParam", TimeSpan.FromDays(1));
                var rule1 = new RuleDescription
                {
                    Name   = "rule1",
                    Filter = sqlFilter,
                    Action = new SqlRuleAction("SET a='b'")
                };
                await client.CreateRuleAsync(topicName, subscriptionName, rule1);

                var correlationFilter = new CorrelationFilter()
                {
                    ContentType      = "contentType",
                    CorrelationId    = "correlationId",
                    Label            = "label",
                    MessageId        = "messageId",
                    ReplyTo          = "replyTo",
                    ReplyToSessionId = "replyToSessionId",
                    SessionId        = "sessionId",
                    To = "to"
                };
                correlationFilter.Properties.Add("customKey", "customValue");
                var rule2 = new RuleDescription()
                {
                    Name   = "rule2",
                    Filter = correlationFilter,
                    Action = null
                };
                await client.CreateRuleAsync(topicName, subscriptionName, rule2);

                var rules = await client.GetRulesAsync(topicName, subscriptionName);

                Assert.True(rules.Count == 3);
                Assert.Equal("rule0", rules[0].Name);
                Assert.Equal(rule1, rules[1]);
                Assert.Equal(rule2, rules[2]);

                ((CorrelationFilter)rule2.Filter).CorrelationId = "correlationIdModified";
                var updatedRule2 = await client.UpdateRuleAsync(topicName, subscriptionName, rule2);

                Assert.Equal(rule2, updatedRule2);

                var defaultRule = await client.GetRuleAsync(topicName, subscriptionName, "rule0");

                Assert.NotNull(defaultRule);
                await client.DeleteRuleAsync(topicName, subscriptionName, "rule0");

                await Assert.ThrowsAsync <MessagingEntityNotFoundException>(
                    async() =>
                {
                    await client.GetRuleAsync(topicName, subscriptionName, "rule0");
                });

                await client.DeleteTopicAsync(topicName);
            }
            catch
            {
                await SafeDeleteTopic(client, topicName);

                throw;
            }
            finally
            {
                await client.CloseAsync();
            }
        }