如何在 AWS Lambda 函数中获取任务令牌

Mar*_*ark 5 java amazon-web-services aws-lambda aws-step-functions

我有一个 AWS Step Function 和用 Java 实现的处理程序。

我的步骤函数定义:

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
Run Code Online (Sandbox Code Playgroud)

我有一个 Java 项目,所有的 Lambda 函数处理程序都在那里定义:

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));

}
Run Code Online (Sandbox Code Playgroud)

我正在使用 AWS SAM 在本地运行 step 函数,并根据此触发: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": {}
}
Run Code Online (Sandbox Code Playgroud)

事实上,它与我在文档中所期望的全局上下文完全不同。

我究竟做错了什么?如何获得任务令牌?

编辑

我将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
Run Code Online (Sandbox Code Playgroud)

在日志中,我可以看到:

the input is: {
  "taskToken": "5286"
}
Run Code Online (Sandbox Code Playgroud)

它导致了另一个问题——它覆盖了状态机的输入。我传入了输入:

{"giftCode": "xxx"}
Run Code Online (Sandbox Code Playgroud)

在第一个 Lambda 函数 中RecipientFraudChecks,我可以获得输入。但是,在第二个中,由于添加了Parameters属性,我现在无法再获得状态机的输入,只有任务令牌......

编辑 在这里实现了答案: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
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

但是我收到另一个错误,这是日志:

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"
  }
}
Run Code Online (Sandbox Code Playgroud)

Bal*_*ala 12

任务令牌不会自动在 lambda 上下文中传递,它需要作为输入传递。

这里的上下文不是 lambda 函数的上下文,而是任务的上下文,为了从上下文中获取详细信息,我们可以在步骤函数定义中使用$$.例如:

  • 获取任务令牌$$.Task.Token
  • 获取开始时间$$.Execution.StartTime

步骤函数示例:

  • 第一个任务使用步骤函数输入执行 Lambda。
  • 将第一个 lambda 的输出附加到阶跃函数输入。
  • 第二个任务使用资源执行另一个 lambda waitForTaskToken,在这里,我们获取任务令牌并将其与上一步的输出一起作为输入传递。
  • 步骤函数等待直到获得SendTaskSuccessSendTaskFailure

在此输入图像描述

{
  "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.$": "$"
        }
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

Step 函数的输入

{
  "inputToStep": "myValue"
}
Run Code Online (Sandbox Code Playgroud)

第一个 Lambda 的输出:假设它是字符串值“10”。它将被附加到输入 Json 中,因为"ResultPath": "$.firstLambdaOutput"

{
  "inputToStep": "myValue",
  "firstLambdaOutput": "10"
}
Run Code Online (Sandbox Code Playgroud)

第二个 Lambda 的输入:将收到以下 json 作为输入并附加任务令牌,因为"token.$": "$$.Task.Token""otherInput.$": "$"

{ otherInput: { inputToStep: 'myValue', firstLambdaOutput: '10' },
  token: 'This is where Task Token generated by step function will be sent' } 
Run Code Online (Sandbox Code Playgroud)