はじめに
こんにちは。Tsukasaです!
皆さん、Step Functionsを触ったことはありますか?
私はありません。認定試験でStep Functionsに関する問題はたまに見かけますが、自分で説明するとなると難易度が高いです。Step Functuonsに対する解像度が低いのであれば、実際に触ってみようということで今回はハンズオンをやってみたので、そのことについて記事にできたらと思います。
今回もAWS公式のハンズオン資料があったのでこちらを用いて行いました。
それでは早速見ていきましょう!
Step Functionsとは
AWS Step Functionsとは、AWSが提供するサーバーレスのワークフローサービスで、複数のAWSサービスを連携させ、複雑な処理を視覚的に管理・オーケストレーションできるサービスです。分散アプリケーションの構築や、マイクロサービス、ETL処理、機械学習パイプラインなどに活用できます。
AWSのワークフロー図と考えていただければいいかと思います。
公式のドキュメントもあるので、興味のある方はご覧いただけたらと思います。
今回やること
今回のハンズオンでやる構成は以下のようになります。
DynamoDBに記事を格納して、検索条件に一致する記事があるかないかで分岐します。
もしあった場合は、並列処理で記事をTranslateを用いて英訳し、更にPollyを使って音声化します。
音声化したファイルはS3バケットに格納されます。
ハンズオン動画でも何をやりたいかの紹介があるので、こちらを見ていただければ今回やりたいことの全体像は何となく掴めると思います。

Step Functions全体の作成
まずはStep Functions全体の作成を行います。マネジメントコンソールでStep Functionsを検索します。
すると下記のような画面に遷移するので、ステートマシンの作成ボタンをクリックして作成を行います。
ステートマシン名は好きな名前で大丈夫ですが、わかりやすいものがいいかと思います。
またステートマシンのタイプですが、下記の画像では標準にチェックが入っていますが、こちらはExpressを選択します。ここまでできたら右下の続行ボタンをクリックします。

その後このような画面に遷移するかと思います。ここまで来たら右上の作成ボタンをクリックします。
ここでワークフロー図を作成します。今回メインで使うのがこちらの画面になります。

作成が完了するとこのようなが画面に遷移します。ステータスが成功になっていますね。

そうしたらこのワークフロー図がちゃんと動くかの確認を行います。
実行を開始ボタンをクリックして確認します。

DynamoDBの作成
Step Functionsのステートマシンが作成できたら、次はDynamoDBを作成します。
テーブル名とパーティションキーを入力して後はデフォルトのままで大丈夫です。
DynamoDBが作成できたら、項目を探索からこちらの画面にアクセスします。
※諸事情により、テーブル名が変わっています。こちらは気にしていただかなくて大丈夫です。

項目を作成ボタンをクリックして下記のように記入を行います。
今回はStep Functionsの概要について記入しました。
こちらが今回核となる記事に該当する部分です。

DynamoDBの初期設定は以上です。
Step Functionsの編集(DynamoDB)
DynamoDBの作成が終わりましたので、これをStep Functionsに反映したいと思います。
まずはPassを削除します。

左のタブでDynamoDBを検索したら、DynamoDB GetItemというものが一番上に表示されるかと思いますので、それおをドロップアンドドラッグして持ってきます。
持ってこれたら、右側の設定を変えます。
統合タイプをAWS SDKにします。

引数と出力のタブで引数を画像のように設定します。
ここまでできたら保存して、ちゃんと動くか確認します。

エラーとなりました。エラー文を読んでみると、権限がないとのことでした。
そうです。IAMロールに追加しないといけません。
IAMロールの追加方法は下記画像のURL部分をクリックすると自動で画面が遷移するようになっています。

今回は一番上のAmazonDynamoDBFullAccessを選択します。

IAMロールの追加が完了したら、再度実行します。
今度は無事に実行できました。
状態の出力を見るとDynamoDBで作成した0001の記事がここで表示されていますね。

分岐処理の作成
最初の構成を思い出してみてください。
DynamoDBの下に分岐処理がありましたよね。
分岐処理の内容としては記事情報があるかないかです。
記事は0001と0002というものを作りましたが、例えば9999という番号の記事はありませんよね?
ここでは記事がある場合とない場合での分岐処理を作成していきます。

Step Functionsの画面から分岐処理を作成します。
フローからChoiceを選択して、DynamoDBの下にドロップアンドドラッグで持ってきます。

Choiceを選択すると、右側にChoice Rulesというものがありますので、Rule #1の鉛筆マークをクリックして、ルールを編集していきます。

今回の条件はItemが存在するかどうかで処理が分岐されるので、頭に$をつけてItemと表記します。
Operatorはis presentを選択します。
そもそもこの$はなんなのか?という話ですが、SONPath という形式で 入力データの特定の値を参照するための記号です。簡単に言えば、Step Functions の中で「どこからデータを取り出すか」を指定するために使われます。
エクセルの関数でも$を用いてどこのセルから参照するか指定するのでそれと同じだと思います。(間違っていたら教えてください)

今回の条件のItemがどこから来たのかわからない方もいらっしゃるかと思います。
Itemは下記から来ています。先程DynamoDBを実行した際に状態の出力を見ていただくと、こちらにItemがあります。

DynamoDB APIパラメータの編集
次はDynamoDBのAPIパラメータの編集を行います。
ArticleIDが"S" : "0001"となっていましたが、これだと0001の記事があるかどうかのチェックになってしまいます。既に0002も作成しましたし、今後記事が追加されてもチェックができるように下記のように編集する必要があります。

並列処理の作成
分岐処理を行い、もし記事がある場合は下記のように並列処理を作成します。
並列処理はTranslateで英語に翻訳するのとPollyで音声化するんでしたよね。
今回はその部分を実装していきたいと思います。
フローからParallelを選択して、ドロップアンドドラッグでChoiceの下に持っていきます。

左側にTranslateTextを持ってきて、右側は一時的にPassにします。(後ほど変更します)

まずは動くかどうかを確認します。
APIパラメータを下記のように設定します。

その後実行します。
そうすると下記のように英語に翻訳されます。

TranslateのAPIパラメータも先程と同じように編集します。
"$.Item.Detail.S"
このパラメータも何故こうする必要があるのかわからない方がいらっしゃるかもしれないので説明いたします。
下記を見ていただくと、Item配下にDetailがありその中にSがあります。
先程も紹介したように記事の内容はその都度違いますし、今後追加されることも考えられるので、$で参照範囲を指定する必要があります。

ここまでできたら、保存して実行します。
実行結果は下記のようになりました。
ちゃんと英訳されてますね!

DynamoDBの更新
次にDynamoDBの更新を行います。
こちらはTranslateの下に持ってきて、英訳されたデータを保存するためのものとなります。
APIパラメータは下記のように設定していただけたらと思います。

一度保存して、実行を行います。
その後DynamoDBを確認するとちゃんとHelloと表示されているのが確認できました!

とりあえず動くことはわかりました。
ですが、これだとHelloのように具体的な値を入力する必要があります。
値はその都度違いますよね?
その場合はどうすればいいでしょうか?
そうです。$を使えばいいのです。
TranslateTextの出力タブで「ResultPathを使用して元の入力を出力に追加」という項目があるので、こちらにチェックを入れます。元の入力と結果を結合を選択して、$.Resultと入力します。
保存して実行します。

実行するとResult配下が英訳されているのがわかるかと思います。

Pollyの作成
ここでは並列処理のもう一つPollyを作成していきます。
Pollyを使うためにはS3バケットが必要なので、まずはS3バケットの作成を行います。
これは音声化したファイルを保存するために必要なものです。
バケット名だけ記入して他の設定はデフォルトのままで大丈夫です。

S3バケットが作成できたら、PollyのIAMロールを設定します。

Step Funcions側でPollyの設定を行います。
今回はStartSpeechSynthesis Taskを選びます。
APIパラメータは下記のように設定します。
保存して実行を行います。

ステートで「タスクが終わるまで待つ」を実装する
音声化できるところまでは確認できました。
しかしこの音声化には時間が少々かかります。
ここでは、音声化が完了した後でDynamoDBテーブルにmp3のパスを格納したいので、Waitステートを使って定期的にポーリングするような実装を行いたいと思います。
まずStartSpeechSynthesisTaskの下にGetSpeechSynthesisTaskを持ってきます。

StartSpeechSynthesisTaskの入力/出力の出力部分を変更します。
先程のTranslateTextと同じように変更します。
保存して実行します。

続いてGetSpeechSynthesisTaksのAPIパラメータを変更します。
こちらは下記のように設定してもらえれば大丈夫です。

因みにこのAPIパラメータも下記から来ています。
Result配下のSynthesisTaskに格納されているTaskIdを指定します。

GetSpeechSynthesisTaskも同様に入力/出力タブを下記のように修正します。
保存して実行を行います。

こちらも問題なく動きました。
ただ、TaskStatusを確認するとCompletedではなくScheduledになっていてまだ完了していません。
ここではCompletedになるまで待つような実装を行いたいと思います。

GetSpeechSynthesisTaskの下にChoiceを入れます。
分岐処理はひとまずPassを置き、もう一つをWaitにします。

ChoiceのChoice Rulesを編集します。
Ruleの鉛筆マークをクリックします。

$.Result.SynthesisTask.TaskStatus
こちらをValuableに記入し、後は下記のように設定していただけたらと思います。
これで条件の設定が完了となります。
これでChoiceでTaskが完了したらPass(後にDynamoDBに変更予定)へと処理が飛び、完了していない場合はWaitに処理が飛ぶ形になります。

続いてWait側です。
こちらの設定を行います。時間はとりあえず5秒で設定します。
次の状態ですが、これで終わっては困るので、GetSpeechSynthesisTaskを指定します。
これで、5秒待っても終わらない場合は、再びGetSpeechSynthesisTaskへ飛びそこで分岐処理を行うといった形になり、表を見ていただくとわかり通りでぐるぐると処理が繰り返される形となります。

それでは保存して実行してみます。
下記を見ていただくとわかるとおり、何度かwaitステータスになっているのがわかります。

DynamoDBの更新
こちらではTranslateの時と同じようにDynamoDBを更新していきます。
手順としてはTranslateと同じなので詳細については割愛します。
DynamoDBにmp3のURLが格納されているのが確認できます。

終わりに
いかがでしたでしょうか?
実際に触るまではStep Functionsが何なのかもいまいち理解できていませんでしたが、こうやって触ってみる事で解像度が上がりました!
また、Step Functionsを触るということはPollyやTranslateといった他のサービスも同時に触ることになるので、他のサービスについて理解を深める良い機会かもしれません。
Step Functionsは初心者レベルとは言えない色々なサービスや機能を複数組み合わせます。
そのため私自身もハンズオンをやりながらあまり理解できておらず、ただ言われるがままにやっただけでした。
それでもちゃんと動くものができた時は嬉しいですし、達成感を感じられました。
理解を深めるためにはハンズオンだけではなく、このようにアウトプットをすることが大事だと思うので、今後とも学んだことはこのようにブログにしていきたいなと思います!


















