StepFunctionsの基本

# StepFunctions
* AWS re:Invent2016 にてStepFunctionsがリリースされた
* 状態マシンを書いてLambdaの処理をさせることができるサービス

----------------------------------


# StepFunctionsの基本構文

-----
## StepFunctionオブジェクト

``` js
{
  "StartAt": "State名",
  "States": {
    "State名": {
      //Stateオブジェクト
    }
  }
}
```
------


## Stateオブジェクト

``` js
{
  "Type": "Stateタイプ",
  "Next": "State名", // Stateが実行された後に続けて実行されるState名
  "End": true // Stateが実行された後、終了する場合はtrueを指定する
}
```
![2016-12-13_12h17_08.png](https://qiita-image-store.s3.amazonaws.com/0/71143/37936131-3f7b-4865-88d2-0092f70b2a9f.png)

--------

# State.Type

----

## Task
LambdaのARNを指定して、実行することができる。

``` js
{
  "Type": "Task",
  "Resource": "LambdaのARN",
  "End": true
}
```

![2016-12-13_12h17_27.png](https://qiita-image-store.s3.amazonaws.com/0/71143/279b3bd6-b2dd-a08a-a3eb-6b54dc1a10b5.png)

-----

## Wait
指定した秒数か、指定した時刻がくるまで待たせることができる。

``` js
{
  "Type": "Wait",
  "Seconds": 10,
  /* または
  "Timestamp": "2015-09-04T01:59:00Z",
  "SecondsPath": "$.hogeTimestamp",
  "TimestampPath": "$.hogeSeconds",
  */
  "End": true
}
```

----

## Choice
前段の処理結果によって後続の処理を分岐する

``` js:Type=Choice
{
  "Type": "Choice",
  "Choices": [ { 
    // Choiceオブジェクト
  } ],
  "Default": "Choiceオブジェクトに該当しなかった場合に実行するState名"
}
```

![2016-12-13_12h40_13.png](https://qiita-image-store.s3.amazonaws.com/0/71143/471a36d8-c310-b709-c743-94155be9fc71.png)

----

# Choice
比較処理を行うメソッドはいくつもあるので、[要確認](http://docs.aws.amazon.com/step-functions/latest/dg/awl-ref-states-choice.html#awl-choice-rules)

``` js:Choiceオブジェクト
{
  "Variable": "前段の処理結果もらった変数のパス($.hogeとか)"
  "StringEquals": "↑で指定したパスから得られる文字列比較",
  "Next": "↑でチェックした内容がtrueであれば次に実行するState名"
}
```

----

# Choice

``` javascript:前段処理のjavascript
exports.handler = function(event, context, callback) {
  // 
  callback( null, {
    "hoge": "1"
  } );
};
```
-----

# Parallel
並列処理を行う
Branchesで配列を指定でき、Branchesの配列一つ一つには、さらに新規にStepFunctionオブジェクトを設定できる。

-----

# Parallel

``` js:JSON
{
  "Type": "Parallel",
  "Next": "NextWorld",
  "Branches": [ {
    // StepFunctionオブジェクト
  } ]
}
```

![2016-12-13_12h29_56.png](https://qiita-image-store.s3.amazonaws.com/0/71143/27f4d399-d407-312d-099e-049db0851c0b.png)

----

## その他のType
### Succeed
* そのタスクに来たら、強制的にStepFunctionが完了したことになる
* たとえばParallelでこれが実行されると、強制的にParallelを抜ける

``` js
{
  "Type": "Succeed"
}
```

-----
## その他のType
### Fail
* このタスクに来たら、強制的にStepFunctionが失敗したことになる

``` js
{
  "Type": "Fail",
  "Cause": "失敗した理由",
  "Error": "エラーオブジェクト"
}
```

-----
## その他のType
### Pass
* モックのような役割を果たし、次のタスクに渡したい値を設定できる。
* 前のタスクの変数に上書きしたりできる

``` js
{
  "Task": "Pass",
  "Result": { 
    // 次のタスクに渡したい値
  },
  "ResultPath": "前のタスクの変数のどこに格納するか($.hogeとか)"
}
```

-----

# 変数について
前段から返却されたパラメータについては、$を使ってアクセスすることができる。
たとえば、次のようなコードで値を返した場合、

----
# 変数について

``` js:前段のコード
exports.handler = function(event, context, callback) {
  callback( null, {
    "response": 20
  } );
};
```

----
# 変数について

変数として、`$`でアクセスすることができる。
例えばWaitのSecondPathの場合、

----
# 変数について

``` js:JSON
{
  "Type": "Wait",
  "SecondPath": "$.response"
  "Next": "NextWorld"
}
```

----
# 変数について
`$.response`で秒数を取得できる。
オブジェクトではなく、文字列などを返却した場合は$でその文字列にアクセスできる。
また、次のタスクでは前段から返却されたパラメータがそのまま変数として渡される。

-----

# TypeがTaskの時に指定できる特別な値

----

## Catch
Taskが何らかのエラーで失敗した場合に、Catchハンドラで捕まえてエラー時の処理を実行させることができます。

``` js:JSON
{
  "Type": "Task",
  "Resource": "ARN",
  "Catch": [ {
    "ErrorEquals": [ "HandledError" ],
    "Next": "NextWorld"
  } ],
  "End": true
},
"NextWorld": {
  // ...
}
```

----

## Retry
Catchとだいたい一緒です。
違いは、エラーになった場合に、指定した処理を実行するのではなく、再実行するところ。

``` js:JSON
{
  "Type": "Task",
  "Resource": "ARN",
  "Retry": {
    "ErrorEquals": ["HandledError"],
    "IntervalSeconds": 1, // 再実行するときにインターバルをあける
    "MaxAttempts": 2, // 再実行回数
    "BackoffRate": 2.0 // 再再実行するときにインターバルを何秒増やすか
  },
  "End": true
}
```

-----
# 参考
[AWS StepFunctions Overview](http://docs.aws.amazon.com/step-functions/latest/dg/awl-ref.html)