本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
使用变量在状态之间传递数据
使用变量管理状态和 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 子工作流程中的数据,并在状态机执行结束时返回。
支持变量的状态
以下状态类型支持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
总是指原始状态输入。
对于Task
Parallel
、和Map
状态:
-
$states.result
如果成功,则指 API 或子工作流程的原始结果。 -
$states.errorOutput
指的是 API 或子工作流程失败时的错误输出。$states.errorOutput
可以用于该Catch
领域的Assign
或Output
。
$states.errorOutput
在创建、更新$states.result
或验证状态机时,如果尝试访问或处于无法访问的字段和状态,则会被捕获。
该$states.context
对象为您的工作流程提供有关其特定执行的信息StartTime
,例如任务令牌和初始工作流程输入。要了解更多信息,请参阅 在 Step Functions 中从 Context 对象访问执行数据 。
变量名语法
变量名称遵循 Unicode ® 标准附录 #31 中所述的 Unicode
变量名惯例类似于 JavaScript 和其他编程语言的规则。
变量范围
Step Functions 工作流程通过使用工作流局部作用域来避免与变量的争用条件。
Workflow-Local 范围包括状态机的 States 字段内的所有状态,但不包括平行或地图状态内的状态。Parallel 或 Map 状态内的状态可以引用外部作用域变量,但它们创建和维护自己的独立工作流局部变量和值。
Parallel
分支和Map
迭代可以从外部作用域访问变量值,但它们无法访问其他并发分支或迭代中的变量值。处理错误时,a 中的Assign
字段Catch
可以为外部作用域(即 Parallel/Map 状态存在的范围)中的变量赋值。
例外:分布式地图状态目前无法引用外部作用域中的变量。
如果作用域中的任何状态为变量赋值,则该变量就存在于该作用域中。为了避免常见错误,在内部作用域中分配的变量不能与在外部作用域中分配的变量同名。例如,如果顶级作用域为名为的变量赋值myVariable
,则其他作用域(在 a Map
中Parallel
)myVariable
也不能赋值。
对变量的访问取决于当前范围。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 对象。每个顶级字段都命名一个要分配的变量。在前面的示例中,变量名为desiredPrice
和maximumWait
。使用时 JSONata,{% ... %}
表示 JSONata 表达式可能包含变量或更复杂的表达式。有关 JSONata 表达式的更多信息,请参阅 JSONata.org 文档
使用JSONata作为查询语言时,下图显示了如何并行处理 “分配” 和 “输出” 字段。注意其含义:分配变量值不会影响状态输出。
以下 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)。以下步骤描述了此过程:
-
使用所有变量的当前值计算所有表达式。
表达式的计算结果
"{% $a %}"
将为 6,"{% $x %}"
计算结果为 3。 -
接下来,进行作业:
$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:
在中分配变量 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,
Map
Parallel
状态中,$
指的是 API/子工作流程结果。in Choice
an Wait
d state,$
指有效输入,即应用于状态输入之后的InputPath
值。对于Pass
,$
是指由字段还是InputPath
/Result
Parameters
字段生成的结果。
以下 JSONPath 示例将一个 JSON 对象分配给details
变量,将 JSONPath 表达式的结果分配$.result.code
给resultCode
,将表达 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"
}