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

RFC 474: Event Bridge Scheduler L2 #486

Merged
merged 19 commits into from
Apr 26, 2023

Conversation

filletofish
Copy link
Contributor

@filletofish filletofish commented Mar 5, 2023

This is a request for comments about EventBridge Scheduler L2 Construct. See #474 for
additional details.

APIs are signed off by @kaizencc

Copy link
Contributor

@kaizencc kaizencc left a comment

Choose a reason for hiding this comment

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

Hi @filletofish, @Jacco, starting off with a few comments on the proposed APIs. Nothing too major. I'll be back to look at the rest soon.

const oneTimeSchedule = new Schedule(this, 'Schedule', {
schedule: ScheduleExpression.at(new Date(2022, 10, 20, 19, 20, 23)),
target,
scheduleTimeZone: 'America/New_York'
Copy link
Contributor

Choose a reason for hiding this comment

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

TimeZone enum is added to core: aws/aws-cdk#24127. We should use it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Amazing, thanks!

- Make minor changes to README
- Add mermaid diagram
@filletofish filletofish marked this pull request as ready for review March 19, 2023 19:18
Copy link
Contributor

@kaizencc kaizencc left a comment

Choose a reason for hiding this comment

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

Hi! @filletofish @Jacco. I am back, and have just a few more comments on this RFC. Once they are addressed I will swiftly approve and we can get to the implementation. Thanks for all your work thus far!

@mergify mergify bot dismissed kaizencc’s stale review April 9, 2023 19:31

Pull request has been modified.

@kaizencc kaizencc added status/final-comment-period Pending final approval status/api-approved API Bar Raiser signed-off the API of this RFC labels Apr 11, 2023
Comment on lines +277 to +279
deadLetterQueue: dlq,
maximumEventAge: Duration.minutes(1),
maximumRetryAttempts: 3
Copy link
Contributor

Choose a reason for hiding this comment

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

are all three of these part of the retry policy?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In CFN only maximum event age and maximum retry attempts are part of retry policy. Would you recommend to organise them similarly in a RetryPolicy structure as well?

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-scheduler-schedule-retrypolicy.html

filletofish and others added 2 commits April 15, 2023 15:38
Co-authored-by: Calvin Combs <66279577+comcalvi@users.noreply.github.com>
Co-authored-by: Calvin Combs <66279577+comcalvi@users.noreply.github.com>
@mergify mergify bot dismissed comcalvi’s stale review April 15, 2023 14:39

Pull request has been modified.

filletofish and others added 4 commits April 15, 2023 15:39
Co-authored-by: Calvin Combs <66279577+comcalvi@users.noreply.github.com>
Co-authored-by: Calvin Combs <66279577+comcalvi@users.noreply.github.com>
Co-authored-by: Calvin Combs <66279577+comcalvi@users.noreply.github.com>
@filletofish
Copy link
Contributor Author

Thank you for your feedback @comcalvi! I have made some updates per your comments.

Copy link

@tmokmss tmokmss left a comment

Choose a reason for hiding this comment

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

A few minor comments from one of the users' perspective. Looking forward to using this feature! 🚀

const cronBasedSchedule = new Schedule(this, 'Schedule', {
schedule: ScheduleExpression.cron({ minute: '0', hour: '23', day: '20', month: '11' }),
target,
scheduleTimeZone: TimeZone.AMERICA_NEW_YORK,
Copy link

Choose a reason for hiding this comment

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

How about renaming the prop scheduleTimezone to timezone to make it short? I feel it is already clear enough that this timezone property is for the schedule.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am concerned that the customer might think that timezone is also applied to other properties. For example, Schedule also has properties startDate and endDate, which should be specified in UTC timezone and do not depend on timezone.

So we have these options:

1 - Do nothing

Keep interface as-is with a separate scheduleTimeZone parameter. It's simple and matches CFN structure https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-scheduler-schedule.html#cfn-scheduler-schedule-scheduleexpressiontimezone

2 - Rename scheduleTimeZone to timeZone

Not obvious that the property timeZone does not apply to startDate and endDate

3 - Add timezone parameter to ScheduleExpression methods

Example:

const cronBasedSchedule = new Schedule(this, 'Schedule', {
    schedule: ScheduleExpression.cron({ minute: '0', hour: '23', day: '20', month: '11', timezone: TimeZone.AMERICA_NEW_YORK}),
    target,
    description: 'This is a test cron-based schedule that will run at 11:00 PM, on day 20 of the month, only in November in New York timezone',
});

In implementation we will create a class ScheduleExpression that will inherit from events.Schedule and will have methods cron(..), at(..) and rate(..) with timezone as an additional parameter.

Not a bad option. Maybe timezone will not be that discoverable as in other options.

4 - Create a separate interface with two parameters expression and timezone

Example:

const cronBasedSchedule = new Schedule(this, 'Schedule', {
    scheduleExpression: {
          expression: ScheduleExpression.cron({ minute: '0', hour: '23', day: '20', month: '11' }),
          timeZone: TimeZone.AMERICA_NEW_YORK
     },
    target,
    description: 'This is a test cron-based schedule that will run at 11:00 PM, on day 20 of the month, only in November in New York timezone',
});

However, I am not sure what name to choose for the new interface as names Schedule and ScheduleExpression are already taken. Any recommendations?


All in all, I am probably still leaning to the first as it's the simplest option. Curious if you guys also have any opinion on this question @Jacco, @kaizencc and @comcalvi?

Copy link

Choose a reason for hiding this comment

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

That makes sense, thanks! To me, option 3 or 4 look nice and more cohesive, but at the same time option 1 sounds reasonable. I'm fine with whatever decision is made :)

Copy link
Contributor

Choose a reason for hiding this comment

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

I think I like option 4, with scheduleExpression: { schedule: Schedule, timeZone: TimeZone }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think I like option 4, with scheduleExpression: { schedule: Schedule, timeZone: TimeZone }

But then there will be two classes with names Schedule. Can't find a better class names, do you have any ideas?

Copy link

@Jacco Jacco Apr 19, 2023

Choose a reason for hiding this comment

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

Few things to consider:

How would the original events.Schedule be changed if timezone support is added for aws-events. I think it would best added CronOptions in CDK since it has no meaning for a rate expressions timeZone has no meaning. It would be kept separate though because in cloudFormation is would probably not be part of the expression but a separate property like here.

So maybe we should still used events.Schedule functionality but not inherit and add the timeZone parameter from cron and at.

Unflat interfaces give less good code completion in some languages (like python).

Another thing to consider: what if aws-events at some point adds another type of schedule that is unsupported by aws-scheduler. We could add an error raising override, but maybe we'd better not inherited?

Maybe implement like this:

import { Duration, TimeZone } from 'aws-cdk-lib';
import * as events from 'aws-cdk-lib/aws-events';

export abstract class ScheduleExpression {
  public static at(date: Date, timeZone?: TimeZone): ScheduleExpression {
    try {
      const literal = date.toISOString().split('.')[0];
      return new LiteralScheduleExpression(`at(${literal})`, timeZone)
    } catch(e) {
      if (e instanceof RangeError){
        throw new Error('Invalid date');
      }
      throw e;
    }
  }

  public static cron(options: events.CronOptions, timeZone?: TimeZone): ScheduleExpression {
    return new LiteralScheduleExpression(events.Schedule.cron(options).expressionString, timeZone);
  }

  public static rate(duration: Duration): ScheduleExpression {
    return new LiteralScheduleExpression(events.Schedule.rate(duration).expressionString);
  }

  public static expression(expression: string, timeZone?: TimeZone) {
    return new LiteralScheduleExpression(expression, timeZone);
  }

   public abstract readonly expressionString: string;

   public abstract readonly expressionTimeZone?: TimeZone;
}

class LiteralScheduleExpression extends ScheduleExpression {
  constructor(public readonly expressionString: string, public readonly expressionTimeZone?: TimeZone) {
    super();
  }

  public _bind() {}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I like that suggestion @Jacco. It's similar to option 3. I was also thinking about the way to reuse functionality of events.Schedule with composition, but couldn't come up with a good enough option like yours.

I will add it to the RFC. Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

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

Agree on not inheriting for now. The ideal scenario is still to put a generic Schedule into core that can be extended by the 4 resources that have the concept of schedule today. But that's out of scope of this RFC.

(autoscaling, app-autoscaling, scheduler, events are the 4 i can think of)

Copy link
Contributor

@comcalvi comcalvi 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 great work, I just have a few minor comments

Comment on lines 52 to 53
2. **Targets**: A target is an API operation that EventBridge Scheduler calls on your behalf every time your schedule runs. EventBridge Scheduler supports two types of targets: templated targets and universal targets. Templated targets invoke common API operations across a core groups of services. For example, EventBridge Scheduler supports templated targets for invoking AWS Lambda Function or starting execution of Step Function state machine. For API operations that are not supported by templated targets you can use customizeable universal targets. Universal targets support calling more than 6,000 API operations across over 270 AWS services.
3. **Schedule Group**: A schedule group is an Amazon EventBridge Scheduler resource that you use to organize your schedules. Your AWS account comes with a default scheduler group. A new schedule will always be added to a scheduling group. If you do not provide a scheduling group to add to, it will be added to the default scheduling group. You can create up to 500 schedule groups in your AWS account. Groups can be used to organize the schedules logically, access the schedule metrics and manage permissions at group granularity (see details below). Scheduling groups support tagging: with EventBridge Scheduler, you apply tags to schedule groups, not to individual schedules to organize your resources.
Copy link
Contributor

Choose a reason for hiding this comment

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

Very nice!

Comment on lines 88 to 91
scheduleExpression: ScheduleExpression.cron(
{ minute: '0', hour: '23', day: '20', month: '11' },
TimeZone.AMERICA_NEW_YORK
),
Copy link
Contributor

Choose a reason for hiding this comment

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

I like this a lot. Why not move the timezone to the struct that's taken as the first argument?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

nice one, will add

Co-authored-by: Calvin Combs <66279577+comcalvi@users.noreply.github.com>
@mergify mergify bot dismissed comcalvi’s stale review April 24, 2023 19:23

Pull request has been modified.

comcalvi
comcalvi previously approved these changes Apr 25, 2023
@comcalvi comcalvi dismissed their stale review April 25, 2023 14:50

Letting Kaizen approve

kaizencc
kaizencc previously approved these changes Apr 25, 2023
@mergify mergify bot dismissed kaizencc’s stale review April 26, 2023 15:14

Pull request has been modified.

@kaizencc kaizencc merged commit 22a3cdc into aws:master Apr 26, 2023
@evgenyka evgenyka added the l2-request request for new L2 construct label Oct 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
l2-request request for new L2 construct status/api-approved API Bar Raiser signed-off the API of this RFC status/final-comment-period Pending final approval
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants