7

Currently, I am attempting to create a series of Lambdas that will execute given specific payloads from the StepFunctions Input. I have everything working; however, it's not as I intended.

I finally have grasped the differences between InputPath, ResultPath, and OutputPath. The only problem I have now is allowing the ResultPath to 'append' the returned JSON rather than nesting it within the payload.

Here is the state machine:

{
  "StartAt": "GetDailyEmails",
  "States": {
    "GetDailyEmails": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:region:account:function:DailyEmailExtractor",
      "InputPath": "$.GetDailyEmailsInputs",
      "ResultPath": "$.TransformEmailsToCSVInputs.GetDailyEmailsResults",
      "Next": "TransformEmailsToCSV"
    },
    "TransformEmailsToCSV": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:region:account:function:EmailTransform",
      "InputPath": "$.TransformEmailsToCSVInputs",
      "End": true
    }
  }
}

Here is the input I'm providing:

{
    "GetDailyEmailsInputs": {
        "secret_name": "email_password",
        "subject_contains": "stuff",
        "json_output_file_name": "test_emails",
        "bucket_name": "emails"
    },
    "TransformEmailsToCSVInputs": {
        "csv_output_file_name": "email_errors"
    }
}

Here was the output I received:

{
  "GetDailyEmailsInputs": {
    "secret_name": "email_password",
    "subject_contains": "stuff",
    "json_output_file_name": "test_emails",
    "bucket_name": "emails"
  },
  "TransformEmailsToCSVInputs": {
    "csv_output_file_name": "apex_errors",
    "GetDailyEmailsResults": {
      "object_key": "raw_emails/test_emails.json",
      "bucket_name": "emails"
    }
  }
}

While this does work, I have to manually extract out the GetDailyEmailsResults in the TransformEmailsToCSV lambda. I wanted to make the lambdas fully agnostic to whether or not they're being executed from a test payload or the stepfunctions.

Here is the output I'm trying to receive:

{
  "GetDailyEmailsInputs": {
    "secret_name": "email_password",
    "subject_contains": "stuff",
    "json_output_file_name": "test_emails",
    "bucket_name": "emails"
  },
  "TransformEmailsToCSVInputs": {
    "csv_output_file_name": "apex_errors",
    "object_key": "raw_emails/test_emails.json",
    "bucket_name": "emails"
  }
}

This way, there is not a GetDailyEmailsResults nested dictionary where I need to account for it.

I could write this in a generalized way where it's just a data payload being passed to it; however, I'm trying to just have everything within a single payload without nesting if that's possible.

1
  • Idea 1: Use an object where the keys are numbers, and keep a separate counter Commented Aug 11, 2024 at 20:20

2 Answers 2

3

I can see that you are trying to achieve a good design. Though there is no out of box solution to provide what you need, I have a different proposal that you might want to consider.

  1. Put GetDailyEmailsResults differently and not in the input that you provided.
  2. Create input to lambda from step function data by picking them from the JSON as required.

Here is the state machine that I am proposing(It may not be completely correct syntactically but you will get an idea).

{
  "StartAt": "GetDailyEmails",
  "States": {
    "GetDailyEmails": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:region:account:function:DailyEmailExtractor",
      "InputPath": "$.GetDailyEmailsInputs",
      "ResultPath": "$.GetDailyEmailsResults",
      "Next": "TransformEmailsToCSV"
    },
    "TransformEmailsToCSV": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "Parameters":{  
            "FunctionName":"EmailTransform",
            "Payload":{  
               "csv_output_file_name": "apex_errors",
               "object_key.$": "$.GetDailyEmailsResults.object_key",
               "bucket_name.$": "$.GetDailyEmailsResults.bucket_name"
            }
         },
      "End": true
    }
  }
}

I hope this helps.

Cheers :)

Sign up to request clarification or add additional context in comments.

Comments

2

Have a look at the Intrinsic functions of the amazon state language..

You can use JsonMerge to achieve what you desire. Beware that it does not work in the data flow simulator.

You can however use a dummy machine consisting of Pass states to simulate and play around.

Unfortunately intrinsic functions are not allowed everywhere. At the bottom of the linked docs above is a table telling where you can use them.

Screenshot of the aws docs where intrinsic functions may be used

3 Comments

can you use States.JsonMerge in the ResultPath?
Unfortunately not. I'll update my answer to point that out.
The workaround I’ve found was to use the “Pass” step function type to manipulate data and use States.JsonMerge there

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.