github.com/mweagle/Sparta@v1.15.0/docs_source/content/reference/step/lambda.md (about)

     1  ---
     2  date: 2018-12-10 21:45:23
     3  title: Lambda
     4  weight: 10
     5  ---
     6  
     7  # Step Functions
     8  
     9  AWS [Step Functions](https://aws.amazon.com/step-functions/) are a powerful way to express long-running, complex workflows comprised of Lambda functions. With Sparta 0.20.2, you can build a State Machine as part of your application. This section walks through the three steps necessary to provision a sample "Roll Die" state machine using a single Lambda function. See [SpartaStep](https://github.com/mweagle/SpartaStep) for the full source.
    10  
    11  ## Lambda Functions
    12  
    13  The first step is to define the core Lambda function [Task](http://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-task-state.html) that will be our Step function's core logic. In this example, we'll define a _rollDie_ function:
    14  
    15  ```go
    16  type lambdaRollResponse struct {
    17    Roll int `json:"roll"`
    18  }
    19  
    20  // Standard AWS λ function
    21  func lambdaRollDie(ctx context.Context) (lambdaRollResponse, error) {
    22    return lambdaRollResponse{
    23      Roll: rand.Intn(5) + 1,
    24    }, nil
    25  }
    26  ```
    27  
    28  ### State Machine
    29  
    30  Our state machine is simple: we want to keep rolling the die until we get a "good" result, with a delay in between rolls:
    31  
    32  ![State Machine](/images/step_functions/roll_die.jpg)
    33  
    34  To do this, we use the new `github.com/mweagle/Sparta/aws/step` functions to define the other states.
    35  
    36  ```go
    37  // Make all the Step states
    38  lambdaTaskState := step.NewTaskState("lambdaRollDie", lambdaFn)
    39  successState := step.NewSuccessState("success")
    40  delayState := step.NewWaitDelayState("tryAgainShortly", 3*time.Second)
    41  lambdaChoices := []step.ChoiceBranch{
    42    &step.Not{
    43      Comparison: &step.NumericGreaterThan{
    44        Variable: "$.roll",
    45        Value:    3,
    46      },
    47      Next: delayState,
    48    },
    49  }
    50  choiceState := step.NewChoiceState("checkRoll",
    51    lambdaChoices...).
    52    WithDefault(successState)
    53  ```
    54  
    55  The Sparta state types correspond to their [AWS States Spec](https://states-language.net/spec.html) equivalents:
    56  
    57    - `successState` : [SucceedState](https://states-language.net/spec.html#succeed-state)
    58    - `delayState` : a specialized [WaitState](https://states-language.net/spec.html#wait-state)
    59    - `choiceState`: [ChoiceState](https://states-language.net/spec.html#choice-state)
    60  
    61  The `choiceState` is the most interesting state: based on the JSON response of the `lambdaRollDie`, it will either transition
    62  to a delay or the success end state.
    63  
    64  See [godoc](https://godoc.org/github.com/mweagle/Sparta/aws/step) for the complete set of types.
    65  
    66  The `lambdaTaskState` uses a normal Sparta function as in:
    67  
    68  ```go
    69  lambdaFn, _ := sparta.NewAWSLambda("StepRollDie",
    70    lambdaRollDie,
    71    sparta.IAMRoleDefinition{})
    72  
    73  lambdaFn.Options.MemorySize = 128
    74  lambdaFn.Options.Tags = map[string]string{
    75    "myAccounting": "tag",
    76  }
    77  ```
    78  
    79  The final step is to hook up the state transitions for states that don't implicitly include them, and create the State Machine:
    80  
    81  ```go
    82  // Hook up the transitions
    83  lambdaTaskState.Next(choiceState)
    84  delayState.Next(lambdaTaskState)
    85  
    86  // Startup the machine with a user-scoped name for account uniqueness
    87  stateMachineName := spartaCF.UserScopedStackName("StateMachine")
    88  startMachine := step.NewStateMachine(stateMachineName, lambdaTaskState)
    89  ```
    90  
    91  At this point we have a potentially well-formed [Lambda-powered](http://docs.aws.amazon.com/step-functions/latest/dg/tutorial-creating-lambda-state-machine.html) State Machine.
    92  The final step is to attach this machine to the normal service definition.
    93  
    94  ### Service Decorator
    95  
    96  The return type from `step.NewStateMachine(...)` is a `*step.StateMachine` instance that exposes a [ServiceDecoratorHook](https://godoc.org/github.com/mweagle/Sparta#ServiceDecoratorHook).
    97  Adding the hook to your service's Workflow Hooks (similar to provisioning a service-scoped [CloudWatch Dashboard](https://github.com/mweagle/Sparta/blob/master/CHANGES.md#v0130))
    98  will include it in the CloudFormation template serialization:
    99  
   100  ```go
   101  // Setup the hook to annotate
   102  workflowHooks := &sparta.WorkflowHooks{
   103    ServiceDecorator: startMachine.StateMachineDecorator(),
   104  }
   105  userStackName := spartaCF.UserScopedStackName("SpartaStep")
   106  err := sparta.MainEx(userStackName,
   107    "Simple Sparta application that demonstrates AWS Step functions",
   108    lambdaFunctions,
   109    nil,
   110    nil,
   111    workflowHooks,
   112    false)
   113  ```
   114  
   115  With the decorator attached, the next service `provision` request will include the state machine as above.
   116  
   117  ```text
   118  
   119  $ go run main.go provision --s3Bucket weagle
   120  INFO[0000] ════════════════════════════════════════════════
   121  INFO[0000] ╔═╗┌─┐┌─┐┬─┐┌┬┐┌─┐   Version : 1.0.2
   122  INFO[0000] ╚═╗├─┘├─┤├┬┘ │ ├─┤   SHA     : b37b93e
   123  INFO[0000] ╚═╝┴  ┴ ┴┴└─ ┴ ┴ ┴   Go      : go1.9.2
   124  INFO[0000] ════════════════════════════════════════════════
   125  INFO[0000] Service: SpartaStep-mweagle                   LinkFlags= Option=provision UTC="2018-01-29T14:33:36Z"
   126  INFO[0000] ════════════════════════════════════════════════
   127  INFO[0000] Provisioning service                          BuildID=f7ade93d3900ab4b01c468c1723dedac24cbfa93 CodePipelineTrigger= InPlaceUpdates=false NOOP=false Tags=
   128  INFO[0000] Verifying IAM Lambda execution roles
   129  INFO[0000] IAM roles verified                            Count=1
   130  INFO[0000] Checking S3 versioning                        Bucket=weagle VersioningEnabled=true
   131  INFO[0000] Checking S3 region                            Bucket=weagle Region=us-west-2
   132  INFO[0000] Running `go generate`
   133  INFO[0000] Compiling binary                              Name=Sparta.lambda.amd64
   134  INFO[0010] Creating code ZIP archive for upload          TempName=./.sparta/SpartaStep_mweagle-code.zip
   135  INFO[0010] Lambda code archive size                      Size="13 MB"
   136  INFO[0010] Uploading local file to S3                    Bucket=weagle Key=SpartaStep-mweagle/SpartaStep_mweagle-code.zip Path=./.sparta/SpartaStep_mweagle-code.zip Size="13 MB"
   137  INFO[0020] Calling WorkflowHook                          ServiceDecoratorHook="github.com/mweagle/Sparta/aws/step.(*StateMachine).StateMachineDecorator.func1" WorkflowHookContext="map[]"
   138  INFO[0020] Uploading local file to S3                    Bucket=weagle Key=SpartaStep-mweagle/SpartaStep_mweagle-cftemplate.json Path=./.sparta/SpartaStep_mweagle-cftemplate.json Size="3.7 kB"
   139  INFO[0021] Creating stack                                StackID="arn:aws:cloudformation:us-west-2:123412341234:stack/SpartaStep-mweagle/6ff65180-0501-11e8-935b-50a68d01a629"
   140  INFO[0094] CloudFormation provisioning metrics:
   141  INFO[0094] Operation duration                            Duration=54.73s Resource=SpartaStep-mweagle Type="AWS::CloudFormation::Stack"
   142  INFO[0094] Operation duration                            Duration=19.02s Resource=IAMRole49969e8a894b9eeea02a4936fb9519f2bd67dbe6 Type="AWS::IAM::Role"
   143  INFO[0094] Operation duration                            Duration=18.69s Resource=StatesIAMRolee00aa3484b0397c676887af695abfd160104318a Type="AWS::IAM::Role"
   144  INFO[0094] Operation duration                            Duration=2.60s Resource=StateMachine59f153f18068faa0b7fb588350be79df422ba5ef Type="AWS::StepFunctions::StateMachine"
   145  INFO[0094] Operation duration                            Duration=2.28s Resource=StepRollDieLambda7d9f8ab476995f16b91b154f68e5f5cc42601ebf Type="AWS::Lambda::Function"
   146  INFO[0094] Stack provisioned                             CreationTime="2018-01-29 14:33:56.7 +0000 UTC" StackId="arn:aws:cloudformation:us-west-2:123412341234:stack/SpartaStep-mweagle/6ff65180-0501-11e8-935b-50a68d01a629" StackName=SpartaStep-mweagle
   147  INFO[0094] ════════════════════════════════════════════════
   148  INFO[0094] SpartaStep-mweagle Summary
   149  INFO[0094] ════════════════════════════════════════════════
   150  INFO[0094] Verifying IAM roles                           Duration (s)=0
   151  INFO[0094] Verifying AWS preconditions                   Duration (s)=0
   152  INFO[0094] Creating code bundle                          Duration (s)=10
   153  INFO[0094] Uploading code                                Duration (s)=10
   154  INFO[0094] Ensuring CloudFormation stack                 Duration (s)=73
   155  INFO[0094] Total elapsed time                            Duration (s)=94
   156  ```
   157  
   158  ### Testing
   159  
   160  With the stack provisioned, the final step is to test the State Machine and see how lucky our die roll is. Navigate to the **Step Functions**
   161  service dashboard in the AWS Console and find the State Machine that was provisioned. Click the **New Execution** button and accept the default JSON.
   162  This sample state machine doesn't interrogate the incoming data so the initial JSON is effectively ignored.
   163  
   164  For this test the first roll was a `4`, so there was only 1 path through the state machine. Depending on your
   165  die roll, you may see different state machine paths through the `WaitState`.
   166  
   167  ![State Machine](/images/step_functions/step_execution.jpg)
   168  
   169  ## Wrapping Up
   170  
   171  AWS Step Functions are a powerful tool that allows you to orchestrate long running workflows using AWS Lambda. State functions
   172  are useful to implement the Saga pattern as in [here](http://theburningmonk.com/2017/07/applying-the-saga-pattern-with-aws-lambda-and-step-functions/) and
   173  [here](https://read.acloud.guru/how-the-saga-pattern-manages-failures-with-aws-lambda-and-step-functions-bc8f7129f900). They can also be used
   174  to compose Lambda functions into more complex workflows that include [parallel](https://states-language.net/spec.html#parallel-state) operations
   175  on shared data.
   176  
   177  # Notes
   178  
   179  - Minimal State machine validation is done at this time. See [Tim Bray](https://www.tbray.org/ongoing/When/201x/2016/12/01/J2119-Validator) for more information.
   180  - Value interrogation is defined by [JSONPath](http://goessner.net/articles/JsonPath/) expressions