LoginSignup
2
0

More than 3 years have passed since last update.

[AWS] Step Functionsで遊んでみる(SAM + Lambda) Part.3(分岐編)

Last updated at Posted at 2020-08-17

Part.2のおさらい

Part2では、主に以下のことを行いました。

  • Lambdaに固定引数を渡してみる
  • Lambdaに外部からの引数を渡してみる
  • Lambdaにコンテキストオブジェクトを渡してみる
  • Lambdaの戻り値を、別のTaskの引数に渡してみる

今回は、その続きからはじめてみます。
ここから始める方は、
https://github.com/hito-psv/sam-demo-005
のコードをgit cloneしてもらっても大丈夫ですし、Part2からやってみてもらっても構いません。

今回のターゲット

  • Lambdaでランダムな結果を返す
  • 結果に応じて、次に実行するタスクを変える
  • リトライ時は、しばらく時間が経ってから再実行する

をターゲットにしてみたいと思います。
Lambda部分については、Part2で作成した「HelloWorld」の関数を少しだけいじって、色々試してみたいと思います。

準備

Lambda関数を修正する

現在のコードに、乱数でいくつかのパターンの文字列を返すようにしてみたいと思います。

hello_world/app.py
import logging
import random

logger = logging.getLogger()
logger.setLevel(logging.INFO)

def lambda_handler(event, context):
    logger.info(event)

    message_array = [
        "hello world",
        "retry"
    ]
    message = random.choice(message_array)
    logger.info(message)

    return {
        "statusCode": 200,
        "body": {
            "message": message,
        }
    }

これで、結果のメッセージには

  • hello_world
  • retry

のいずれかの文字列が返されます。

ビルド・デプロイする

この状態で、sam buildsam deploy --guidedを実行し、Lambda関数をデプロイしましょう。

Lambda関数の戻り値によって振る舞いを変える

ステートマシン定義の修正

まずは、ステートマシンの定義を修正します。
修正内容は後ほど説明しますので、まずは、このように修正してみます。

step_functions/state_machine.json
{
  "StartAt": "hello world 1",
  "States": {
    "hello world 1": {
      "Type": "Task",
      "Resource": "${HelloWorldFunction}",
      "Parameters": {
        "p1.$": $.p1,
        "p2.$": "$.p2",
        "p3": {
          "p3-1": 20,
          "p3-2": "xyz"
        },
        "all.$": "$"
      },
      "ResultPath": "$.hello_world_result",
      "OutputPath": "$",
      "Next": "check state"
    },
    "retry lambda": {
      "Type": "Task",
      "Resource": "${HelloWorldFunction}",
      "InputPath": "$",
      "ResultPath": "$.hello_world_result",
      "OutputPath": "$",
      "Next": "check state"
    },
    "check state": {
      "Type" : "Choice",
      "Choices": [
        {
          "Variable": "$.hello_world_result.body.message",
          "StringEquals": "hello world",
          "Next": "hello world 2"
        },
        {
          "Variable": "$.hello_world_result.body.message",
          "StringEquals": "retry",
          "Next": "wait state"
        }
      ],
      "Default": "fail state"
    },
    "wait state": {
      "Type": "Wait",
      "Seconds": 5,
      "Next": "retry lambda"
    },
    "hello world 2": {
      "Type": "Task",
      "Resource": "${HelloWorldFunction}",
      "InputPath": "$",
      "End": true
    },
    "fail state": {
      "Type": "Fail",
      "Cause": "No Matches!"
    }
  }
}
  1. 「hello world 1」は次のステートに「check state」のステートを実行する
  2. 「check state」は「$.hello_world_result.body.message」の値が「hello world」なら、次のステートに「hello world 2」を実行する
  3. 「check state」は「$.hello_world_result.body.message」の値が「retry」なら、次のステートに「wait state」を実行する
  4. 「check state」は「$.hello_world_result.body.message」の値が「hello world」「retry」以外なら、次のステートに「fail state」を実行する(今回は起こり得ない)
  5. 「wait state」は、5秒経ったら「retry lambda」のステートを実行する
  6. 「retry lambda」は、lambda関数をコールした後、「check state」のステートを実行する
  7. 「hello world 2」はlambda関数をコールした後、ステート実行を終了する
  8. 「fail state」は、異常終了としてステート実行を終了する

という記述になっています。
「Choices」の中で

  • Variable:チェック対象
  • StringEquals:文字列がこの値と同じなら
  • Next:次に実行するステート

を指定します。
なお、StringEqualsの箇所に指定できる演算は、AWS Step Functions開発者ガイドを参照ください。

ビルド・デプロイする

この状態で、sam buildsam deploy --guidedを実行し、デプロイしましょう。

ステートマシンの確認

まずは、ステートマシンの定義更新によって、可視化されたステートマシンがどのようになっているかをみてみましょう。

sf1.png

変更したように、「check state」から分岐し、「retry lambda」の後「check state」に戻っていることが確認できたと思います。

ステートマシンを実行してみる

マネジメントコンソールから、ステートマシンを実行してみましょう。
Part.2からの修正のため、入力値のp1、p2を使用するため、入力蘭を以下のように指定してください。

68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3432373939382f64303138383561632d323261362d623039372d646435622d3135383438333539616634372e706e67.png

  • p1に、9999数値を指定
  • p2に「p2 strings.」という文字列を指定

結果をみてみる

まずは、ビジュアルフローを確認してみましょう。
見事に、全パスが通ってくれてます(ランダムなので、「hello world 1」→「check state」→「hello world 2」という流れもありえます)。

sf2.png

では、Choiceの処理が正しく動作しているのか、確認してみましょう。
まずは、「hello world 1」のステートから呼び出されたLambda関数の戻りがこちらです。

sf3.png

bodyのmessage部が「retry」であることが確認できます。
その結果、次に「wait state」が実行され、5秒後(#10と#11の時間をチェック)「retry lambdaのステートが実行されています。

sf4.png

実は、この後、更に2回連続して「retry」が返ってきますが、3回目に「hello world」が返されます。

sf5.png

その後は「hello world 2」のステートが実行されていることがわかります。

sf6.png

そして、そのままステートが終了します。

新しく追加された「Choice」ステート

2020/8/13に、アップデートされた内容があります。

値のテスト(型チェック)

  • IsNull
  • IsString
  • IsNumeric
  • IsBoolean
  • IsTimestamp

によって、Variableの型をChoiceで確認することができます。

   "Variable": "$.foo",
   "IsNull|IsString|IsNumeric|IsBoolean|IsTimestamp": true|false

存在チェック

  • IsPresent

によって、Variableそのものの存在チェックを行うことができます。

  "Variable": "$.foo",
  "IsPresent": true|false

ワイルドカードチェック

  • StringMatches

によって、ワイルドカードを使用した判定チェックが行えます。

  "Variable": "$.foo",
  "StringMatches": "log-*.txt"

別の入力フィールドとの比較

  • StringEqualsPath

によって、入力フィールドを別の入力フィールドと比較できます。状態の変更などを確認するときに使用できます。

  "Variable": "$.foo",
  "StringEqualsPath": "$.bar"

詳細

こちらから確認できます。

AWS Step Functions adds updates to ‘choice’ state, global access to context object, dynamic timeouts, result selection, and intrinsic functions to Amazon States Language

まとめ

今回はChoiceによる分岐を行なってみましたが、ここまで来ると、ようやくワークフローっぽくなってきた感じがしますね。
ここまでのPart.1〜Part.3の内容だけでも、ある程度のステートマシンが定義できるようになっているかと思います。
次回は、Lambda以外のサービスをタスク定義で呼び出してみたいと思います。

サンプルコードリポジトリ

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0