Azure Function and .NET 5: How to retry with Queue Trigger
Tags: azure, function, queue, dotnet
Published: 2021-05-10 07:23:04

Any program may fail at some point, and we need to prepare for it. I will explain how we can retry Function App with Queue trigger.

# Poison Queue

By default, the function app retries five times before give-up processing the queue item. Then, it sends the item to **Poison queue** so that developer can take a look later.

There are many reasons why it failed to process it, but most of the time, the item itself has issue, such as unexpected format of data.

Let's check the behavior.

## Create Storage Queue

I use local storage emulator this time.

1\. Make sure to run **Azure Storage Emulator**, and open Storage Explorer to connect to local storage queue.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kamig79iytp6bcyw6o7t.png)

2\. Add new queue "testqueue".

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dadxtp7kocsptm1iuwk0.png)
 
## Create Queue Trigger function

1\. Create new folder, and new function in it.

```shell
mkdir queueretryfunc
cd queueretryfunc
func init --workder-runtime dotnetIsolated
func new -n queueretryfunc
```

2\. Select **QueueTrigger**.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iqohljhsl8i7mw99crrt.png)
 
3\. Open with Visual Studio Code.

```shell 
code .
```
4\. Open queuetryfunc.cs file and update QueueTrigger properties.

```csharp
public static void Run([QueueTrigger("testqueue", Connection = "QueueConnectionString")] string myQueueItem,
            FunctionContext context)
```

5\. Open local.settings.json and add QueueConnectionString variable. Enter the appropriate value.

```json
{
    "IsEncrypted": false,
    "Values": {
        "AzureWebJobsStorage": "UseDevelopmentStorage=true",
        "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
        "QueueConnectionString":"[your connection string]"
    }
}
```

6\. Back to queuetryfunc.cs and update the run method to simply return Exception.

```csharp
using System;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;

namespace queueretryfunc
{
    public static class queueretryfunc
    {
        [Function("queueretryfunc")]
        public static void Run([QueueTrigger("testqueue", Connection = "QueueConnectionString")] string myQueueItem,
            FunctionContext context)
        {
           throw new Exception();
        }
    }
}
```

## Test it!

1\. Start function by func start.

```shell
func start
```
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/873rl3dy5ur6dkh19zr3.png)

2\. Create new queue item in storage.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cvyikq0ojrbkenhq2lbz.png)


3\. We can see the exception five times in the log. It indicates that the item was moved to poison queue.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g1l1zlxxso03p5kyoiut.png)


4\. Confirm that there is new queue and the created item in it.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/69inhdek37z3cf7hpgo8.png)

# Change time out and retry count

As we saw, the function immediately process the item five times, without any break, which may not be ideal situation in real scenario.

Let's change some settings to control the behavior.

## Update host.json

To control the queue trigger behavior, we can update host.json.

1\. Open host.json and update as below. This indicates we want to wait five seconds before next retry, and we only retry three times before sending the item to poison queue.

```json
{
    "version": "2.0",
    "logging": {
        "applicationInsights": {
            "samplingSettings": {
                "isEnabled": true,
                "excludedTypes": "Request"
            }
        }
    },
    "extensions": {
        "queues": {
            "visibilityTimeout": "00:00:05",
            "maxDequeueCount": 3
        }
    }
}
```

2\. Run the function again, and add new item in the queue.

3\. Then, check the log to see there is more than five seconds intervals between each Exception, and it retries three times only.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l3vq5l3je1sqy8shd9xe.png)
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jd7pcyuvu40tzx9f2ovj.png)
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0clo5tr04e9qkk5vvenj.png) 
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2eoliqjgnzso6xf0dp06.png)
  
# Summary

It's quite easy to control the behavior only if we know where to update. See [here](https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-storage-queue#hostjson-settings) for complete list and detail explanation of the settings.