-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
StepFunctions - RunLambdaTask with Payload not working #7371
Comments
I confirm the issue. Experienced with just simple replace of |
Hi sacag@, When you use If you want to pass your Calling |
@wqzoww @shivlaks - are you suggesting something like this? I think I tried it, but let try again.
|
@shivlaks - the above code snippet did not work...parameter received in lambda is null |
@sacag - here's a gist that includes a couple of small inline Lambdas to illustrate how the one of the things you're missing in your line from the looks of it is is the "lambdaResult.$", "$.Payload" I don't believe you need to specify InputPath, ResultPath, OutputPath The input will always include the payload in the request body when calling subsequent lambdas and will need to be pointed at specifically. You can read more about the request parameters here I'm going to mark this as guidance as this isn't quite a bug, but does represent an area where we can improve documentation, samples, and providing direction to users who want to migrate from |
@shivlaks @wqzoww is it possible to get exactly the same behaviour as it was before? I can add to payload something like this |
@shivlaks @wqzoww - suggestion doesn't seem to work. The json layout changes per task state (TaskStateEntered(1st image) and TaskStateScheduled(2nd image))seems like. See the attached images. So, the below code cannot find the correct jsonpath as described in the code below and sends NULL to lambda function
|
@shivlaks - So, my Lambda's FunctionHandler looks like below:
I changed my input parameter in the RunLambdaTask to this:
Still I get NULL in the lambda's function-handler |
@codenamestif - Glad you were able to get it working. I'm looking into whether there's a way to preserve the old flow by reaching out to the Step Functions team. AFAIK, the new service integration pattern is structurally different. Some of the historical context is captured here @sacag are you reading the i.e. in the above example: InvokeFunction would have produced {
"statusCode": "200",
"body": "hello, world!"
} the output, and hence input for subsequent Lambda's in your Step Functions workflow with using {
"ExecutedVersion": "$LATEST",
"Payload": {
"statusCode": "200",
"body": "hello, world!"
},
"SdkHttpMetadata": {
"HttpHeaders": {
"Connection": "keep-alive",
"Content-Length": "43",
"Content-Type": "application/json",
"Date": "Thu, 16 Apr 2020 17:58:15 GMT",
"X-Amz-Executed-Version": "$LATEST",
"x-amzn-Remapped-Content-Length": "0",
"x-amzn-RequestId": "88fba57b-adbe-467f-abf4-daca36fc9028",
"X-Amzn-Trace-Id": "root=1-5e989cb6-90039fd8971196666b022b62;sampled=0"
},
"HttpStatusCode": 200
},
"SdkResponseMetadata": {
"RequestId": "88fba57b-adbe-467f-abf4-daca36fc9028"
},
"StatusCode": 200
} |
So, I see how we can get it to work in C# as well. I was able to proof it out. But, it is no where close to an optimal solution for us. We will have to make un-necessary changes to our Model just to incorporate an additional layer of "input field" added to the payload. It's not like Typescript/Nodejs. It's not a dynamic model. So, hopefully there is a better way to do this in C# if not now then sometime soon. Maybe before InvokeFunction is retired. @shivlaks |
@codenamestif - as you've mentioned, specifying the key as |
I realise that this may be off-topic, apologies in advance. You could implement a DTO that consists of a Lambda-compatible structure and map it to your original model so you don't have to mutate your model. While there may be constraints to the setup of mapping payloads using Stepfunctions/CDK (especially in statically typed languages like C#), you could easily abstract away the input models from your internal modes. In general I think this is good practise :) |
@shivlaks cool! But i'm not sure about specifying |
@codenamestif Nope, you're right. We need to cover all cases. The |
TL;DR Step Functions has two ways to represent Lambda Tasks, which is reflected in the two different constructs InvokeFunction (a.k.a "old style" Lambda Task)The deprecated "Invoke Function": {
"Type": "Task",
"Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
"Next": "NEXT_STATE"
} Optionally, you can specify "Invoke Function - with parameters": {
"Type": "Task",
"Parameters": {
"OriginalExecutionInput.$": "$$.Execution.Input",
"StateInput.$": "$",
"HardcodedValue": 123
},
"Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
"Next": "NEXT_STATE"
} In this example, the input to the state is {
"OriginalExecutionInput": {},
"StateInput": { "foo": "bar" },
"HardcodedValue": 123
} RunLambdaTask
To send the entire state input to the Lambda function, "Run Lambda Task": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"FunctionName": "FUNCTION_NAME",
"Payload.$": "$"
},
"Next": "NEXT_STATE"
} In CDK, this is configured in Some edge cases to consider:
|
…sk context as input to the service integration The Lambda service integration requires an input field called `payload`. We modeled this as a `{[key: string]: any}` which precludes the usage of execution data or context data as inputs to a Lambda function. Fix: Change the type of `payload` to be `TaskInput` which has already modeled a type union for task classes that accept multiple types of payload. This will enable usage of literal strings, objects, execution data, and task context. Rationale: Although this is a breaking change, the workarounds for enabling usage of different types is not user friendly and incomplete as all of the types above cannot be expressed in the current modeling of `payload` Fixes #7371 BREAKING CHANGE: `payload` in RunLambdaTask is now of type `TaskInput`. You can migrate your current assignment to payload by supplying it to the `TaskInput.fromObject()` API
…sk context as input to the `RunLambda` service integration (#7428) The Lambda service integration requires an input field called `payload`. We modeled this as a `{[key: string]: any}` which precludes the usage of execution data or context data as inputs to a Lambda function. Fix: Change the type of `payload` to be `TaskInput` which has already modeled a type union for task classes that accept multiple types of payload. This will enable usage of literal strings, objects, execution data, and task context as input types supported for invoking a Lambda function. Rationale: Although this is a breaking change, the workarounds for enabling usage of different types is not user friendly and incomplete as all of the types above cannot be expressed in the current modeling of `payload` Fixes #7371 BREAKING CHANGE: `payload` in RunLambdaTask is now of type `TaskInput` and has a default of the state input instead of the empty object. You can migrate your current assignment to payload by supplying it to the `TaskInput.fromObject()` API
I wonder if with this fix we could take only the "Payload" part of the task result (the lambda return value) and mount it on the ResultPath... I really can't find a way to do this |
@fabio-vitali Not directly, but you can chain a Pass state with const lambdaTask = new stepfunctions.Task(this, 'CallLambda', {
task: new tasks.RunLambdaTask(lambdaFn),
resultPath: '$.LambdaResult'
})
const extractPayload = new stepfunctions.Pass(this, 'ExtractPayload', {
inputPath: '$.LambdaResult.Payload',
resultPath: '$.LambdaResult'
})
new stepfunctions.StateMachine(this, 'DemoStateMachine', {
definition: lambdaTask.next(extractPayload)
}) |
@wong-a thank you!! |
@fabio-vitali related issue (#7709) - workaround if the behaviour is desired to add a Pass state as @wong-a mentioned I think I included another full sample here feel free to add any other thoughts or considerations you come across in the related issue cheers! |
I am seeing more issues with RunLambdaTask:
below is the code which works with InvokeFunction..$.Payload has my model in json string
The same code when using RunLambdaTask...not sure how to access $.Payload in the Payload property, so that it can be passed over to the Lambda function? This is what I have
When I do Context.StringAt(...) in RunLambdaTask, i think it takes the execution's input and not the task input..i think, maybe there is another way to access the TaskState input?
Basically, the model sent to my lambda is NULL in case of RunLambdaTask.
Environment
Other
This is 🐛 Bug Report
The text was updated successfully, but these errors were encountered: