Mastodon API で二重トゥートを防ぐ簡単な方法（Idempotency-Key で重複投稿防止）

<h2>重複投稿／二重投稿を防ぎたい</h2>

> マストドン API を利用時、**トゥートの投稿に失敗した際のリトライで重複投稿するのを避けたい**。

例えば、500 系のエラー発生やネットワークの問題などでタイムアウトした場合のリトライで、「Mastodon 側の反応が悪いことによる重複投稿」をしないように[ポカよけ](https://ja.wikipedia.org/wiki/%E3%83%9D%E3%82%AB%E3%83%A8%E3%82%B1)したい。

- マストドンとは[^mastodon]

[^mastodon]: **マストドンとは**、ミニブログ・タイプの [SNS](https://ja.wikipedia.org/wiki/%E7%A4%BE%E4%BC%9A%E7%9A%84%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF) の一種で、そのプログラムおよびサービスを指します。Facebook や twitter のように、１社もしくは１つのサーバー（ドメイン）に依存する「中央集権型 SNS」と異なり、共通のプロトコルを持ったサーバー間で通信を行う「[連合型 SNS](https://ja.wikipedia.org/wiki/%E5%88%86%E6%95%A3%E5%9E%8B%E3%82%BD%E3%83%BC%E3%82%B7%E3%83%A3%E3%83%AB%E3%83%BB%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF)」の１つです。マストドン・サーバー間だけでなく、[ActivityPub](https://ja.wikipedia.org/wiki/ActivityPub) と呼ばれる共通のプロトコルを使ったサーバーであれば通信できます。ちなみに Qiita の SNS である [Qiitadon](https://qiitadon.com/) はマストドンを使っています。<br>「[マストドン](https://ja.wikipedia.org/wiki/%E3%83%9E%E3%82%B9%E3%83%88%E3%83%89%E3%83%B3_(%E3%83%9F%E3%83%8B%E3%83%96%E3%83%AD%E3%82%B0))」@ Wikipedia<br>[マストドン公式サイト](https://joinmastodon.org/)

## TL; DR <sub><sup><sub><sup>（今北産業）</sup></sub></sup></sub>

> Mastodon のトゥート API は `idempotency`（[冪等](https://ja.wikipedia.org/wiki/%E5%86%AA%E7%AD%89)）に対応しています。

リクエスト・ヘッダーに "`Idempotency-Key: <UNIQUE ID>`" を含めると、**同じ `<UNIQUE ID>` のトゥートは１つのみが適用されます**。

```bash:bashサンプル
curl -X POST \
     -d 'status=Hello%20Qiitadon%21' \
     -d 'visibility=unlisted' \
     --header 'Authorization: Bearer <YOUR ACCESS TOEKN>' \
     --header 'Idempotency-Key: <UNIQUE ID>' \
     -sS https://qiitadon.com/api/v1/statuses
```

<font color=red>**注意:**</font> 同じ `Idempotency-Key` で処理済み（トゥート済み）の場合は `HTTP/1.1 404 Not Found` エラーが返ってきます。

## TS; DR

> **Note:** In order to prevent duplicate statuses, this endpoint accepts an `Idempotency-Key` header, which should be set to a unique string for each new status. In the event of a network error, a request can be retried with the same `Idempotency-Key`. Only one status will be created regardless of how many requests with the same `Idempotency-Key` did go through.
>
> See https://stripe.com/blog/idempotency for more on idempotency and idempotency keys.
> （"[Posting a new status](https://github.com/tootsuite/documentation/blob/master/Using-the-API/API.md#posting-a-new-status)" | Statuses | API overview | [Mastodon 公式 API](https://github.com/tootsuite/documentation/blob/master/Using-the-API/API.md) @ より）

▼ 筆者訳
> **注：** `statuses`（以下トゥート）の重複を防ぐために、このエンドポイントは `Idempotency-Key` ヘッダーを受け入れます。このヘッダーには、新しいトゥートごとに一意の文字列を設定する必要があります。ネットワークエラーが発生した場合は、同じ `Idempotency-Key` でリクエストを再試行できます。同じ `Idempotency-Key` のリクエストがいくつ通過したかにかかわらず、トゥートは１つだけ作成されます。
>
> `Idempotency` および `Idempotency-Key` についての詳細は、https://stripe.com/blog/idempotency を参照してください。


Qiita の SNS「[Qiitadon](https://qiitadon.com/)」（Qiita のマストドン・サーバー）で、[時報をトゥートする BOT](https://qiitadon.com/@QiiTime/with_replies) があるのですが、サーバーやネットワークの混雑からか、たまに失敗することがあります。

失敗した場合はリトライをするのですが、重複を避けるためにリトライ前に API で投稿済みのトゥートを調べていました。

BOT のリファクタをしようと API のドキュメントを眺めていたら、いつのまにか（2018/03 には）[新規トゥートの重複投稿に関する注意書き](https://github.com/tootsuite/documentation/commit/c2e5d5d6659112362ab6c941b4da70474de87b3b#diff-bb117bb0e63810e12cce57962e9b2a4f)が追加されていて、しかも 2017 年 3 月にはこの[重複投稿の予防は実装されていました](https://github.com/tootsuite/mastodon/pull/2419/files)。

気づくの遅いよっ！！ :wave: ﾊﾞｼｯ