2

With no luck, I tried configuring my ServiceBusClient to retry a message with a Fixed Delay of 10 seconds. I also tried Exponential retries configuration. However, the code is always retrying the message within a second or 2 and completely ignoring the configuration. It even ignores the MaxRetries and only retries 10 times, the value configured in Azure Portal for the queue. What am I doing wrong?

I am using The Azure.Messaging.ServiceBus library, NuGet package 7.0.0.

The code:

ServiceBusClient client = new ServiceBusClient(serviceBusConnectionString, new ServiceBusClientOptions()
            {
                RetryOptions = new ServiceBusRetryOptions()
                {
                    Mode = ServiceBusRetryMode.Fixed,
                    Delay = TimeSpan.FromSeconds(10),
                    MaxDelay = TimeSpan.FromMinutes(3),
                    MaxRetries = 30
                }
            });

ServiceBusProcessor processor = client.CreateProcessor(queueName, new ServiceBusProcessorOptions());

// throwing an exception in MyMessageHandlerAsync on purpose
// to test out the retries configuration
processor.ProcessMessageAsync += MyMessageHandlerAsync;

// The uncaught exception causes this method to execute. 
// Processing is attempted 10 times with
// virtually no delay between each attempt.
// After the 10th attempt, the message goes to deadletter,
// which is expected.
processor.ProcessErrorAsync += MyErrorHandler;

I'm adding more to this question after receiving the 1st response:

Currently, MyMessageHandlerAsync is:

    private async Task MyMessageHandlerAsync(EventArgs eventArgs)
    {
        var args = (ProcessMessageEventArgs)eventArgs;

        var body = args.Message.Body.ToString();
        
        // ...
        // process body
        // ...

        await args.CompleteMessageAsync(args.Message);
    }

How should I change the method's contents to retry a non-transient ServiceBusException? Please help provide the code where the TODOs are below:

    private async Task MyMessageHandlerAsync(EventArgs eventArgs)
    {
        var args = (ProcessMessageEventArgs)eventArgs;

        try
        {

            var body = args.Message.Body.ToString();
        
            // ...
            // process body
            // ...

            await args.CompleteMessageAsync(args.Message);
        }
        catch (ServiceBusException sbe)
        {
            if (sbe.IsTransiet)
            {
                // TODO: Is it correct that the exponential retry will work
                // here?  The one defined in the ServiceBusClient.
                // So, no code is needed here, just throw.
                throw;
            }
            else
            {
                // TODO: for non-transient, this is where the
                //       options in the ServiceBusClient don't apply.
                //       Is that correct?  How do I do an
                //       exponential retry here?
            }
        }
        catch (Exception e)
        {
            // TODO: same problem as else in first catch.
        }
    }
Jeremy Ray Brown
  • 1,499
  • 19
  • 23

1 Answers1

3

ServiceBusRetryOptions is intended to be used by the ASB client when there are transient errors that are not bubbled up to your code right away, i.e. an internal retry mechanism built into the client to perform retries on your behalf before exception is raised.

Use retry policy to specify to the ASB client how to deal with transient errors prior to giving up, not how many times a message handler throws error:

enter image description here

Harshita Singh
  • 4,590
  • 1
  • 10
  • 13
  • Thank you for your answer. I will look into this and see if I can get it to work properly. – Jeremy Ray Brown Jan 29 '21 at 19:15
  • Hi @singhh-msft, I added more to the question. Do you have another resource that can help? Thanks for the 1st resource. – Jeremy Ray Brown Jan 31 '21 at 20:39
  • This is a different question. Could you pls conclude this one and add another question for non transient error handling? I will look into it. – Harshita Singh Feb 01 '21 at 04:10
  • Hi @singhh-msft, I would rather leave this open, because my original question didn't have enough details. You've helped me get more details in it. I will upvote your response because of your help thus far. – Jeremy Ray Brown Feb 01 '21 at 12:48
  • 1
    For non transient errors you can use Polly library. It is very helpful. – Harshita Singh Feb 02 '21 at 14:26
  • Thank you, I will look into that @singhh-msft – Jeremy Ray Brown Feb 02 '21 at 19:49
  • Let me know if you dont find any samples/documentation. – Harshita Singh Feb 03 '21 at 04:36
  • Does this answer your query? – Harshita Singh Feb 03 '21 at 13:12
  • Yes, your answers help me take the next steps. The developers and I are investigating possible solutions. We are considering leaving the default retry mechanism in place and creating a background job that automatically processes dead letter messages. Since I don't have more time to investigate, I will leave this question open and probably add a bounty to get additional answers to fill in the gaps in the code in the question – Jeremy Ray Brown Feb 03 '21 at 17:35
  • This didnt answer, imo. I see no effect what so ever of the ServiceBusRetryOptions, like Jemery said. – Ted Aug 09 '23 at 11:07