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(event-handler): Add AppSync handler decorator #363

Merged
merged 19 commits into from
Mar 31, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
ce80a90
feat(event-handler): Add AppSync handler decorator
michaelbrewer Mar 25, 2021
c7709bf
test(event-handler): Use pathlib
michaelbrewer Mar 25, 2021
f145c04
fix(tracer): Correct type hint for MyPy
michaelbrewer Mar 25, 2021
f4c07aa
Merge branch 'develop' into feat-event-handler-appsync
michaelbrewer Mar 25, 2021
2b82642
docs(event-handler): Initial markdown docs
michaelbrewer Mar 26, 2021
9f4e3e8
feat(event-handler): Add an implicit appsync handler
michaelbrewer Mar 26, 2021
3f664d7
docs(event-handler): Add implicit handler example
michaelbrewer Mar 26, 2021
4f43365
docs(event-handler): Add full amplify example
michaelbrewer Mar 26, 2021
36b088e
chore(event-handler): Add more docs
michaelbrewer Mar 27, 2021
347091f
chore(event-handler): Add current_event
michaelbrewer Mar 29, 2021
d969e98
Merge branch 'develop' into feat-event-handler-appsync
michaelbrewer Mar 29, 2021
7d98715
refactor(event-handler): Remove include_event and incluce_context opt…
michaelbrewer Mar 30, 2021
240b0a6
chore: bump ci
michaelbrewer Mar 30, 2021
f009f56
Merge branch 'develop' into feat-event-handler-appsync
michaelbrewer Mar 30, 2021
dc93055
Merge branch 'develop' into feat-event-handler-appsync
michaelbrewer Mar 30, 2021
8f04851
refactor(event-handler): Move to up to
michaelbrewer Mar 30, 2021
daa56f9
chore(event-handler): Add debug logging to appsync resolver
michaelbrewer Mar 30, 2021
02818db
docs(event-handler): Add more detailed example to docstring
michaelbrewer Mar 30, 2021
e778cf0
chore(event-handler): Rename to _get_resolver
michaelbrewer Mar 31, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions aws_lambda_powertools/event_handler/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""
Event handler decorators for common Lambda events
"""

from .appsync import AppSyncResolver

__all__ = ["AppSyncResolver"]
113 changes: 113 additions & 0 deletions aws_lambda_powertools/event_handler/appsync.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import logging
from typing import Any, Callable

from aws_lambda_powertools.utilities.data_classes import AppSyncResolverEvent
from aws_lambda_powertools.utilities.typing import LambdaContext

logger = logging.getLogger(__name__)


class AppSyncResolver:
"""
AppSync resolver decorator

Example
-------

**Sample usage**

from aws_lambda_powertools.event_handler import AppSyncResolver

app = AppSyncResolver()

@app.resolver(type_name="Query", field_name="listLocations")
def list_locations(page: int = 0, size: int = 10) -> list:
# Your logic to fetch locations with arguments passed in
return [{"id": 100, "name": "Smooth Grooves"}]

@app.resolver(type_name="Merchant", field_name="extraInfo")
def get_extra_info() -> dict:
# Can use "app.current_event.source" to filter within the parent context
account_type = app.current_event.source["accountType"]
method = "BTC" if account_type == "NEW" else "USD"
return {"preferredPaymentMethod": method}

@app.resolver(field_name="commonField")
def common_field() -> str:
# Would match all fieldNames matching 'commonField'
return str(uuid.uuid4())
"""

current_event: AppSyncResolverEvent
lambda_context: LambdaContext

def __init__(self):
self._resolvers: dict = {}

def resolver(self, type_name: str = "*", field_name: str = None):
"""Registers the resolver for field_name

Parameters
----------
type_name : str
Type name
field_name : str
Field name
"""

def register_resolver(func):
logger.debug(f"Adding resolver `{func.__name__}` for field `{type_name}.{field_name}`")
self._resolvers[f"{type_name}.{field_name}"] = {"func": func}
return func

return register_resolver

def resolve(self, event: dict, context: LambdaContext) -> Any:
"""Resolve field_name

Parameters
----------
event : dict
Lambda event
context : LambdaContext
Lambda context

Returns
-------
Any
Returns the result of the resolver

Raises
-------
ValueError
If we could not find a field resolver
"""
self.current_event = AppSyncResolverEvent(event)
self.lambda_context = context
resolver = self._get_resolver(self.current_event.type_name, self.current_event.field_name)
return resolver(**self.current_event.arguments)

def _get_resolver(self, type_name: str, field_name: str) -> Callable:
"""Get resolver for field_name

Parameters
----------
type_name : str
Type name
field_name : str
Field name

Returns
-------
Callable
callable function and configuration
"""
full_name = f"{type_name}.{field_name}"
resolver = self._resolvers.get(full_name, self._resolvers.get(f"*.{field_name}"))
if not resolver:
raise ValueError(f"No resolver found for '{full_name}'")
return resolver["func"]

def __call__(self, event, context) -> Any:
"""Implicit lambda handler which internally calls `resolve`"""
return self.resolve(event, context)
5 changes: 4 additions & 1 deletion aws_lambda_powertools/utilities/data_classes/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
from aws_lambda_powertools.utilities.data_classes.appsync_resolver_event import AppSyncResolverEvent
"""
Event Source Data Classes utility provides classes self-describing Lambda event sources.
"""

from .alb_event import ALBEvent
from .api_gateway_proxy_event import APIGatewayProxyEvent, APIGatewayProxyEventV2
from .appsync_resolver_event import AppSyncResolverEvent
from .cloud_watch_logs_event import CloudWatchLogsEvent
from .connect_contact_flow_event import ConnectContactFlowEvent
from .dynamo_db_stream_event import DynamoDBStreamEvent
Expand Down

This file was deleted.

Loading