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

[proposal] Add support for scheduled events #390

Closed
jamesls opened this issue Jun 26, 2017 · 1 comment
Closed

[proposal] Add support for scheduled events #390

jamesls opened this issue Jun 26, 2017 · 1 comment

Comments

@jamesls
Copy link
Member

jamesls commented Jun 26, 2017

Add support for scheduled events

There have been multiple requests for scheduled events:

#231
#234
#102
#49
#86

There has also been an add-on to chalice that implements this (and more):

https://github.com/kislyuk/domovoi

The linked issues also have multiple comments from customers stating
they'd like to see support for this feature.

Based on this customer feedback, this is a proposal to support scheduled events
directly in chalice. The built in authorizer feature (#356) updated the
internals to support deploying multiple lambda functions as part of chalice
app. This feature would build on top of that support.

API

The API uses the same decorated based API used for routing and built in authorizers:

@app.schedule(schedule_expression)
def handler(event):
    pass

The handler has this signature:

def handler(event: CloudWatchEvent) -> None: ...

class CloudWatchevent:
    version: str = ...
    id: str = ...
    source: str = ...
    account: str = ...
    time: str = ...
    region: str = ...
    resources: List[str] = ...
    detail: Dict[str, Any] = ...
    to_dict: Callable[[], Dict[str, Any]] = ...

and the schedule() function has this signature:

def schedule(schedule_expression: Union[str, Cron, Rule]): ...

First, the schedule_expression can be a direct string passthrough of what's supported in the
cloudwatch events API (http://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html)
which can include either rate() or cron() expressions. From that documentation page,
here are their examples ported to chalice:

@app.schedule('cron(0 12 * * ? *)')
def handler(event):
    pass

@app.schedule('cron(15 10 ? * 6L 2002-2005)')
def handler(event):
    pass

@app.schedule('rate(5 minutes)')
def handler(event):
    pass

@app.schedule('rate(1 hour)')
def handler(event):
    pass

@app.schedule('rate(1 day)')
def handler(event):
    pass

To help avoid syntax errors, you can also provide the Cron
or the Rule object which will construct the appropriate
cloudwatch event schedule expression for you. These objects are:

class Rule:
    value = ...  # type: int
    unit = ...  # type: str
    # Strs/ints or whatever, but not using another object for simplicity.
    MINUTES
    HOURS
    DAYS

class Cron:
    # All of type Union[str, int].
    minutes
    hours
    day_of_month
    month
    day_of_week
    year

So the original string examples using these objects would be:

@app.schedule(Cron(0, 12, '*', '*', '?', '*'))
def handler(event):
    pass

@app.schedule(Cron(15, 10, '?', '*', '6L', '2002-2005'))
def handler(event):
    pass

@app.schedule(Rate(value=5, unit=Rate.MINUTES))
def handler(event):
    pass

@app.schedule(Rate(value=1, unit=Rate.HOURS))
def handler(event):
    pass

@app.schedule(Rate(value=1, unit=Rate.DAYS))
def handler(event):
    pass

Each @app.schedule will result in a new lambda function being created,
similar to the approach outlined in the @app.authorizer feature.

Rationale

Using a typed object for the function agument

This is primarily for consistency with the auth_request in
the built-in authorizer. It will also help with auto completion in IDEs
and linters. There's also a to_dict() method which returns the input
event dict so you can get at the raw data. This is useful if new params
are added to the event dict that haven't been mapped in chalice yet.

The argument to the schedule() function

Using a union type is consistent with the pattern we've followed for
CORSConfig, AuthRoute, and AuthResponse. In this scenario,
the str type can always be used if you want direct control over the
schedule expression or if cloudwatch events adds support for a new expression
type that chalice hasn't mapped to an object/attr yet.

Multiple lambda functions

This is consistent with how built in authorizers (and more generally any future non-route
decorators) work. Unlike the @app.route decorators, authorizers and scheduled
events are conceptually separate from each other and make sense to
track per-lambda function.

Let me know what you all think.

cc @kyleknap @stealthycoin @kislyuk

@jamesls
Copy link
Member Author

jamesls commented Jul 5, 2017

Implemented in #393
Merged in 2fa94a1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant