Service Bus

How to set LockDuration on an Azure ServiceBus queue with PowerShell

Hi again,

Been doing some heavy integration work for a client, and we are using an Azure ServiceBus queue to hold our messages for a Logic App to process.

The workflow in the Logic App is complex and needs to query quite a few external services. The number of calls and a for-each loop means that the execution duration of the Logic App has, on many occasions, exceeded the default 1 minute lock duration of a ServiceBus queue.

I know that there is the ability to take a message off a ServiceBus queue, but for reasons which I’ll leave for maybe another blog post, we decided only to peek at the message and leave it on the queue for a re-execution if the Logic App processing failed for any reason.

So, being good DevOps as we all are, the deployment was scripted. However, I wanted to script the creation of the Azure resources individually, and not as the Resource Group deployment model that the Logic App template uses.

With the Azure Resource Manager PowerShell cmdlets, you use easily create a ServiceBus namespace and a queue.

However, it appears that there is a bug with the Set-AzureRMServiceBusQueue cmdlet in that neither the LockDuration nor the MaxDeliveryCount properties of a ServiceBus queue can be set to anything other than their default values.

(PowerShell snippet)
# Check if queue already exists
$queueName = 'myQueueName'
$currentQ = Get-AzureRmServiceBusQueue -ResourceGroup $resourceGroupName -NamespaceName $servicebusNamespace -QueueName $queueName;
if($currentQ)
{
 Write-Host "The queue $queueName already exists";
}
else
{
 Write-Host "The $queueName queue does not exist.";
 Write-Host "Creating the $queueName queue";
 New-AzureRmServiceBusQueue -ResourceGroup $resourceGroupName -NamespaceName $servicebusNamespace -QueueName $queueName -EnablePartitioning $False;
 $currentQ = Get-AzureRmServiceBusQueue -ResourceGroup $resourceGroupName -NamespaceName $servicebusNamespace -QueueName $queueName;
 Write-Host "The $queueName queue in Resource Group $resourceGroupName has been successfully created.";
}
# Set queue properties
$currentQ.DeadLetteringOnMessageExpiration = $True;
$currentQ.MaxDeliveryCount = 10;
$currentQ.MaxSizeInMegabytes = 1024;
$currentQ.LockDuration = 300;

Set-AzureRmServiceBusQueue -ResourceGroup $resourceGroupName -NamespaceName $servicebusNamespace -QueueName $queueName -QueueObj $currentQ;

 

For LockDuration, I’ve even tried the different formats that I know of;

  • “00:05:00”
  • “PT05S”
  • 300, either as integer or string, for 300 seconds

None of these formats appeared to make any difference to the LockDuration property!!!

I carefully checked the PowerShell output from the Set-AzureRmServiceBusQueue call and noticed that the LockDuration property was blank! Oh no! Something is not right here!

AzureServiceBusQueueLockDuration_NotSet

 

Solution:

To change the LockDuration of a ServiceBus queue, you need to use the Microsoft.ServiceBus assembly in your PowerShell script and use its NamespaceManager class. I placed the assembly in the same folder as the PowerShell script.

(PowerShell snippet)
Add-Type -Path ".\Microsoft.ServiceBus.dll"

# Need to get SAS token for "RootManageSharedAccessKey" on Service Bus itself
$keys = Get-AzureRmServiceBusNamespaceKey -ResourceGroup $resourceGroupName -NamespaceName $serviceBusNamespace -AuthorizationRuleName "RootManageSharedAccessKey"
$serviceBusConnectionString = $keys.PrimaryConnectionString

# LockDuration is a TimeSpan type. Set it to 5 minutes.
$lockDuration = [System.TimeSpan]::FromSeconds(300)

$queueName = 'myQueueName'
$currentQ = New-Object -TypeName Microsoft.ServiceBus.Messaging.QueueDescription -ArgumentList $queueName

# Check if the queue already exists
$NamespaceManager = [Microsoft.ServiceBus.NamespaceManager]::CreateFromConnectionString($serviceBusConnectionString);
if ($NamespaceManager.QueueExists($queueName))
{
 Write-Host "The queue '$queueName' already exists"
 Write-Host "Ensuring '$queueName' properties"
 $currentQ = $NamespaceManager.GetQueue($queueName);
 $currentQ.LockDuration = $lockDuration
 $currentQ.EnablePartitioning = $False
 $currentQ.EnableDeadLetteringOnMessageExpiration = $True
 $currentQ.MaxDeliveryCount = 10
 $currentQ.MaxSizeInMegabytes = 1024 
 $currentQ.EnableExpress = $False
 $currentQ.EnableBatchedOperations = $True 
 $currentQ.RequiresSession = $False 
 $currentQ.RequiresDuplicateDetection = $False
 $NamespaceManager.UpdateQueue($currentQ);
}
else
{
 Write-Host "The '$queueName' queue does not exist"
 Write-Host "Creating the '$queueName' queue"
 $currentQ = New-Object -TypeName Microsoft.ServiceBus.Messaging.QueueDescription -ArgumentList $queueName
 $currentQ.LockDuration = $lockDuration
 $currentQ.EnablePartitioning = $False
 $currentQ.EnableDeadLetteringOnMessageExpiration = $True
 $currentQ.MaxDeliveryCount = 10
 $currentQ.MaxSizeInMegabytes = 1024 
 $currentQ.EnableExpress = $False
 $currentQ.EnableBatchedOperations = $True 
 $currentQ.RequiresSession = $False 
 $currentQ.RequiresDuplicateDetection = $False

 $NamespaceManager.CreateQueue($currentQ);
 Write-Host "The $queueName queue in Resource Group $resourceGroupName has been successfully created.";
}

 

Now, when you check the LockDuration property in the output, you see that the property is now correctly set.

AzureServiceBusQueueLockDuration_CorrectlySet

A bug in the Set-AzureRmServiceBusQueue cmdlet perhaps ….

Until next tip… be good!