github.com/mweagle/Sparta@v1.15.0/aws/step/state_map.go (about) 1 package step 2 3 import ( 4 "math/rand" 5 ) 6 7 //////////////////////////////////////////////////////////////////////////////// 8 // MapState 9 //////////////////////////////////////////////////////////////////////////////// 10 11 /* 12 "Validate-All": { 13 "Type": "Map", 14 "InputPath": "$.detail", 15 "ItemsPath": "$.shipped", 16 "MaxConcurrency": 0, 17 "Iterator": { 18 "StartAt": "Validate", 19 "States": { 20 "Validate": { 21 "Type": "Task", 22 "Resource": "arn:aws:lambda:us-east-1:123456789012:function:ship-val", 23 "End": true 24 } 25 } 26 }, 27 "ResultPath": "$.detail.shipped", 28 "End": true 29 } 30 */ 31 32 // MapState is a synthetic state that executes a dynamically determined set 33 // of nodes in parallel 34 type MapState struct { 35 baseInnerState 36 States *StateMachine 37 Parameters map[string]interface{} 38 ResultPath string 39 ItemsPath string // optional 40 MaxConcurrency int //optional 41 Retriers []*TaskRetry 42 Catchers []*TaskCatch 43 } 44 45 // WithResultPath is the fluent builder for the result path 46 func (ms *MapState) WithResultPath(resultPath string) *MapState { 47 ms.ResultPath = resultPath 48 return ms 49 } 50 51 // WithRetriers is the fluent builder for TaskState 52 func (ms *MapState) WithRetriers(retries ...*TaskRetry) *MapState { 53 if ms.Retriers == nil { 54 ms.Retriers = make([]*TaskRetry, 0) 55 } 56 ms.Retriers = append(ms.Retriers, retries...) 57 return ms 58 } 59 60 // WithCatchers is the fluent builder for TaskState 61 func (ms *MapState) WithCatchers(catch ...*TaskCatch) *MapState { 62 if ms.Catchers == nil { 63 ms.Catchers = make([]*TaskCatch, 0) 64 } 65 ms.Catchers = append(ms.Catchers, catch...) 66 return ms 67 } 68 69 // Next returns the next state 70 func (ms *MapState) Next(nextState MachineState) MachineState { 71 ms.next = nextState 72 return nextState 73 } 74 75 // AdjacentStates returns nodes reachable from this node 76 func (ms *MapState) AdjacentStates() []MachineState { 77 if ms.next == nil { 78 return nil 79 } 80 return []MachineState{ms.next} 81 } 82 83 // Name returns the name of this Task state 84 func (ms *MapState) Name() string { 85 return ms.name 86 } 87 88 // WithComment returns the TaskState comment 89 func (ms *MapState) WithComment(comment string) TransitionState { 90 ms.comment = comment 91 return ms 92 } 93 94 // WithInputPath returns the TaskState input data selector 95 func (ms *MapState) WithInputPath(inputPath string) TransitionState { 96 ms.inputPath = inputPath 97 return ms 98 } 99 100 // WithOutputPath returns the TaskState output data selector 101 func (ms *MapState) WithOutputPath(outputPath string) TransitionState { 102 ms.outputPath = outputPath 103 return ms 104 } 105 106 // MarshalJSON for custom marshalling 107 func (ms *MapState) MarshalJSON() ([]byte, error) { 108 /* 109 A Map State MUST contain an object field named “Iterator” which MUST 110 contain fields named “States” and “StartAt”, whose meanings are exactly 111 like those in the top level of a State Machine. 112 113 A state in the “States” field of an “Iterator” field MUST NOT have a 114 “Next” field that targets a field outside of that “States” field. A state 115 MUST NOT have a “Next” field which matches a state name inside an 116 “Iterator” field’s “States” field unless it is also inside the same 117 “States” field. 118 119 Put another way, states in an Iterator’s “States” field can transition 120 only to each other, and no state outside of that “States” field can 121 transition into it. 122 */ 123 // Don't marshal the "End" flag 124 ms.States.disableEndState = true 125 additionalParams := make(map[string]interface{}) 126 additionalParams["Iterator"] = ms.States 127 if ms.ItemsPath != "" { 128 additionalParams["ItemsPath"] = ms.ItemsPath 129 } 130 if ms.ResultPath != "" { 131 additionalParams["ResultPath"] = ms.ResultPath 132 } 133 if len(ms.Retriers) != 0 { 134 additionalParams["Retry"] = ms.Retriers 135 } 136 if ms.Catchers != nil { 137 additionalParams["Catch"] = ms.Catchers 138 } 139 if ms.Parameters != nil { 140 additionalParams["Parameters"] = ms.Parameters 141 } 142 143 return ms.marshalStateJSON("Map", additionalParams) 144 } 145 146 // NewMapState returns a "MapState" with the supplied 147 // information 148 func NewMapState(parallelStateName string, states *StateMachine) *MapState { 149 return &MapState{ 150 baseInnerState: baseInnerState{ 151 name: parallelStateName, 152 id: rand.Int63(), 153 }, 154 States: states, 155 } 156 }