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  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  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