2
votes

I'm using a Service Bus queue with Sessions enabled and I'm sending 5 messages with the same SessionId. My receiving code uses AcceptMessageSessionAsync to get a session lock so that it will receive all the messages for that session. It then uses session.ReceiveBatchAsync to try and get all the messages for the session. However, it only seems to get the first message, then when another attempt is made, it gets all the others. You should be able to see that there is a gap of almost a minute between the two batches even though all these messages were sent at once:

Session started:AE8DC914-8693-4110-8BAE-244E42A302D5
Message received:AE8DC914-8693-4110-8BAE-244E42A302D5_1_08:03:03.36523
Session started:AE8DC914-8693-4110-8BAE-244E42A302D5
Message received:AE8DC914-8693-4110-8BAE-244E42A302D5_2_08:03:04.22964
Message received:AE8DC914-8693-4110-8BAE-244E42A302D5_3_08:03:04.29515
Message received:AE8DC914-8693-4110-8BAE-244E42A302D5_4_08:03:04.33959
Message received:AE8DC914-8693-4110-8BAE-244E42A302D5_5_08:03:04.39587

My code to process these is a function in a WebJob:

[NoAutomaticTrigger]
public static async Task MessageHandlingLoop(TextWriter log, CancellationToken cancellationToken)
{
    var connectionString = ConfigurationManager.ConnectionStrings["ServiceBusListen"].ConnectionString;
    var client = QueueClient.CreateFromConnectionString(connectionString, "myqueue");

    while (!cancellationToken.IsCancellationRequested)
    {
        MessageSession session = null;

        try
        {
            session = await client.AcceptMessageSessionAsync(TimeSpan.FromMinutes(1));

            log.WriteLine("Session started:" + session.SessionId);
            foreach (var msg in await session.ReceiveBatchAsync(100, TimeSpan.FromSeconds(5)))
            {
                log.WriteLine("Message received:" + msg.MessageId);
                msg.Complete();
            }
        }
        catch (TimeoutException)
        {
            log.WriteLine("Timeout occurred");
            await Task.Delay(5000, cancellationToken);
        }
        catch (Exception ex)
        {
            log.WriteLine("Error:" + ex);
        }
    }
}

This is called from my WebJob Main using:

JobHost host = new JobHost();
host.Start();
var task = host.CallAsync(typeof(Functions).GetMethod("MessageHandlingLoop"));
task.Wait();
host.Stop();

Why don't I get all my messages in the first call of ReceiveBatchAsync?

1

1 Answers

2
votes

This was answered in the MSDN forum by Hillary Caituiro Monge: https://social.msdn.microsoft.com/Forums/azure/en-US/9a84f319-7bc6-4ff8-b142-4fc1d5f1e2fa/service-bus-session-receivebatchasync-only-receiving-1-message?forum=servbus

Service Bus does not guarantee you will receive the message count you specify in receive batch even if your queue has them or more. Having say that, you can change your code to try to get the 100 messages in the first call, buy remember that your application should not assume that as a guaranteed behavior.

Below this line of code varclient = QueueClient.CreateFromConnectionString(connectionString, "myqueue");
add client.PrefetchCount = 100;

The reason that you are getting only 1 message at all times in the first call is due to that when you accept a session it may be also getting 1 prefetched message with it. Then when you do receive batch, the SB client will give you that 1 message.

Unfortunately I found that setting the PrefetchCount didn't have an affect, but the reason given for only receiving one message seemed likely so I accepted it as the answer.