Azure Service Bus 配信不能キュー (DLQ) を REST API で操作したい

# Azure Service Bus

フルマネージドなメッセージング サービスです。
メッセージングとは、システム間でのメッセージのやり取りです。

詳しくは、以下のドキュメントをご覧ください。

https://learn.microsoft.com/ja-jp/azure/service-bus-messaging/service-bus-messaging-overview?WT.mc_id=AZ-MVP-5003113

https://learn.microsoft.com/ja-jp/azure/service-bus-messaging/service-bus-queues-topics-subscriptions?WT.mc_id=AZ-MVP-5003113

Azure でキュー機能を提供するサービスとして、Service Bus の他に [Azure Storage キュー](https://learn.microsoft.com/ja-jp/azure/storage/queues/storage-queues-introduction?WT.mc_id=AZ-MVP-5003113)があります。

Storage キューと Service Bus キューの違いや使い分けについては、以下のドキュメントにまとまっていますので、ご参照ください。

https://learn.microsoft.com/ja-jp/azure/service-bus-messaging/service-bus-azure-and-service-bus-queues-compared-contrasted?WT.mc_id=AZ-MVP-5003113


# 配信不能キュー

Azure Service Bus キューとトピック サブスクリプションには、配信不能キュー (DLQ : dead-letter queue) というセカンダリ キューが提供されます。この配信不能キューの目的は、受信者に配信できないメッセージや受信者が処理できなかったメッセージを保持することです。
なお、配信不能キュー内のメッセージは、自動的に削除されることはありません。

https://docs.microsoft.com/ja-jp/azure/service-bus-messaging/service-bus-dead-letter-queues?WT.mc_id=AZ-MVP-5003113


## メッセージを配信不能キューに移動させるには

メインとなるキューの対象のメッセージが以下のいずれかの条件を満たすと、配信不能キューに移動させることができます。

- **メッセージの最大配信数を超過した場合**

メッセージの配信できる回数には上限 (既定値 10 回) があり、この配信回数の上限を超えると対象のメッセージは配信不能キューに移動します。

メッセージがピーク/ロック状態で配信されて明示的に削除されたか、ロックが期限切れになった場合に配信回数がカウントアップします。

- **メッセージの有効期限が切れた場合**

メッセージには有効期限が設けられており、この有効期限が切れたメッセージは配信不能キューに移動します。なお、この操作は明示的にこの操作を有効にした場合のみです。

有効期限が切れたメッセージを自動的に配信不能キューに移動させるには、以下のドキュメントの手順に従って設定してください。

https://learn.microsoft.com/ja-jp/azure/service-bus-messaging/enable-dead-letter?WT.mc_id=AZ-MVP-5003113


## 配信不能キューを REST API で操作したい

まず、メッセージを直接配信不能キューに送信することはできません。[前述した](#%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%82%92%E9%85%8D%E4%BF%A1%E4%B8%8D%E8%83%BD%E3%82%AD%E3%83%A5%E3%83%BC%E3%81%AB%E7%A7%BB%E5%8B%95%E3%81%95%E3%81%9B%E3%82%8B%E3%81%AB%E3%81%AF)とおり、メインとなるキューのメッセージがある条件に満たした場合に配信不能キューに移動します。

よって、配信不能キューに格納されたメッセージに対する操作 (受信アクセス) を行うことができます。


### アクセス制御

ここでは、Azure リソースのマネージド ID、または Azure AD に登録したアプリケーションのサービス プリンシパルにアクセス許可を付与することを想定します。

https://learn.microsoft.com/ja-jp/azure/service-bus-messaging/service-bus-managed-service-identity?WT.mc_id=AZ-MVP-5003113

https://learn.microsoft.com/ja-jp/azure/service-bus-messaging/authenticate-application?WT.mc_id=AZ-MVP-5003113

配信不能キューのメッセージを操作するためには、(組み込みロールでいうと)「[Azure Service Bus データ受信者](https://learn.microsoft.com/ja-jp/azure/role-based-access-control/built-in-roles?WT.mc_id=AZ-MVP-5003113#azure-service-bus-data-receiver)」ロールを Service Bus 名前空間に割り当てて、アクセス許可すれば良いでしょう。

そして、アクセス元でアクセス トークンを取得し、リクエスト ヘッダーに取得したアクセス トークンを含めて Service Bus の各 REST API にリクエストします。

```http:Request&#x20;Headers
Authorization: Bearer <アクセス トークン>
```

### 配信不能キューのパスは？

ドキュメントには、配信不能キューを操作するためのパスが明確に書かれおらず、以下の構文を使うんだとしか書かれていません...:cry:

```http
<queue path>/$deadletterqueue
<topic path>/Subscriptions/<subscription path>/$deadletterqueue
```

https://learn.microsoft.com/ja-jp/azure/service-bus-messaging/service-bus-dead-letter-queues?WT.mc_id=AZ-MVP-5003113#path-to-the-dead-letter-queue

さて、配信不能キューのメッセージを操作するための実際のパスはどのようなものなのでしょうか？:rolling_eyes:

ということで、以下より、筆者が心が折れることなく調べた結果をシェアします。:muscle:

なお、この件は公式ドキュメントに載っておらず検証結果から見出したものなので、今後の仕様変更などにより変更されるかもしれません。ご了承ください。

※トピック サブスクリプションについては調べていません。:bow:
　(同じノリでできると思いますけど)


### 配信不能キューからメッセージを受信して削除

```http:Receive&#x20;and&#x20;Delete&#x20;Message&#x20;(Destructive&#x20;Read)
DELETE https://{serviceNamespace}.servicebus.windows.net/{queuePath}/$DeadLetterQueue/messages/head
```

| パラメーター | 設定値 |
|:-|:-|
| ```{serviceNamespace}``` | Service Bus の名前空間。 |
| ```{queuePath}``` | Service Bus のキュー。 |

リクエスト ヘッダー・ボディ、レスポンス コード・ヘッダー・ボディについては、メイン キューでの「[メッセージを受信して削除する (破壊読み取り)](https://learn.microsoft.com/ja-jp/rest/api/servicebus/receive-and-delete-message-destructive-read?WT.mc_id=AZ-MVP-5003113)」と同じですので、以下のドキュメントをご参考ください。

https://learn.microsoft.com/ja-jp/rest/api/servicebus/receive-and-delete-message-destructive-read?WT.mc_id=AZ-MVP-5003113


### 配信不能キューからメッセージを受信 (ピーク/ロック メッセージ)

```http:Peek-Lock&#x20;Message&#x20;(Non-Destructive&#x20;Read)
POST https://{serviceNamespace}.servicebus.windows.net/{queuePath}/$DeadLetterQueue/messages/head
```

| パラメーター | 設定値 |
|:-|:-|
| ```{serviceNamespace}``` | Service Bus の名前空間。 |
| ```{queuePath}``` | Service Bus のキュー。 |

リクエスト ヘッダー・ボディ、レスポンス コード・ヘッダー・ボディについては、メイン キューでの「[ピーク/ロック メッセージ (非破壊読み取り)](https://learn.microsoft.com/ja-jp/rest/api/servicebus/peek-lock-message-non-destructive-read?WT.mc_id=AZ-MVP-5003113)」と同じですので、以下のドキュメントをご参考ください。

https://learn.microsoft.com/ja-jp/rest/api/servicebus/peek-lock-message-non-destructive-read?WT.mc_id=AZ-MVP-5003113


### 配信不能キューのメッセージを削除

```http:Delete&#x20;Message
DELETE https://{serviceNamespace}.servicebus.windows.net/{queuePath}/$DeadLetterQueue/messages/{messageId | sequence-number}/{lockToken}
```

| パラメーター | 設定値 |
|:-|:-|
| ```{serviceNamespace}``` | Service Bus の名前空間。 |
| ```{queuePath}``` | Service Bus のキュー。 |
| ```{messageId}``` | ピーク/ロック メッセージ操作で返されるレスポンス ヘッダー ```BrokerProperties{MessageId}``` の値。メッセージ ID。 |
| ```{sequence-number}``` | ピーク/ロック メッセージ操作で返されるレスポンス ヘッダー ```BrokerProperties{SequenceNumber}``` の値。メッセージのシーケンス番号。 |
| ```{lockToken}``` | ピーク/ロック メッセージ操作で返されるレスポンス ヘッダー ```BrokerProperties{LockToken}```の値。メッセージのロックトークン。 |

リクエスト ヘッダー・ボディ、レスポンス コード・ヘッダー・ボディについては、メイン キューでの「[メッセージの削除](https://learn.microsoft.com/ja-jp/rest/api/servicebus/delete-message?WT.mc_id=AZ-MVP-5003113)」と同じですので、以下のドキュメントをご参考ください。

https://learn.microsoft.com/ja-jp/rest/api/servicebus/delete-message?WT.mc_id=AZ-MVP-5003113


### 配信不能キューのメッセージのロックを解除

```http:Unlock&#x20;Message
PUT https://{serviceNamespace}.servicebus.windows.net/{queuePath}/$DeadLetterQueue/messages/{messageId | sequence-number}/{lockToken}
```

| パラメーター | 設定値 |
|:-|:-|
| ```{serviceNamespace}``` | Service Bus の名前空間。 |
| ```{queuePath}``` | Service Bus のキュー。 |
| ```{messageId}``` | ピーク/ロック メッセージ操作で返されるレスポンス ヘッダー ```BrokerProperties{MessageId}``` の値。メッセージ ID。 |
| ```{sequence-number}``` | ピーク/ロック メッセージ操作で返されるレスポンス ヘッダー ```BrokerProperties{SequenceNumber}``` の値。メッセージのシーケンス番号。 |
| ```{lockToken}``` | ピーク/ロック メッセージ操作で返されるレスポンス ヘッダー ```BrokerProperties{LockToken}```の値。メッセージのロックトークン。 |

リクエスト ヘッダー・ボディ、レスポンス コード・ヘッダー・ボディについては、メイン キューでの「[メッセージのロックを解除する](https://learn.microsoft.com/ja-jp/rest/api/servicebus/unlock-message?WT.mc_id=AZ-MVP-5003113)」と同じですので、以下のドキュメントをご参考ください。

https://learn.microsoft.com/ja-jp/rest/api/servicebus/unlock-message?WT.mc_id=AZ-MVP-5003113


### 配信不能キューのメッセージのロックを更新

```http:Renew-Lock&#x20;for&#x20;a&#x20;Message
POST https://{serviceNamespace}.servicebus.windows.net/{queuePath}/$DeadLetterQueue/messages/{messageId | sequence-number}/{lockToken}
```

| パラメーター | 設定値 |
|:-|:-|
| ```{serviceNamespace}``` | Service Bus の名前空間。 |
| ```{queuePath}``` | Service Bus のキュー。 |
| ```{messageId}``` | ピーク/ロック メッセージ操作で返されるレスポンス ヘッダー ```BrokerProperties{MessageId}``` の値。メッセージ ID。 |
| ```{sequence-number}``` | ピーク/ロック メッセージ操作で返されるレスポンス ヘッダー ```BrokerProperties{SequenceNumber}``` の値。メッセージのシーケンス番号。 |
| ```{lockToken}``` | ピーク/ロック メッセージ操作で返されるレスポンス ヘッダー ```BrokerProperties{LockToken}```の値。メッセージのロックトークン。 |

リクエスト ヘッダー・ボディ、レスポンス コード・ヘッダー・ボディについては、メイン キューでの「[メッセージのロックを更新する](https://learn.microsoft.com/ja-jp/rest/api/servicebus/renew-lock-for-a-message?WT.mc_id=AZ-MVP-5003113)」と同じですので、以下のドキュメントをご参考ください。

https://learn.microsoft.com/ja-jp/rest/api/servicebus/renew-lock-for-a-message?WT.mc_id=AZ-MVP-5003113


# まとめ

Azure Service Bus 配信不能キューの存在、その目的と操作方法を知ることで、オモテ向きのキューだけでなく、配信不能キューもいろいろと活用できそうですね。:heart_eyes:

今回は REST API での操作について触れましたが、各種 SDK を用いれば配信不能キューの操作もカンタンにできると思います。

なお、REST API でアクセスする場合は、そのパスに[ドキュメント](https://learn.microsoft.com/ja-jp/azure/service-bus-messaging/service-bus-dead-letter-queues?WT.mc_id=AZ-MVP-5003113#path-to-the-dead-letter-queue)に示されている「```$DeadLetterQueue```」 を含めることをお忘れなく。

この投稿の内容が少しでもお役に立てればと思います。