0

Using the older "Windows.Azure.ServiceBus" library, I am able to setup a SqlFilter that takes as its parameters a TimeSpan, but when I try the same using the "Microsoft.Azure.ServiceBus" library it fails with the following error:

Object is not of supported type: TimeSpan. Only following types are supported through HTTP: string,int,long,bool,double,DateTime

What I am trying to do:

  1. I want to have 2 subscriptions on my topic (highPriority, normalPriority)
  2. Messages have a user property called "StartDate"
  3. If StartDate <= 1 day, then it should go to highPriority subscription, else it should go to normalPriority. [i.e (StartDate - sys.EnqueuedDateTimeUtc) <= 24 hours].

Code that works (when using the older .net-framework Windows.Azure.ServiceBus package):

SqlFilter highMessagesFilter =
       new SqlFilter("(StartDate-sys.EnqueuedTimeUtc) <= @TimeSpanImmediateWindow");
highMessagesFilter.Parameters.Add("@TimeSpanImmediateWindow", TimeSpan.FromDays(1));

var subscription = SubscriptionClient.CreateFromConnectionString(connectionString,topicName, subName1);
subscription.RemoveRule(RuleDescription.DefaultRuleName);
subscription.AddRule(new RuleDescription()
{
    Name = RuleDescription.DefaultRuleName,
    Filter = highMessagesFilter,
    Action = new SqlRuleAction("set priorityCalc = (StartDate-sys.EnqueuedTimeUtc)")
});

Where as, this code (using: Microsoft.Azure.ServiceBus) doesnt work:

var filter = new SqlFilter("(StartDate-sys.EnqueuedTimeUtc) <= @TimeSpanHoursImmediateWindow");
filter.Parameters.Add("@TimeSpanHoursImmediateWindow",TimeSpan.FromDays(1));

var ruleDescription = new RuleDescription
{
    Filter = filter,
    Action = new SqlRuleAction(@"
        SET HighPriority = TRUE;
        SET Window = StartDate - sys.EnqueuedTimeUtc
        "),
    Name = RuleDescription.DefaultRuleName,

};

await managementClient.UpdateRuleAsync(topicPath,subscriptionName,ruleDescription);

The above code throws the following error:

Object is not of supported type: TimeSpan. Only following types are supported through HTTP: string,int,long,bool,double,DateTime

If instead of managementClient.UpdateRuleAsync, I try using the following code:

var subClient = new SubscriptionClient(connectionString, topicPath, subscriptionName);

await subClient.RemoveRuleAsync(RuleDescription.DefaultRuleName);
await subClient.AddRuleAsync(ruleDescription);

It fails, with the following error (ServiceBusException):

Message The service was unable to process the request; please retry the operation. For more information on exception types and proper exception handling, please refer to http://go.microsoft.com/fwlink/?LinkId=761101

The microsoft link is to a list of exceptions, and FilterException, but its not!

Here is the stack trace of the 2nd exception:

at Microsoft.Azure.ServiceBus.Amqp.AmqpSubscriptionClient.OnAddRuleAsync(RuleDescription description) in C:\source\azure-service-bus-dotnet\src\Microsoft.Azure.ServiceBus\Amqp\AmqpSubscriptionClient.cs:line 132 at Microsoft.Azure.ServiceBus.SubscriptionClient.AddRuleAsync(RuleDescription description) in C:\source\azure-service-bus-dotnet\src\Microsoft.Azure.ServiceBus\SubscriptionClient.cs:line 499 at UserQuery.Main() in C:\Users\XXXX\AppData\Local\Temp\LINQPad6_quhgasgl\niqvie\LINQPadQuery.cs:line 82

So my questions are:

  1. Can I use TimeSpan parameters using .net standard library? or will I have to use the older .net framework library if I wanted to use TimeSpans.

  2. Is there a better way to implement what I am trying to do, a way that would work with the newer .net standard library? (FYI: I thought about sending the calculation as the parameter (decimal) and then the parameter would be a double, instead of a TimeSpan). And in fact, thats what I might end up doing.

Raj Rao
  • 8,872
  • 12
  • 69
  • 83

1 Answers1

1

If the library is throwing an exception stating that TimeSpan is not a supported type, then it's pretty much what you have. Note that the .NET Standard client has two implementations, the ManagementClient and some operations via entity clients, such as subscription client. The latter is implemented using AMQP. ManagementClient is entirely based on HTTP. While it would be ideal to use the AMQP implementation, it's incomplete. I would recommend relying on the ManagementClient. This is likely the reason why modifying rules using a subscription client is throwing an exception.

Regarding a better way - your idea sounds right. As long as it's not a type that the new client doesn't accept. Also, you can raise an issue with the library team at https://github.com/Azure/azure-sdk-for-net/issues if you'd like to know the reason why TimeSpan is no longer supported.

Sean Feldman
  • 23,443
  • 7
  • 55
  • 80