Sidekiqを自動に再実行スクリプトならjqとbashだけで出来ます！

## sidekiqについて

シンプルで効率的なRubyのバックグラウンド処理。

Sidekiqは、スレッドを使用して、同じプロセスで同時に多くのジョブを処理します。Railsを必要としませんが、Railsと緊密に統合し、バックグラウンド処理を死ぬほどシンプルにすることができます。

SidekiqはRedisを使ってて管理してます。


## 今回のやったもの

Sidekiqを管理するはデフォルトで管理画面だけです
![Screen Shot 2022-11-04 at 15.05.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878226/28427293-87ab-ead2-ddd3-aee81166ecad.png)

ですが、毎回手動で確認するも時間の無駄なので早めに自動にしたいと思ってまして、やってみました。

## 使い方

### データをアクセスする

SidekiqはRailsを使ってますがー Redis-cliも使えます！それだと直接DBを操作できます！

```bash
$ redis-cli -h 10.XX.XX.XX -p 6379 -n 12 「コマンド」
```

重要は`-n`パラメータです、sidekiqは１２番のノードで動いてます。それで色んなキューのデータを見えます、例えばsidekiqの死亡タスクリストを見たいは簡単で見えます：

```bash
$ redis-cli -h 10.XX.XX.XX -p 6379 -n 12 zrange sidekiq:dead 0 -1
   1) "{\"retry\":3,\"queue\":\"my_queue\",\"class\":\"MyJobs::WorkerJob1\",\"args\":[403006293],\"jid\":\"56ca5a4be4ef23b6f3676f66\",\"enqueued_at\":1665855225.4404187,\"error_message\":\"Endpoint does not exist\",\"error_class\":\"   AWS::SNS::Errors::InvalidParameter\",\"failed_at\":1665855225.5153027,\"retry_count\":3,\"retried_at\":1665855459.3232806}"
   2) "{\"retry\":3,\"queue\":\"my_queue\",\"class\":\"MyJobs::WorkerJob2\",\"args\":[342105086],\"jid\":\"3413771368fb2b2a027546db\",\"enqueued_at\":1665855398.6243336,\"error_message\":\"Could not connect to MySQL\",\"error_class\":\"AWS::RDS::Errors::NoConnection\",\"failed_at\":1665855398.7288938,\"retry_count\":3,\"retried_at\":1665855640.0306947}"
   3) "{\"retry\":3,\"queue\":\"my_queue\",\"class\":\"MyJobs::WorkerJob2\",\"args\":[404318713],\"jid\":\"56104406dc2e252842344dbb\",\"enqueued_at\":1665859144.2329714,\"error_message\":\"Could not connect to MySQL\",\"error_class\":\"AWS::RDS::Errors::NoConnection\",\"failed_at\":1665859144.3381548,\"retry_count\":3,\"retried_at\":1665859416.574747}"
   4) "{\"retry\":3,\"queue\":\"my_queue\",\"class\":\"MyJobs::WorkerJob3\",\"args\":[404320461],\"jid\":\"804e1960b48f7cfc904eb22d\",\"enqueued_at\":1665859721.6611075,\"error_message\":\"Could not connect to MySQL\",\"error_class\":\"AWS::RDS::Errors::NoConnection\",\"failed_at\":1665859721.7336028,\"retry_count\":3,\"retried_at\":1665859871.431027}"
   5) "{\"retry\":3,\"queue\":\"my_queue\",\"class\":\"MyJobs::WorkerJob3\",\"args\":[400817551],\"jid\":\"3f853435b08b82572b69bacb\",\"enqueued_at\":1665865808.7670307,\"error_message\":\"Could not connect to MySQL\",\"error_class\":\"AWS::RDS::Errors::NoConnection\",\"failed_at\":1665865808.87391,\"retry_count\":3,\"retried_at\":1665866071.994373}"
```

Jsonのフォーマットで全部のジョブを見えます！

### データを変更する

Redisは以外と単純です、データを入れられる、データを削除する、それだけです、Updateとかはあんまり使わらないし、IDとかもないです、ノードの中では色んなのキューはあって、そのキューの中はメンバーがあります。

データを入れたいとき：

```bash
$ redis-cli -h 10.XX.XX.XX -p 6379 -n 12 lpush "「キューの名前」" "「メンバー」"`
```
例えば：

```bash

$ redis-cli -h 10.XX.XX.XX -p 6379 -n 12 lpush "sidekiq:queue:my_queue" "{\"retry\":3,\"queue\":\"my_queue\",\"class\":\"MyJobs::WorkerJob3\",\"args\":[400817551],\"jid\":\"3f853435b08b82572b69bacb\",\"enqueued_at\":1665865808.7670307,\"error_message\":\"Could not connect to MySQL\",\"error_class\":\"AWS::RDS::Errors::NoConnection\",\"failed_at\":1665865808.87391,\"retry_count\":3,\"retried_at\":1665866071.994373}"
```

１件ずつをするのがちょっと大変なのでスクリプトを入れる！

必須なもの：

- 死亡のリストを取る
    - リストの全部を取るの方がいいので：
    - ```bash
      $ redis-cli -h 10.XX.XX.XX -p 6379 -n 12 zrange sidekiq:dead 0 -1 > ファイル.log
       ```
- キューの名前：
    - さっきJsonだと気づいたらなので `jq` コマンドを使えます！
        ```bash
        echo "{\"retry\":3,\"queue\":\"default\",\"class\":\"DropTmpTableWorker\",\"args\":[\"tmp_julien_test_tmp_table\"],\"jid\":\"7b1b36e00383906568f3bf2d\",\"enqueued_at\":1661332354.1658273,\"error_message\":\"Invalid parameter: Endpoint Reason: Endpoint does not exist for endpoint arnarn:aws:sns:ap-northeast-1:600552931410:endpoint/GCM/85989/24276665-d2cd-3d3a-90d5-6f6902d860a9\",\"error_class\":\"AWS::SNS::Errors::InvalidParameter\",\"failed_at\":1661332354.3494694,\"retry_count\":3,\"retried_at\":11666466992.0864118}" | jq .
        {
        "retry": 3,
        "queue": "default",
        "class": "DropTmpTableWorker",
        "args": [
          "tmp_julien_test_tmp_table"
        ],
        "jid": "7b1b36e00383906568f3bf2d",
        "enqueued_at": 1661332354.1658273,
        "error_message": "Invalid parameter: Endpoint Reason: Endpoint does not exist for endpoint arnarn:aws:sns:ap-northeast-1:600552931410:endpoint/GCM/85989/24276665-d2cd-3d3a-90d5-6f6902d860a9",
        "error_class": "AWS::SNS::Errors::InvalidParameter",
        "failed_at": 1661332354.3494694,
        "retry_count": 3,
        "retried_at": 11666466992.086412
        }
        ```

        もっと便利はこちら
        
        ```bash
        echo "{\"retry\":3,\"queue\":\"default\",\"class\":\"DropTmpTableWorker\",\"args\":[\"tmp_julien_test_tmp_table\"],\"jid\":\"7b1b36e00383906568f3bf2d\",\"enqueued_at\":1661332354.1658273,\"error_message\":\"Invalid parameter: Endpoint Reason: Endpoint does not exist for endpoint arnarn:aws:sns:ap-northeast-1:600552931410:endpoint/GCM/85989/24276665-d2cd-3d3a-90d5-6f6902d860a9\",\"error_class\":\"AWS::SNS::Errors::InvalidParameter\",\"failed_at\":1661332354.3494694,\"retry_count\":3,\"retried_at\":11666466992.0864118}" | jq '.queue'
        "default"
        ```

それで毎ジョブを自動にキューを取れる。

- retry_countを少なくにする、もう死亡に入ったのでそのパラメータを変更しないと一気に死亡に戻ります
    - Sidekiqのコードでそれを対応しなきゃ
    - もう一回パラメータをjqしてからJsonで戻すこと
```bash
retry_params=$(echo "$line" | jq '.retry_count = 0 | @json')
```

- redis-cliを使いながらジョブを入れて、死亡のキューのジョブを削除
```bash:キューに入れる
redis-cli -h $REDIS -p $PORT -n $SEED lpush "sidekiq:queue:${queue//\"/}" "${retry_params}"
```
```bash:死亡を削除
redis-cli -h $REDIS -p $PORT -n $SEED lpush "sidekiq:queue:${queue//\"/}" "${retry_params}"
```

それで無事に再実行が自動でできます！

最後のファイルはこんな感じです：

```bash
REDIS=10.XX.XX.XX
PORT=XXXX
SEED=12
redis-cli -h $REDIS -p $PORT -n $SEED zrange sidekiq:dead 0 -1 > ファイル.log
while read line; do
    queue=$(echo "$line" | jq '.queue')
    retry_params=$(echo "$line" | jq '.retry_count = 0 | @json')
    redis-cli -h $REDIS -p $PORT -n $SEED lpush "sidekiq:queue:${queue//\"/}" "${retry_params}"
    redis-cli -h $REDIS -p $PORT -n $SEED ZREM "sidekiq:dead" "${line}"
done < ファイル.log
```

## 注意点

色々やってみてたら、`jq`コマンドで変なバグが見つかりました、数字の文字制限がありました。

```bash
echo "{\"retry\":3,\"queue\":\"default\",\"class\":\"DropTmpTableWorker\",\"args\":[\"tmp_julien_test_tmp_table\"],\"jid\":\"7b1b36e00383906568f3bf2d\",\"enqueued_at\":1661332354.1658273,\"error_message\":\"Invalid parameter: Endpoint Reason: Endpoint does not exist for endpoint arnarn:aws:sns:ap-northeast-1:600552931410:endpoint/GCM/85989/24276665-d2cd-3d3a-90d5-6f6902d860a9\",\"error_class\":\"AWS::SNS::Errors::InvalidParameter\",\"failed_at\":1661332354.3494694,\"retry_count\":3,\"retried_at\":11666466992.0864108}" | jq .
{
  "retry": 3,
  "queue": "default",
  "class": "DropTmpTableWorker",
  "args": [
    "tmp_julien_test_tmp_table"
  ],
  "jid": "7b1b36e00383906568f3bf2d",
  "enqueued_at": 1661332354.1658273,
  "error_message": "Invalid parameter: Endpoint Reason: Endpoint does not exist for endpoint arnarn:aws:sns:ap-northeast-1:600552931410:endpoint/GCM/85989/24276665-d2cd-3d3a-90d5-6f6902d860a9",
  "error_class": "AWS::SNS::Errors::InvalidParameter",
  "failed_at": 1661332354.3494694,
  "retry_count": 3,
  "retried_at": 11666466992.08641
}
```

１件だけは違いありまして、`\"retried_at\":11666466992.0864108`がjsonに入ってますが、`jq`を入れたら、`"retried_at": 11666466992.08641`になってます、`.086408`から`.08641`になってます。。

今回は死亡を削除したい場合は全く同じパラメータじゃないと削除できないのでご注意ください。