简体   繁体   中英

Parallel States Merge the output in Step Function

Is it possible to have following kind of Step Function graph, ie from 2 parallel state output, one combined state:

在此处输入图片说明

If yes, what would json for this looks like? If not, why?

A parallel task always outputs an array (containing one entry per branch).

You can tell AWS step functions to append the output into new (or existing) property in the original input with "ResultPath": "$.ParallelOut" in your parallel state definition, but this is not what you seem to be trying to achieve.

To merge the output of parallel task, you can leverage the "Type": "Pass" state to define transformations to apply to the JSON document.

For example, in the state machine below, I'm transforming a JSON array...

[
  {
    "One": 1,
    "Two": 2
  },
  {
    "Foo": "Bar",
    "Hello": "World"
  }
]

...into a few properties

{
  "Hello": "World",
  "One": 1,
  "Foo": "Bar",
  "Two": 2
}

使用 AWS Step Functions 将数组转换为属性

{
    "Comment": "How to convert an array into properties",
    "StartAt": "warm-up",
    "States": {
      "warm-up": {
        "Type": "Parallel",
        "Next": "array-to-properties",
        "Branches": [
          {
            "StartAt": "numbers",
            "States": {
              "numbers": {
                "Type": "Pass",
                "Result": {
                    "One": 1,
                    "Two" : 2
                },
                "End": true
              }
            }
          },
          {
            "StartAt": "words",
            "States": {
              "words": {
                "Type": "Pass",
                "Result": {
                    "Foo": "Bar",
                    "Hello": "World"
                },
                "End": true
              }
            }
          }
        ]
      },
      "array-to-properties": {
        "Type": "Pass",
        "Parameters": {
          "One.$": "$[0].One",
          "Two.$": "$[0].Two",
          "Foo.$": "$[1].Foo",
          "Hello.$": "$[1].Hello"
        },
        "End": true
      }
    }
}

It is possible as opposed diagram below

在此处输入图片说明

The parallel state should look like this

"MyParallelState": {
  "Type": "Parallel",
  "InputPath": "$",
  "OutputPath": "$",
  "ResultPath": "$.ParallelResultPath",
  "Next": "SetCartCompleteStatusState",
  "Branches": [
    {
      "StartAt": "UpdateMonthlyUsageState",
      "States": {
        "UpdateMonthlyUsageState": {
          "Type": "Task",
          "InputPath": "$",
          "OutputPath": "$",
          "ResultPath": "$.UpdateMonthlyUsageResultPath",
          "Resource": "LambdaARN",
          "End": true
        }
      }
    },
    {
      "StartAt": "QueueTaxInvoiceState",
      "States": {
        "QueueTaxInvoiceState": {
          "Type": "Task",
          "InputPath": "$",
          "OutputPath": "$",
          "ResultPath": "$.QueueTaxInvoiceResultPath",
          "Resource": "LambdaARN",
          "End": true
        }
      }
    }

The output of MyParallelState will be populated as in array, from each state in the Parallel state . They are populated within ParallelResultPath object and will be passed into the Next state

{
  "ParallelResultPath": [
    {
      "UpdateMonthlyUsageResultPath": Some Output
    },
    {
      "QueueTaxInvoiceResultPath": Some Output
    }
  ]
}

Your diagram is technically wrong because no state can set multiple states to its Next task. You cannot start State Machine as StartAt by providing multiple State names. Also, even if it was possible I don't see any point why would you want to run two parallel states as opposed to one parallel state with all the sub states that you would split into two.

We can use ResultSelector and Result Path to combine the result into one object

We have a parallel state like:

{
  "StartAt": "ParallelBranch",
  "States": {
    "ParallelBranch": {
      "Type": "Parallel",
      "ResultPath": "$",
      "InputPath": "$",
      "OutputPath": "$",
      "ResultSelector": {
        "UsersResult.$": "$[1].UsersUpload",
        "CustomersResult.$": "$[0].customersDataUpload"
      },
      "Branches": [
        {
          "StartAt": "customersDataUpload",
          "States": {
            "customersDataUpload": {
              "Type": "Pass",
              "ResultPath": "$.customersDataUpload.Output",
              "Result": {
                "CompletionStatus": "success",
                "CompletionDetails": null
              },
              "Next": "Wait2"
            },
            "Wait2": {
              "Comment": "A Wait state delays the state machine from continuing for a specified time.",
              "Type": "Wait",
              "Seconds": 2,
              "End": true
            }
          }
        },
        {
          "StartAt": "UsersUpload",
          "States": {
            "UsersUpload": {
              "Type": "Pass",
              "Result": {
                "CompletionStatus": "success",
                "CompletionDetails": null
              },
              "ResultPath": "$.UsersUpload.Output",
              "Next": "Wait1"
            },
            "Wait1": {
              "Comment": "A Wait state delays the state machine from continuing for a specified time.",
              "Type": "Wait",
              "Seconds": 1,
              "End": true
            }
          }
        }
      ],
      "End": true
    }
  },
  "TimeoutSeconds": 129600,
  "Version": "1.0"
}

enter image description here

And the output will be like:

{
  "UsersResult": {
    "Output": {
      "CompletionStatus": "success",
      "CompletionDetails": null
    }
  },
  "CustomersResult": {
    "Output": {
      "CompletionStatus": "success",
      "CompletionDetails": null
    }
  }
}

This worked for me

        "Transform And Freeze": {
          "Type": "Parallel",
          "InputPath": "$",
          "Branches": [
            {
              "StartAt": "Transform Status",
              "States": {
                "Transform Status": {
                  "Type": "Map",
                  "ItemsPath": "$",
                  "MaxConcurrency": 25,
                  "Iterator": {
                    "StartAt": "Transform",
                    "States": {
                      "Transform": {
                        "Type": "Task",
                        "Resource": "${TransformFunction}",
                        "End": true
                      }
                    }
                  },
                  "End": true
                }
              }
            },
            {
              "StartAt": "Freeze Status",
              "States": {
                "Freeze Status": {
                  "Type": "Map",
                  "MaxConcurrency": 25,
                  "Iterator": {
                    "StartAt": "Freeze",
                    "States": {
                      "Freeze Transactions": {
                        "Type": "Task",
                        "Resource": "${FreezeFunction}",
                        "End": true
                      }
                    }
                  },
                  "End": true
                }
              }
            }
          ],
          "ResultPath" : "$.parts",
          "Next": "SetParallelOutput",
          "Catch": [
            {
              "ErrorEquals": [
                "States.ALL"
              ],
              "ResultPath": "$.exception",
              "Next": "Error Handler"
            }
          ]
        },
        "SetParallelOutput": {
          "Type": "Pass",
          "Parameters": {
            "foo.$": "$.foo",
            "bar.$": "$.bar",
            "parts.$": "$.parts[0]"
          },
          "Next": "Target Type"
        },

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM