AWS Step Functions の redrive を使ってみた

AWS Step Functions について使ってみた結果を残していきます。今回はワークフローが失敗したポイントから再実行できる redrive について確認しています。
# ドキュメントの確認
## Whats new の情報
https://aws.amazon.com/jp/about-aws/whats-new/2023/11/aws-step-functions-restarting-workflows-failure/

What's new には「AWS Step Functions がワークフローが失敗したポイントから簡単に再実行できる」という要点と Step Functions 全体の便利さの紹介が書いてあります。[AWS Blog へのリンク](https://aws.amazon.com/jp/blogs/compute/introducing-aws-step-functions-redrive-a-new-way-to-restart-workflows/)もあるので参考になります。

## Developer Guide の情報
https://docs.aws.amazon.com/step-functions/latest/dg/redrive-executions.html

2023年11月18日時点ではまだ英語のみなので、ポイントを抽出してみます。
### 概要
* 再実行を redrive と呼ぶ
* 過去14日間以内に実行が成功しなかった標準ワークフローを redrive できる
* Redrive では前回実行と同じ ステートマシン定義、同じARN を使用するため input や version や alias などは変えられない
* Redrive するためには IAM アクセス権限として"states:RedriveExecution"の追加が必要
* Management Console と API のどちらからも redrive 可能
* Redrive の結果は Cosole もしくは [GetExecutionHistory](https://docs.aws.amazon.com/step-functions/latest/apireference/API_GetExecutionHistory.html) と [DesrbiteExecution](https://docs.aws.amazon.com/step-functions/latest/apireference/API_DescribeExecution.html) で確認可能

### redrive の条件
* 2023年11月15日以降に実行している。
* 実行の状態が SUCCEEDED 以外。
* redrive 期限の14日間を超えていない。
* 年間 open time など[ステートマシンに関する Quotas](https://docs.aws.amazon.com/step-functions/latest/dg/limits-overview.html#service-limits-state-machine-executions) を超えていない。
* 実行履歴が 24,999 を超えていない。

### 状態毎の redrive の振る舞い
* **Pass**: 再実行される
* **Task**: 再度スケジュールされてタスクが開始される。
* **Choise**: チョイスルールが再評価される
* **Wait**: Timestamp か TimestampPath が過去の時間を指しているならNext に進む
* **Succeed**: 再実行されない
* **Fail**: Fail状態に再度入り、再度失敗となる
* **Parallel**: failed か aborted のブランチのみがredrive される。ただし、fail の理由が States.DataLimitExceeded の場合、元々成功していたブランチも再実行される。
* **Inline Map state**: (Parallelと同じ)
* **Distributed Map state**: Map run 内の成功しなかった子ワークフローが redrive される。ただし、fail の理由が States.DataLimitExceeded の場合、元々成功していた子ワークフローも再実行される。


# サンプルによる実験
今回は ec2上に配置された shell の実行を実験してみました。全体の流れは以下のAWS 規範的ガイダンスを参考にして作成しました。

https://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/patterns/run-aws-systems-manager-automation-tasks-synchronously-from-aws-step-functions.html


## 1) 前提：EC2 Instance の立ち上げと SSM Agent の稼働
EC2 Instance を立ち上げてSSM (AWS System Manager) Agent が稼働している状態にします。SSM agent の詳細については以下を参照ください。

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/ssm-agent.html


## 2) 実行するサンプルシェルスクリプトの作成と配置
サンプルとして以下のシェルスクリプトを作成し、上で作ったEC2インスタンスの `/home/ec2-user/sample-batch/do-some1.sh` に配置しています。後で AWS Step Functions の挙動を実験するために、引数やファイル有無で return code を変更できるようにしています。

```
#!/bin/bash
if [ $# -ne 0 ]; then
        echo "引数は$#個です" 1>&2
        echo "引数を指定してはいけません" 1>&2
        exit 1
fi
for i in {1..10} ; do
        echo "Doing Something #1" ${i}
        sleep 1
done
if [ -f ./filetest ]; then
        exit 1
fi
exit 0
```


## 3) AWS Systems Manager に Document を作成
aws-samples の [amazon-stepfunctions-ssm-waitfortasktoken](https://github.com/aws-samples/amazon-stepfunctions-ssm-waitfortasktoken) を利用して SfnRunCommandByInstanceIds を作成。

https://github.com/aws-samples/amazon-stepfunctions-ssm-waitfortasktoken

作成した結果は AWS Systems Managers 上に以下のように表示されます。本記事では SfnRunCommandByInstanceIds を使っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3623605/51486dbf-6801-0729-3210-425bc9dc5855.png)


## 4) AWS Step Functions にステートマシンを作成
上と同じく  [amazon-stepfunctions-ssm-waitfortasktoken](https://github.com/aws-samples/amazon-stepfunctions-ssm-waitfortasktoken)  のサンプルを流用して、以下の定義を持つステートマシンを作成。
```
{
  "Comment": "This is a test state machine by yki",
  "StartAt": "StartAutomationWaitForCallBack",
  "States": {
    "StartAutomationWaitForCallBack": {
      "Type": "Task",
      "Resource": "arn:aws:states:::aws-sdk:ssm:startAutomationExecution.waitForTaskToken",
      "Parameters": {
        "DocumentName": "SfnRunCommandByInstanceIds",
        "Parameters": {
          "InstanceIds": [
            "i-0xxxxxxxxxxxxxxx"
          ],
          "taskToken.$": "States.Array($$.Task.Token)",
          "workingDirectory": [
            "/home/ec2-user/sample-batch/"
          ],
          "Commands": [
            "./do-some1.sh"
          ]
        }
      },
      "End": true
    }
  }
}
```

IAM で実行ロールに以下の権限追加も行いました。
```
{
            "Effect": "Allow",
            "Action": "ssm:StartAutomationExecution",
            "Resource": "*"
}
```

## 5) ステートマシンの実行
実行前にEC2 インスタンス上で `/home/ec2-user/sample-batch/filetest` というファイルを作り、シェルが "1"を return するようにしてステートマシンを実行すると、想定通り実行失敗を発生させることができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3623605/15e213cd-2893-d31b-d8b3-6fa99babf558.png)

実行ステータスは失敗と表示され、イベントにも ExecutionFailed が見えています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3623605/b06e6fbd-eb3a-b1cd-5f3e-dd85e895a15f.png)

## 6) ステートマシンの再実行 (redrive)

それでは今回の本題の redrive です。EC2 インスタンス上で `/home/ec2-user/sample-batch/filetest` を削除した上で、失敗したステートマシンを redrive してみます。マネジメントコンソール上で失敗したステートマシンを見ると、「リドライブ」が選べるので、これを選択してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3623605/7a99959e-2075-d11d-1737-d9a5b39528e4.png)


すると以下のダイアログが表示されるので、「リドライブの実行」を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3623605/9c1d9716-2db3-facb-5234-66adaa79eea7.png)


すると次は無事に成功しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3623605/ca213ba8-83e5-e276-0a18-9d881ce542fd.png)

実行ステータスは成功となり、イベントにも ExecutionSucceeded が表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3623605/7eaa52e1-1914-d5f0-ca64-6b46178e6f93.png)

今回は実際に redrive で再実行はできましたが、ステートマシンの定義がシンプル過ぎるため詳細の挙動の確認には至りませんでした。次回の記事ではもう少し細かい挙動の確認をしてみようと思います。 

**[追記]**
少し細かい挙動の実験を３種類してみました。すこし癖がある動きをするので複雑なステートマシンを組む際には注意が必要そうです。

https://qiita.com/pryki/items/a3bffa39f4bed5cdd0fb

https://qiita.com/pryki/items/b4425f86a926a711ea89

https://qiita.com/pryki/items/4c7bb4a0ca4acb863de6