Is there support for queueClient CompleteBatch method?
https://docs.microsoft.com/en-us/dotnet/api/microsoft.servicebus.messaging.queueclient.completebatch?view=azure-dotnet
If not is there a workaround to improve performance while using peekLock receive mode?
@gwintca Can you share some more details on the performance hit you are seeing that a feature of completing messages in a batch would help in? If you could share a code snippet of how you are using the receiver and settling messages would also help in this discussion.
Meanwhile we will look into the link that you shared above
cc @richardpark-msft
Thanks for asking @gwintca.
Service doesn't support completing (or settling) a batch of messages. So, we won't be supporting the CompleteBatch (as of now at least).
And regarding the CompleteBatch method that was pointed out, it was from the older Service Bus SDK for .NET.
Summarizing the things I learned from @JoshLove-msft on the CompleteBatch method:
CompleteBatch is called by the user with a set of locktokens, the library internally calls Complete individually for each of the locktokens(messages). Basically, looping over the complete method for the messages.Completing messages individually is the only way you'll be able to complete the messages in the "peekLock" mode(in both V1 and V7 service-bus JS SDKs).
As @ramya-rao-a already asked, please let us know the kind of issues that you see and preferably a code sample representing your scenario.
Thanks for your replies. I ended up running complete() in parallel which improved the performance:
await Promise.all(
messages.map(async m => {
await m.complete();
}),
);
Yes, that is what we were about to recommend once we saw your code snippets.
Also, I believe you can remove the async/awaits in there
await Promise.all(messages.map(m => m.complete()));
While we have you here, can you share which API on the receiver are you using to receive messages? The one that gives you a promise that resolves to a batch of messages, or the async iterator or the one where you register handlers. And can you share the reason for your choice?
I'm using receiveMessages(number, undefined | number) - the one that resolves to a batch of messages. The reason for my choice is I eventually would need to save message data to a database and I would prefer to do it in one query -
INSERT INTO table (col1, col2, ...) VALUES
(val1, val2, ...),
(val11, val12, ...);
so using something like receiveMessages(100, 60) would give me "batching receiver". I didn't find any other way to receive message batch.
I also have a question about using handlers and specifically about the sample code in https://github.com/Azure/azure-sdk-for-js/blob/master/sdk/servicebus/service-bus/samples-v1/typescript/src/receiveMessagesStreaming.ts
Why does it create and close receiver inside a loop? Wouldn't it be more performant to create receiver only once and keep it open?
Also this line
let enableReceiverRecovery = true;
suggests enableReceiverRecovery will be changed inside the code but it's not. Is there something missing?
Please let me know if above questions should be put in a separate post.
Thanks again for your help.
Why does it create and close receiver inside a loop?
That specific sample was not meant to use directly as it is. The intention behind the sample is to show one way of how the user can manage the receiver if a "retryable" error is seen.
Wouldn't it be more performant to create receiver only once and keep it open?
You're right about creating the receiver once and keeping it open forever to receive the messages, that is what the registerMessageHandler is meant to be.
In the sample, with the looping, when a retryable error is observed, it closes the receiver and creates a new one. At any given moment, there would only be a single receiver receiving the messages.
In general with the registerMessageHandler, the errors observed(also passed on to the onError handler) such as the connection errors, or any transient issues, or even for the network failures, SDK attempts recovery gracefully and continues receiving the messages once the receiver comes back up.
Regarding the enableReceiverRecovery variable, say a certain failure/error occurs more than often, it might be hinting at a deeper issue, which is when this variable can be set to false to break out of the loop and to notify the user about the issue from the application.
On a related note, I'm inclining to update the sample to keep things clearer.
/cc @richardpark-msft
Thanks @HarshaNalluru!
@gwintca Thanks for engaging with us. We are currently wrapping up our work on the next version of the Service Bus package. We would love to hear your feedback on the API design changes we have done there. If you are interested please try out version 7.0.0-preview.7 of the same @azure/service-bus package and let us know what you think via another GitHub issue. Here is a migration guide that lists key differences
Most helpful comment
Yes, that is what we were about to recommend once we saw your code snippets.
Also, I believe you can remove the async/awaits in there
await Promise.all(messages.map(m => m.complete()));While we have you here, can you share which API on the receiver are you using to receive messages? The one that gives you a promise that resolves to a batch of messages, or the async iterator or the one where you register handlers. And can you share the reason for your choice?