[Azure Functions] Service Bus Trigger の再試行を試してみる

# 目的
Azure Functions では関数の実行が失敗しても、自動的に再試行してくれる機能が一部トリガーで提供されています。
今回は Service Bus トリガーの再試行を試してみます。

https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-bindings-error-pages?tabs=fixed-delay%2Cin-process&pivots=programming-language-csharp#retries

>再試行
関数で使用できる再試行には、個々のトリガー拡張機能の組み込みの再試行動作と再試行ポリシーの 2 種類があります。 次の表は、再試行をサポートするトリガーと、再試行動作が構成されている場所を示しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256703/016d12a0-6a69-8792-0540-f6846eed1670.png)

# 最大配信回数 (MaxDeliveryCount) について

Service Bus では、[最大配信数 (MaxDeliveryCount)](https://learn.microsoft.com/ja-jp/azure/service-bus-messaging/service-bus-dead-letter-queues#maximum-delivery-count) までキューに保管されたメッセージの配信が試行されます。
これにより、メッセージ受け取り側の Azure Functions で関数の実行が失敗しても、また再度キューからメッセージを取り出して試行することが出来ます。



ちなみに最大配信数 (MaxDeliveryCount) は、Service Bus の [概要] ブレード > 設定 の "最大配信数" より変更・確認できるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256703/29d31833-1b20-50d7-7a9e-db1d11c1efb3.png)


# 検証環境の構築
それではさっそくやってみましょう！
まずはこちらのドキュメントを参考に Service Bus キューと Service Bus Queue トリガーの関数を作成します。

[Azure portal を使用して Service Bus キューを作成する - Azure Service Bus | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/service-bus-messaging/service-bus-quickstart-portal#create-a-namespace-in-the-azure-portal)
[Visual Studio Code を使用して C# 関数を作成する - Azure Functions | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/azure-functions/create-first-function-vs-code-csharp?tabs=in-process#create-an-azure-functions-project)

# Azure Functions と Service Bus の連携
接続文字列を使って Azure Functions と Service Bus を連携させます。

Service Bus キューの共有アクセスポリシーからプライマリ接続文字列を取得します。
その後、Azure Functions のアプリケーション設定 (ローカルで実行する場合は local.settings.json) に任意の名前で値に接続文字列を登録しておきます。今回は "ServiceHub" という名前で設定しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256703/b1f408ef-51ad-4a0e-7657-7cd687d56bf0.png)


Service Bus キューと接続文字列を登録したアプリケーション設定の名前を、以下のように ServiceBusTrigger のプロパティに渡せば OK です。

```c#:ServiceBusQueueTrigger1.cs
    public class ServiceBusQueueTrigger1
    {
        [FunctionName("ServiceBusQueueTrigger1")]
        public void Run([ServiceBusTrigger("functions", Connection = "ServiceHub")]string myQueueItem, Int32 deliveryCount, ILogger log)
        {
            log.LogInformation($"C# ServiceBus queue trigger function processed message: {myQueueItem}"+" DeliveryCount:"+deliveryCount);
            throw new Exception("fail sample");
        }
    }
```

# 試してみる
Service Bus キューの [概要] から最大配信数を 13 回に変更し、 [Service Bus エクスプローラー] からメッセージを送信してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256703/1dac8d98-64f4-0a14-8bce-f5044692e74b.png)


その後、Azure Functions のSCM サイトから %HOME%\LogFiles\Application\Functions\Function 配下の関数実行ログを見てみると 13 回再実行されているのが分かります。

```
2022-10-19T07:26:58.576 [Information] C# ServiceBus queue trigger function processed message: service bus sample mesage DeliveryCount:1
2022-10-19T07:26:58.656 [Error] Executed 'ServiceBusQueueTrigger1' (Failed, Id=85402bbd-a655-47f6-95dc-52d6177bf6bd, Duration=72ms)
fail sample
2022-10-19T07:26:59.044 [Information] C# ServiceBus queue trigger function processed message: service bus sample message DeliveryCount:2
2022-10-19T07:26:59.082 [Error] Executed 'ServiceBusQueueTrigger1' (Failed, Id=e06e063a-9327-420d-8377-1747c34a959d, Duration=5ms)
fail sample
...(中略)...
2022-10-19T07:27:00.918 [Information] C# ServiceBus queue trigger function processed message: service bus sample message DeliveryCount:13
2022-10-19T07:27:00.939 [Error] Executed 'ServiceBusQueueTrigger1' (Failed, Id=b2fc3cd2-08fe-4ef3-94e4-c181bb1c5d1b, Duration=1ms)
fail sample
```

※ なお、最大配信数は「関数側がリトライされる回数」ではなく、「Service Bus 側で誰かにメッセージを読み取らせる回数」なので、メッセージを読み取るクライアントが複数いた場合には、必ずしも最大配信数分再実行されるわけではないので注意が必要です。


# まとめ
Service Bus トリガーの関数では、メッセージの再配信機能があるため関数の処理が途中で失敗しても再試行することが出来るので便利ですね。
ぜひ試してみてください～