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

Add support for scheduled events #393

Merged
merged 5 commits into from Jul 5, 2017
Merged

Conversation

jamesls
Copy link
Member

@jamesls jamesls commented Jun 29, 2017

Proposal: #390

Sample app:

from chalice import Chalice
import datetime

app = Chalice(app_name='testevents')


@app.route('/')
def index():
    return {'hello': 'world'}


@app.schedule('rate(1 minute)')
def every_minute(event):
    print(event.to_dict())

The implementation piggy backs off of the multi lambda support from the built in authorizers. The only unexpected change was an update to the deployed.json file from:

    "lambda_functions": {
      "testevents-dev-every_minute": "arn:lambda-foo"
    },

to:

    "lambda_functions": {
      "testevents-dev-every_minute": {
        "type": "scheduled_event",
        "arn": "arn:lambda-foo"
      }
    },

So we can differentiate the different types of lambda functions.

The other caveat is that right now you still need to deploy an API gateway API. There isn't support yet for only deploying scheduled events. That will be in a follow up PR.

Review Notes

The deployer module has some duplication that I'm working on removing. The logic itself won't change but I'm refactoring the code. Everything else (app.py, awsclient.py, all the tests) are ready for review.

@codecov-io
Copy link

codecov-io commented Jun 29, 2017

Codecov Report

Merging #393 into master will increase coverage by 0.47%.
The diff coverage is 97.77%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #393      +/-   ##
==========================================
+ Coverage   92.28%   92.75%   +0.47%     
==========================================
  Files          18       18              
  Lines        2464     2569     +105     
  Branches      323      334      +11     
==========================================
+ Hits         2274     2383     +109     
+ Misses        141      137       -4     
  Partials       49       49
Impacted Files Coverage Δ
chalice/__init__.py 100% <ø> (ø) ⬆️
chalice/deploy/swagger.py 100% <100%> (ø) ⬆️
chalice/config.py 97.29% <100%> (+0.15%) ⬆️
chalice/awsclient.py 92.9% <96.77%> (+1.41%) ⬆️
chalice/deploy/deployer.py 90.37% <96.87%> (+1.07%) ⬆️
chalice/app.py 97.06% <98.46%> (+0.21%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0f13291...83eafe1. Read the comment docs.

Copy link
Member

@kyleknap kyleknap left a comment

Choose a reason for hiding this comment

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

Looks good. Just some early feedback on the user interface to start before I get into the deployer part of the code.


class CloudWatchEvent(object):
def __init__(self, event_dict):
self.version = event_dict['version']
Copy link
Member

Choose a reason for hiding this comment

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

Will all of these be guaranteed to be present in the event? If it is a direct lookup and a key is missing from the event it would cause issues.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes.

@@ -765,3 +779,82 @@ class AuthRoute(object):
def __init__(self, path, methods):
self.path = path
self.methods = methods


class EventSource(object):
Copy link
Member

Choose a reason for hiding this comment

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

I think the name EventSource along with Chalice.event_sources may be a bit ambiguous here because event source (thinking from the lambda perspective) could mean any event from any service as show by their docs but this seems to be specific to cloud watch events. We may want to either make the name more specific to cloudwatch event sources or make this class more generalized for any lambda event source (like repurpose the schedule_expression to something general to lambda event sources).

Copy link
Member Author

Choose a reason for hiding this comment

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

It's intentional to have an EventSource type. The idea would be this is used for all event types as support more types is added. I don't envision adding a new public attr to chalice.Chalice for every new event source, that wouldn't be maintainable. I can extract out a separate CloudWatchEventSource class with EventSource as its base type. Seemed like overkill for now, but I don't mind adding it.

Copy link
Member

Choose a reason for hiding this comment

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

Makes sense. I like the idea of having EventSource be the base class and CloudWatchEventSource subclass from it to include any of the cloudwatch event specific logic.

Copy link
Member Author

Choose a reason for hiding this comment

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

I pushed an update. Let me know what you think.

chalice/app.pyi Outdated


class Rate(ScheduleExpression):
unit = ... # type: str
Copy link
Member

Choose a reason for hiding this comment

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

The type here should be an integer. Or union of str and integer to be similar to Cron? I think I would prefer integer though if you can only provide whole numbers to rate.

Copy link
Member Author

Choose a reason for hiding this comment

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

That should be an integer, I'll update.

Copy link
Member

@kyleknap kyleknap left a comment

Choose a reason for hiding this comment

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

Looks good. Just had a couple more comments. I think we should be good once we have docs up.

'AWS:SourceArn': source_arn,
}
},
'Effect': 'Allow',
Copy link
Member

Choose a reason for hiding this comment

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

Without looking at what got removed in the diff, it is not very easy to tell what portion of the policy needs to be present for it to be skipped. Maybe separate this into tests where one tests that a specific policy entry skips over the add_permission call but the other entries causes add_permission to be triggered?

Copy link
Member Author

Choose a reason for hiding this comment

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

I refactored the test a bit to make this more clear.

return 'rate(%s %s)' % (self.value, unit)


class Cron(ScheduleExpression):
Copy link
Member

Choose a reason for hiding this comment

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

Did we want to add Cron and Rate to the __init__?

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't follow what you're asking. Can you elaborate?

Copy link
Member

Choose a reason for hiding this comment

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

Oh so I have to import those two from chalice.app right now, but I'm use to importing all of the user facing classes from chalice instead when I right my application.

Copy link
Member Author

Choose a reason for hiding this comment

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

ohhhh, chalice/__init__.py. Gotcha. Yeah I can add that.

@kyleknap
Copy link
Member

Cool. Looks good once docs are included, it should be good to merge. I also noticed that there was some missing coverage according to the codecov report. Do you know what that may be?

@jamesls
Copy link
Member Author

jamesls commented Jun 30, 2017

Yeah it was some of the new code I added for the base class refactoring. I added a isinstance check that's missing a testcase if you don't pass an instance of CloudWatchEventSource. Right now there are no other kinds so I can make one up for the test.

@jamesls
Copy link
Member Author

jamesls commented Jul 3, 2017

OK I think everything has been addressed, and docs have been added. Let me know if there's any more feedback.

cc @kyleknap @stealthycoin

Copy link
Member

@kyleknap kyleknap left a comment

Choose a reason for hiding this comment

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

Looks good. Just had a small comment. Otherwise, 🚢

.. code-block:: python

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

Choose a reason for hiding this comment

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

We may want to have all of these handler names share the function name handler() just in case if someone tries to literally copy and paste all of this. Maybe make these handler names more specific like cron_handler()?

Copy link
Member Author

Choose a reason for hiding this comment

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

You mean not share?

Copy link
Member

Choose a reason for hiding this comment

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

yes not share

Copy link
Member Author

Choose a reason for hiding this comment

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

OK I'll update that before merging.

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

Successfully merging this pull request may close these issues.

None yet

4 participants