Skip to content
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

feat(stepfunctions-tasks): add sns publish with message attributes #14817

Merged
merged 39 commits into from
Jul 28, 2021

Conversation

moofish32
Copy link
Contributor

This PR address #4702

I am primarily solving for the use case of using SNS publish with
message attributes for sns filtering. If EventBridge integrations have a
fast follow for wait for task token features, that would solve my use
case. Because I'm solving for filtering and based on anecdotal
experience String is the primary attribute type. I've included Binary
because the pattern is the same. I have not implemented Number or
String.Array because they are not Lambda supported and I believe less
common.

I chose to attempt to solve for consumer ergonomics with:

    const task = new SnsPublish(stack, 'Publish', {
      topic,
      message: sfn.TaskInput.fromText('Publish this message'),
      messageAttributes: {
        cake: {
          type: SnsMessageAttributeType.STRING,
          value: sfn.TaskInput.fromText('chocolate'),
        },
        cakePic: {
          type: SnsMessageAttributeType.BINARY,
          value: sfn.TaskInput.fromDataAt('$.cake.pic'),
        },
      },
    });

This results in a value member on the message attribute interface.
While I think that maps best for the SNS json definition and does yield
this ugly line in the private render methods:

      attrs[a][`${attr.type}Value`] = attr.value.value;

Is there a better way?

I did not implement SQS message attributes yet. Based on my limited
knowledge the StepFunction integrations are similar(potentially
identical if we again only support Binary and String). If the answer is
one implementation, should I move the below code snippets into something
generically named MessageAttribute within the stepfunctions package
perhaps as part of base-task?

/**
 * SNS Message Attribute type enum
 */
export enum SnsMessageAttributeType {

  /**
   * String type attributes.
   *
   * @see https://docs.aws.amazon.com/sns/latest/dg/sns-message-attributes.html#SNSMessageAttributes.DataTypes
   */
  STRING = 'String',

  /**
   * Binary type attributes.
   *
   * @see https://docs.aws.amazon.com/sns/latest/dg/sns-message-attributes.html#SNSMessageAttributes.DataTypes
   */
  BINARY = 'Binary',
}

/**
 * SNS Message Attribute
 */
export interface SnsMessageAttribute {
  /**
   * MessageAttributeType is the type of data being passed.
   *
   *
   * @see https://docs.aws.amazon.com/sns/latest/dg/sns-message-attributes.html#SNSMessageAttributes.DataTypes
   */
  readonly type: SnsMessageAttributeType;

  /**
   * The value of the data being passed
   */
  readonly value: sfn.TaskInput;
}

This PR address aws#4702

I am primarily solving for the use case of using SNS publish with
message attributes for sns filtering. If EventBridge integrations have a
fast follow for wait for task token features, that would solve my use
case. Because I'm solving for filtering and based on anecdotal
experience String is the primary attribute type. I've included Binary
because the pattern is the same. I have not implemented Number or
String.Array because they are not Lambda supported and I believe less
common.

I chose to attempt to solve for consumer ergonomics with:

```ts
    const task = new SnsPublish(stack, 'Publish', {
      topic,
      message: sfn.TaskInput.fromText('Publish this message'),
      messageAttributes: {
        cake: {
          type: SnsMessageAttributeType.STRING,
          value: sfn.TaskInput.fromText('chocolate'),
        },
        cakePic: {
          type: SnsMessageAttributeType.BINARY,
          value: sfn.TaskInput.fromDataAt('$.cake.pic'),
        },
      },
    });
```

This results in a `value` member on the message attribute interface.
While I think that maps best for the SNS json definition and does yield
this ugly line in the private render methods:

```
      attrs[a][`${attr.type}Value`] = attr.value.value;
```

Is there a better way?

I did not implement SQS message attributes yet. Based on my limited
knowledge the StepFunction integrations are similar(potentially
identical if we again only support Binary and String). If the answer is
one implementation, should I move the below code snippets into something
generically named MessageAttribute within the stepfunctions package
perhaps as part of base-task?

```ts
/**
 * SNS Message Attribute type enum
 */
export enum SnsMessageAttributeType {

  /**
   * String type attributes.
   *
   * @see https://docs.aws.amazon.com/sns/latest/dg/sns-message-attributes.html#SNSMessageAttributes.DataTypes
   */
  STRING = 'String',

  /**
   * Binary type attributes.
   *
   * @see https://docs.aws.amazon.com/sns/latest/dg/sns-message-attributes.html#SNSMessageAttributes.DataTypes
   */
  BINARY = 'Binary',
}

/**
 * SNS Message Attribute
 */
export interface SnsMessageAttribute {
  /**
   * MessageAttributeType is the type of data being passed.
   *
   *
   * @see https://docs.aws.amazon.com/sns/latest/dg/sns-message-attributes.html#SNSMessageAttributes.DataTypes
   */
  readonly type: SnsMessageAttributeType;

  /**
   * The value of the data being passed
   */
  readonly value: sfn.TaskInput;
}
```
@gitpod-io
Copy link

gitpod-io bot commented May 21, 2021

Copy link
Contributor Author

@moofish32 moofish32 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding in line comments similar to the summary for comment tracking.

@moofish32
Copy link
Contributor Author

@shivlaks I think you indicated some interest in a PR here, if you have something ready feel free to push and take the lead.

@moofish32
Copy link
Contributor Author

moofish32 commented May 28, 2021

Ok I've realized I did not understand the value/flexibility of sfn.TaskInput.fromObject. I think we can simplify by using that function. Can anybody from the CDK team comment if that is a better path? I have pushed a very rough implementation example using this approach.

If we can agree that we will only support String types then this solution could simplify to a structure more like:

    const pubTask = new SnsPublish(stack, 'Publish', {
      topic,
      message: sfn.TaskInput.fromText('Publish this message'),
      messageAttributes: {
        cake: sfn.TaskInput.fromText('chocolate'),
        attribute2: sfn.TaskInput.fromDataAt('$.attribute2'),
      },
    });

I prefer the above because it's the only use case I've seen in the wild and most simple to declare.

@shivlaks are you able to help here at all?

@shivlaks shivlaks changed the title feat(aws-stepfunctions-task): add sns publish with message attributes feat(stepfunctions-tasks): add sns publish with message attributes Jun 8, 2021
Co-authored-by: Shiv Lakshminarayan <shivlaks@amazon.com>
@mergify mergify bot dismissed shivlaks’s stale review June 9, 2021 13:58

Pull request has been modified.

@moofish32
Copy link
Contributor Author

Ok I've realized I did not understand the value/flexibility of sfn.TaskInput.fromObject. I think we can simplify by using that function. Can anybody from the CDK team comment if that is a better path? I have pushed a very rough implementation example using this approach.

If we can agree that we will only support String types then this solution could simplify to a structure more like:

    const pubTask = new SnsPublish(stack, 'Publish', {
      topic,
      message: sfn.TaskInput.fromText('Publish this message'),
      messageAttributes: {
        cake: sfn.TaskInput.fromText('chocolate'),
        attribute2: sfn.TaskInput.fromDataAt('$.attribute2'),
      },
    });

I prefer the above because it's the only use case I've seen in the wild and most simple to declare.

@shivlaks are you able to help here at all?

I think I still have a question here. If we agree String support is the only type we can simplify a lot of code.

export interface MessageAttributes { [key: string]: string; }
// usage becomes
const pubTask = new SnsPublish(stack, 'Publish', {
      topic,
      message: sfn.TaskInput.fromText('Publish this message'),
      messageAttributes: {
        cake: 'chocolate',
        attribute2: sfn.JsonPathAt('$.attribute2'),
      },
    });

I think part of my confusion is where do I need to enforce they use sfn.TaskInput versus just using literal strings and JsonPath?

@BenChaimberg
Copy link
Contributor

I think overall, I'd like to support more than just strings. The current split of only allowing task input in the attribute value is fine for me. This is a design decision that we should align on, but I think it's a realistic tradeoff as allowing too much flexibility removes all the nice type checking, serialization, etc. that we can do

@moofish32
Copy link
Contributor Author

moofish32 commented Jul 3, 2021 via email

@mergify mergify bot dismissed BenChaimberg’s stale review July 8, 2021 17:19

Pull request has been modified.

@moofish32
Copy link
Contributor Author

This comment #14817 (comment) represents what I believe to be blocking finishing this work.

Copy link
Contributor

@BenChaimberg BenChaimberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the auto-detect, feels very powerful for our customers! Just a few major comments, rest are naming/implementation details

@moofish32
Copy link
Contributor Author

I agree with comments @BenChaimberg and will get a refactor up this week.

moofish32 and others added 2 commits July 17, 2021 16:17
Co-authored-by: Ben Chaimberg <youppi3@gmail.com>
Co-authored-by: Ben Chaimberg <youppi3@gmail.com>
@mergify mergify bot dismissed BenChaimberg’s stale review July 17, 2021 22:17

Pull request has been modified.

@mergify mergify bot dismissed BenChaimberg’s stale review July 21, 2021 16:33

Pull request has been modified.

@moofish32
Copy link
Contributor Author

@BenChaimberg - I think I've now addressed all of your comments. Can you please give me another review?

@moofish32 moofish32 requested a review from BenChaimberg July 21, 2021 16:39
Copy link
Contributor

@BenChaimberg BenChaimberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking great! Just a couple of minor things and I think we'll be good to go!

Co-authored-by: Ben Chaimberg <youppi3@gmail.com>
@mergify mergify bot dismissed BenChaimberg’s stale review July 27, 2021 17:14

Pull request has been modified.

@mergify mergify bot dismissed BenChaimberg’s stale review July 28, 2021 16:08

Pull request has been modified.

@mergify
Copy link
Contributor

mergify bot commented Jul 28, 2021

Thank you for contributing! Your pull request will be updated from master and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject89A8053A-LhjRyN9kxr8o
  • Commit ID: 0b6dbc7
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@mergify mergify bot merged commit bc99e82 into aws:master Jul 28, 2021
@mergify
Copy link
Contributor

mergify bot commented Jul 28, 2021

Thank you for contributing! Your pull request will be updated from master and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

TikiTDO pushed a commit to TikiTDO/aws-cdk that referenced this pull request Aug 3, 2021
…ws#14817)

This PR address aws#4702

I am primarily solving for the use case of using SNS publish with
message attributes for sns filtering. If EventBridge integrations have a
fast follow for wait for task token features, that would solve my use
case. Because I'm solving for filtering and based on anecdotal
experience String is the primary attribute type. I've included Binary
because the pattern is the same. I have not implemented Number or
String.Array because they are not Lambda supported and I believe less
common.

I chose to attempt to solve for consumer ergonomics with:

```ts
    const task = new SnsPublish(stack, 'Publish', {
      topic,
      message: sfn.TaskInput.fromText('Publish this message'),
      messageAttributes: {
        cake: {
          type: SnsMessageAttributeType.STRING,
          value: sfn.TaskInput.fromText('chocolate'),
        },
        cakePic: {
          type: SnsMessageAttributeType.BINARY,
          value: sfn.TaskInput.fromDataAt('$.cake.pic'),
        },
      },
    });
```

This results in a `value` member on the message attribute interface.
While I think that maps best for the SNS json definition and does yield
this ugly line in the private render methods:

```
      attrs[a][`${attr.type}Value`] = attr.value.value;
```

Is there a better way?

I did not implement SQS message attributes yet. Based on my limited
knowledge the StepFunction integrations are similar(potentially
identical if we again only support Binary and String). If the answer is
one implementation, should I move the below code snippets into something
generically named MessageAttribute within the stepfunctions package
perhaps as part of base-task?

```ts
/**
 * SNS Message Attribute type enum
 */
export enum SnsMessageAttributeType {

  /**
   * String type attributes.
   *
   * @see https://docs.aws.amazon.com/sns/latest/dg/sns-message-attributes.html#SNSMessageAttributes.DataTypes
   */
  STRING = 'String',

  /**
   * Binary type attributes.
   *
   * @see https://docs.aws.amazon.com/sns/latest/dg/sns-message-attributes.html#SNSMessageAttributes.DataTypes
   */
  BINARY = 'Binary',
}

/**
 * SNS Message Attribute
 */
export interface SnsMessageAttribute {
  /**
   * MessageAttributeType is the type of data being passed.
   *
   *
   * @see https://docs.aws.amazon.com/sns/latest/dg/sns-message-attributes.html#SNSMessageAttributes.DataTypes
   */
  readonly type: SnsMessageAttributeType;

  /**
   * The value of the data being passed
   */
  readonly value: sfn.TaskInput;
}
```
hollanddd pushed a commit to hollanddd/aws-cdk that referenced this pull request Aug 26, 2021
…ws#14817)

This PR address aws#4702

I am primarily solving for the use case of using SNS publish with
message attributes for sns filtering. If EventBridge integrations have a
fast follow for wait for task token features, that would solve my use
case. Because I'm solving for filtering and based on anecdotal
experience String is the primary attribute type. I've included Binary
because the pattern is the same. I have not implemented Number or
String.Array because they are not Lambda supported and I believe less
common.

I chose to attempt to solve for consumer ergonomics with:

```ts
    const task = new SnsPublish(stack, 'Publish', {
      topic,
      message: sfn.TaskInput.fromText('Publish this message'),
      messageAttributes: {
        cake: {
          type: SnsMessageAttributeType.STRING,
          value: sfn.TaskInput.fromText('chocolate'),
        },
        cakePic: {
          type: SnsMessageAttributeType.BINARY,
          value: sfn.TaskInput.fromDataAt('$.cake.pic'),
        },
      },
    });
```

This results in a `value` member on the message attribute interface.
While I think that maps best for the SNS json definition and does yield
this ugly line in the private render methods:

```
      attrs[a][`${attr.type}Value`] = attr.value.value;
```

Is there a better way?

I did not implement SQS message attributes yet. Based on my limited
knowledge the StepFunction integrations are similar(potentially
identical if we again only support Binary and String). If the answer is
one implementation, should I move the below code snippets into something
generically named MessageAttribute within the stepfunctions package
perhaps as part of base-task?

```ts
/**
 * SNS Message Attribute type enum
 */
export enum SnsMessageAttributeType {

  /**
   * String type attributes.
   *
   * @see https://docs.aws.amazon.com/sns/latest/dg/sns-message-attributes.html#SNSMessageAttributes.DataTypes
   */
  STRING = 'String',

  /**
   * Binary type attributes.
   *
   * @see https://docs.aws.amazon.com/sns/latest/dg/sns-message-attributes.html#SNSMessageAttributes.DataTypes
   */
  BINARY = 'Binary',
}

/**
 * SNS Message Attribute
 */
export interface SnsMessageAttribute {
  /**
   * MessageAttributeType is the type of data being passed.
   *
   *
   * @see https://docs.aws.amazon.com/sns/latest/dg/sns-message-attributes.html#SNSMessageAttributes.DataTypes
   */
  readonly type: SnsMessageAttributeType;

  /**
   * The value of the data being passed
   */
  readonly value: sfn.TaskInput;
}
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants