[英]How to get Task Token in AWS Lambda Function
我有一个 AWS Step Function 和在 Java 中实现的处理程序。
我的步骤 function 定义:
definition:
Comment: Steps for issuing a card
StartAt: RecipientFraudChecks
States:
RecipientFraudChecks:
Type: Task
Next: SaveTaskToken
Resource: arn:aws:lambda:eu-west-1:099720403855:RecipientFraudChecks
SaveTaskToken:
Type: Task
Resource: arn:aws:lambda:eu-west-1:12345678:function:SaveTaskToken
End: true
我有一个 Java 项目,所有 Lambda Function 处理程序都在那里定义:
public class SaveTaskToken implements RequestHandler<Map<String,String>, String> {
....
@Override
public String handleRequest(Map<String, String> input, final Context context) {
// do the fraud checks
System.out.println("the context is: " + gson.toJson(context));
System.out.println("input: " + gson.toJson(input));
}
我正在使用 AWS SAM 在本地运行步骤 function,并根据此触发: https://docs.aws.amazon.com/step-functions/latest/dg/sfn-local-lambda.html#install-sam
在context
,我希望看到任务令牌,但我没有。 日志显示:
the context is: {
"memoryLimit": 512,
"awsRequestId": "5065a9aa-1a4a-46fe-9b58-7dc2194f92b7",
"logGroupName": "aws/lambda/SaveTaskToken",
"logStreamName": "$LATEST",
"functionName": "SaveTaskToken",
"functionVersion": "$LATEST",
"invokedFunctionArn": "",
"cognitoIdentity": {
"identityId": "",
"poolId": ""
},
"logger": {}
}
事实上,它与我在文档中所期望的全局上下文完全不同。
我究竟做错了什么? 如何获得任务令牌?
编辑
我将Parameters
属性添加到“SaveTaskToken”并将资源更改为arn:aws:states:::lambda:invoke.waitForTaskToken
并且知道我可以获得任务令牌:
definition:
Comment: Steps for issuing a card
StartAt: RecipientFraudChecks
States:
RecipientFraudChecks:
Type: Task
Next: SaveTaskToken
Resource: arn:aws:lambda:eu-west-1:099720403855:RecipientFraudChecks
SaveTaskToken:
Type: Task
Resource: arn:aws:states:::lambda:invoke.waitForTaskToken
Parameters:
FunctionName: arn:aws:lambda:eu-west-1:12345678:function:SaveTaskToken
Payload:
taskToken
End: true
在日志中我可以看到:
the input is: {
"taskToken": "5286"
}
它引起了另一个问题 - 它覆盖了 state 机器的输入。 我传入输入:
{"giftCode": "xxx"}
在第一个 Lambda function, RecipientFraudChecks
中,我可以得到输入。 但是,在第二个中,由于添加了Parameters
属性,我现在无法再获得state机器的输入,只有任务令牌......
编辑在这里实现了答案: https://stackoverflow.com/a/66995869/1246159
{
"Comment": "Steps for issuing a card",
"StartAt": "RecipientFraudChecks",
"States": {
"RecipientFraudChecks": {
"Type": "Task",
"Next": "PauseCardIfNecessary",
"ResultPath": "$.firstLambdaOutput",
"Resource": "arn:aws:lambda:us-east-1:123456789012:function:RecipientFraudChecks"
},
"PauseCardIfNecessary": {
"Type": "Task",
"Next": "GetOrCreateClient",
"Resource": "arn:aws:states:::lambda:invoke.waitForTaskToken",
"Parameters": {
"FunctionName": "arn:aws:lambda:us-east-1:123456789012:function:PauseCardIfNecessary",
"Payload": {
"token.$": "$$.Task.Token",
"otherInput.$": "$"
}
}
},
"GetOrCreateClient": {
"Type": "Task",
"Next": "GetOrAccountClient",
"Resource": "arn:aws:lambda:us-east-1:123456789012:function:GetOrCreateClient"
},
"GetOrAccountClient": {
"Type": "Task",
"Resource": "arn:aws:lambda:us-east-1:123456789012:function:GetOrAccountClient",
"End": true
}
}
}
但我得到另一个错误,这里是日志:
arn: aws: states: eu-west-1: 123456789012: execution: HelloWorld5: cardIssue: {
"Type": "TaskStateExited",
"PreviousEventId": 5,
"StateExitedEventDetails": {
"Name": "RecipientFraudChecks",
"Output": "{\"inputToStep\":\"xxxx\",\"firstLambdaOutput\":\"output of recipient lambda\"}"
}
} arn: aws: states: eu-west-1: 123456789012: execution: HelloWorld5: cardIssue: {
"Type": "TaskStateEntered",
"PreviousEventId": 6,
"StateEnteredEventDetails": {
"Name": "PauseCardIfNecessary",
"Input": "{\"inputToStep\":\"xxxx\",\"firstLambdaOutput\":\"output of recipient lambda\"}"
}
} arn: aws: states: eu-west-1: 123456789012: execution: HelloWorld5: cardIssue: {
"Type": "ExecutionFailed",
"PreviousEventId": 7,
"ExecutionFailedEventDetails": {
"Error": "States.Runtime",
"Cause": "An error occurred while executing the state 'PauseCardIfNecessary' (entered at the event id #7). The value for the field 'token.$' must be a valid JSONPath expression"
}
}
任务令牌不会在 lambda 上下文中自动传递,它需要作为输入传递。
这里的上下文不是 lambda function 的上下文,而是任务的上下文以及从上下文中获取细节,我们可以使用$$.
在步骤 function 定义内,例如:
$$.Task.Token
$$.Execution.StartTime
示例步骤 function:
waitForTaskToken
执行另一个 lambda ,在这里,我们获取任务令牌并将其与上一步的 output 作为输入一起传递。{
"StartAt": "fist-lambda-invoke-sync",
"States": {
"fist-lambda-invoke-sync": {
"Next": "second-lambda-invoke-task-token",
"Type": "Task",
"ResultPath": "$.firstLambdaOutput",
"Resource": "arn:aws:lambda:us-east-1:11112223333:function:myfirstlambda"
},
"second-lambda-invoke-task-token": {
"End": true,
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke.waitForTaskToken",
"Parameters": {
"FunctionName": "arn:aws:lambda:us-east-1:11112223333:function:mysecondlambda",
"Payload": {
"token.$": "$$.Task.Token",
"otherInput.$": "$"
}
}
}
}
}
输入到步骤 function :
{
"inputToStep": "myValue"
}
第一个 Lambda 的 Output :假设它是一个字符串值“10”。 它将被附加到输入 Json 因为"ResultPath": "$.firstLambdaOutput"
{
"inputToStep": "myValue",
"firstLambdaOutput": "10"
}
第二个 Lambda 的输入:将在 json 下方接收作为附加任务令牌的输入,因为"token.$": "$$.Task.Token"
和"otherInput.$": "$"
{ otherInput: { inputToStep: 'myValue', firstLambdaOutput: '10' },
token: 'This is where Task Token generated by step function will be sent' }
关于输入,文档 [1] 中似乎有一个简单的解决方案:
您可以使用来自 state 机器执行的输入,而不是在 state 机器定义中硬编码事件负载。 以下示例使用运行 state 机器时指定的输入作为事件负载:
"Payload.$": "$"
文档 [2] 中还有另一个示例:
{
"StartAt":"GetManualReview",
"States":{
"GetManualReview":{
"Type":"Task",
"Resource":"arn:aws:states:::lambda:invoke.waitForTaskToken",
"Parameters":{
"FunctionName":"get-model-review-decision",
"Payload":{
"model.$":"$.new_model",
"token.$":"$$.Task.Token"
},
"Qualifier":"prod-v1"
},
"End":true
}
}
}
您可以将"model.$":"$.new_model"
更改为类似"input.$":"$"
并获得所需的 Lambda 有效负载。
在 YAML 中转换为以下内容:
Parameters:
Payload:
input.$: "$"
token.$: "$$.Task.Token"
[1] https://docs.aws.amazon.com/lambda/latest/dg/services-stepfunctions.html#services-stepfunctions-setup
[2] https://docs.amazonaws.cn/en_us/step-functions/latest/dg/connect-lambda.html
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.