使用变量在状态之间传递数据 - Amazon Step Functions
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用变量在状态之间传递数据

使用变量管理状态和 JSONata

Step Functions 最近添加了变量 JSONata ,用于管理状态和转换数据。

要了解更多信息,请阅读博客文章 “使用变量简化开发者体验 JSONata ” 和 Amazon Step Functions

使用变量和状态输出,您可以在工作流程的各个步骤之间传递数据。

使用工作流变量,可以在步骤中存储数据,并在将来的步骤中检索该数据。例如,您可以存储包含稍后可能需要的数据的 API 响应。相反,状态输出只能用作下一步的输入。

变量的概念概述

使用工作流程变量,您可以存储数据以备日后参考。例如,步骤 1 可能会存储 API 请求的结果,以便稍后在步骤 5 中重复使用该请求的一部分。

在以下场景中,状态机从 API 获取数据一次。在步骤 1 中,工作流程将返回的 API 数据(每个状态最多 256 KiB)存储在变量 'x' 中,以便在后续步骤中使用。

如果没有变量,则需要将数据通过从步骤 1 到步骤 2 的输出传递到步骤 3 再到步骤 4,才能在步骤 5 中使用。如果这些中间步骤不需要数据怎么办? 通过输出和输入将数据从一个州传递到另一个州将是不必要的。

使用变量,您可以存储数据并在将来的任何步骤中使用它。您还可以在不中断数据流的情况下修改、重新排列或添加步骤。考虑到变量的灵活性,您可能只需要使用 O ut put 来返回 Parallel 和 Map 子工作流程中的数据,并在状态机执行结束时返回。

Diagram showing step 1 assigning a value to $x, used in step 5.

支持变量的状态

以下状态类型支持Assign为变量声明和赋值:通过、任务、地图、并行、选择、等待。

要设置变量,请提供一个包含变量名称和值的 JSON 对象:

"Assign": { "productName": "product1", "count" : 42, "available" : true }

要引用变量,请在名称前面加上美元符号 ($),例如。$productName

保留变量:$states

Step Functions 定义了一个名为的保留变量$states。在 JSONata 状态中,分配了以下结构以$states供在 JSONata 表达式中使用:

# Reserved $states variable in JSONata states $states = { "input": // Original input to the state "result": // API or sub-workflow's result (if successful) "errorOutput": // Error Output (only available in a Catch) "context": // Context object }

进入状态时,Step Functions 会将状态输入分配给。$states.input的值$states.input可用于所有接受 JSONata 表达式的字段。 $states.input总是指原始状态输入。

对于TaskParallel、和Map状态:

  • $states.result如果成功,则指 API 或子工作流程的原始结果。

  • $states.errorOutput指的是 API 或子工作流程失败时的错误输出。

    $states.errorOutput可以用于该Catch领域的AssignOutput

$states.errorOutput在创建、更新$states.result或验证状态机时,如果尝试访问或处于无法访问的字段和状态,则会被捕获。

$states.context对象为您的工作流程提供有关其特定执行的信息StartTime,例如任务令牌和初始工作流程输入。要了解更多信息,请参阅 在 Step Functions 中从 Context 对象访问执行数据

变量名语法

变量名称遵循 Unicode ® 标准附录 #31 中所述的 Unicode 标识符规则。变量名的第一个字符必须是 Unicode ID_Start 字符,第二个及后续字符必须是 Unicode ID_Continue 字符。变量名的最大长度为 80。

变量名惯例类似于 JavaScript 和其他编程语言的规则。

变量范围

Step Functions 工作流程通过使用工作流局部作用域来避免与变量的争用条件。

Workflow-Local 范围包括状态机的 States 字段内的所有状态,但不包括平行或地图状态内的状态。Parallel 或 Map 状态内的状态可以引用外部作用域变量,但它们创建和维护自己的独立工作流局部变量和值。

Parallel分支和Map迭代可以从外部作用域访问变量值,但它们无法访问其他并发分支或迭代中的变量值。处理错误时,a 中的Assign字段Catch可以为外部作用域(即 Parallel/Map 状态存在的范围)中的变量赋值。

例外:分布式地图状态目前无法引用外部作用域中的变量。

如果作用域中的任何状态为变量赋值,则该变量就存在于该作用域中。为了避免常见错误,在内部作用域中分配的变量不能与在外部作用域中分配的变量同名。例如,如果顶级作用域为名为的变量赋值myVariable,则其他作用域(在 a MapParallelmyVariable也不能赋值。

对变量的访问取决于当前范围。Parallel 和 Map 状态有自己的作用域,但可以访问外部作用域中的变量。

当 Parallel 或 Map 状态完成时,它们的所有变量都将超出范围并停止可访问。使用 O utput 字段将数据传递出并行分支和 Map 迭代。

在 ASL 中分配字段

ASL 中的Assign字段用于为一个或多个变量赋值。该Assign字段位于每个状态(Succeed和除外Fail)、内部Choice州规则和内部Catch字段的顶层。例如:

# Example of Assign with JSONata "Store inputs": { "Type": "Pass", "Next": "Get Current Price", "Comment": "Store the input desired price into a variable: $desiredPrice", "Assign": { "desiredPrice": "{% $states.input.desired_price %}", "maximumWait": "{% $states.input.max_days %}" } },

Assign字段采用一个 JSON 对象。每个顶级字段都命名一个要分配的变量。在前面的示例中,变量名为desiredPricemaximumWait。使用时 JSONata,{% ... %}表示 JSONata 表达式可能包含变量或更复杂的表达式。有关 JSONata 表达式的更多信息,请参阅 JSONata.org 文档

使用JSONata作为查询语言时,下图显示了如何并行处理 “分配” 和 “输出” 字段。注意其含义:分配变量值不会影响状态输出

Diagram showing a comparison of JSONPath and JSONata flow.

以下 JSONata 示例order.product从状态输入中检索。该变currentPrice量设置为任务结果中的一个值。

# Example of Task with JSONata assignment from result { "Type": "Task", ... "Assign": { "product": "{% $states.input.order.product %}", "currentPrice": "{% $states.result.Payload.current_price %}" }, "Next": "the next state" }

注意:不能为变量的一部分赋值。例如,你可以"Assign":{"x":42},但不能"Assign":{"x.y":42}"Assign":{"x[2]":42}

分配字段中的评估顺序

Step Functions 状态中的所有变量引用都使用状态输入时的值。

前面的事实对于了解该Assign字段如何为一个或多个变量赋值非常重要。首先,计算新值,然后 Step Functions 将新值分配给变量。新的变量值将从下一个状态开始可用。例如,考虑以下Assign字段:

# Starting values: $x=3, $a=6 "Assign": { "x": "{% $a %}", "nextX": "{% $x %}" } # Ending values: $x=6, $nextX=3

在前面的示例中,变量既x被赋值,又被引用。

请记住,首先对所有表达式进行求值,然后进行赋值。新分配的值将在下一个状态下可用。

让我们详细看一下这个例子。假设在之前的状态下,$x被分配的值为三 (3),$a被分配的值为六 (6)。以下步骤描述了此过程:

  1. 使用所有变量的当前值计算所有表达式。

    表达式的计算结果"{% $a %}"将为 6,"{% $x %}"计算结果为 3。

  2. 接下来,进行作业:

    $x将被分配为六 (6) 的值

    $nextX将被分配三 (3)

注意:如果$x之前未分配过,则该示例将失败,因为$x未定义

总而言之,Step Functions 会评估所有表达式,然后进行赋值。变量在Assign字段中出现的顺序关紧要。

限制

对于标准和快速工作流程,单个变量的最大大小为 256Kib。

单个Assign字段中所有变量的最大组合大小也为 256Kib。例如,您可以将 X 和 Y 分配给 128KiB,但不能在同一个字段中将 X 和 Y 同时分配给 256KiB。Assign

每次执行时,所有存储变量的总大小不能超过 10MiB。

在 JSONPath 状态中使用变量

变量在使用 JSONPath 查询语言的状态中也可用。

你可以在任何接受 JSONpath 表达式($.$$.语法)的字段中引用变量,但除外ResultPath,它在状态输入中指定了注入状态结果的位置。变量不能在中使用ResultPath

在中 JSONPath,$符号指的是 “当前” 值并$$表示状态上下文对象。 JSONPath 表达式可以以 as 开头,$.$.customer.name。您可以使用 a $$. s in 访问上下文$$.Execution.Id

要引用变量,也可以在变量名前使用$符号,例如$x$order.numItems

例如,在接受内部函数的 JSONPath字段中,可以在参数中使用变量。States.Format('The order number is {}', $order.number)

下图说明了任务中的分配步骤是如何与JSONPath任务同时发生的 ResultSelector:

Logical diagram of a state that uses JSONPath query language.

在中分配变量 JSONPath

JSONPath 变量赋值的行为与有效载荷模板类似。以结尾的字段.$表示值是一个 JSONPath 表达式,Step Functions 在状态机执行期间将其计算为一个值(例如:$.order..product$.order.total)。

# Example of Assign with JSONPath { "Type": "Task", ... "Assign": { "products.$": "$.order..product", "orderTotal.$": "$.order.total" }, "Next": "the next state" }

对于 JSONPath 州,Assign字段$中的值取决于状态类型。在Task,MapParallel状态中,$指的是 API/子工作流程结果。in Choice an Wait d state,$有效输入,即应用于状态输入之后的InputPath值。对于Pass$是指由字段还是InputPath/ResultParameters字段生成的结果。

以下 JSONPath 示例将一个 JSON 对象分配给details变量,将 JSONPath 表达式的结果分配$.result.coderesultCode,将表达 JSONPath 式的结果分配States.Format('Hello {}', $customer.name)message。如果处于Task状态,则$$.order.items和中$.result.code指的是 API 结果。使用来自 Context 对象的值为该startTime变量赋值$$.Execution.StartTime

"Assign": { "details": { "status": "SUCCESS", "lineItems.$": "$.order.items" }, "resultCode.$": "$.result.code", "message.$": "States.Format('Hello {}', $customer.name)", "startTime.$": "$$.Execution.StartTime" }