-
Notifications
You must be signed in to change notification settings - Fork 421
refactor(apigateway): Add BaseRouter and duplicate route check #757
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
Conversation
Codecov Report
@@ Coverage Diff @@
## develop #757 +/- ##
===========================================
+ Coverage 99.93% 99.97% +0.04%
===========================================
Files 116 116
Lines 4953 4939 -14
Branches 276 275 -1
===========================================
- Hits 4950 4938 -12
+ Misses 1 0 -1
+ Partials 2 1 -1
Continue to review full report at Codecov.
|
Add behavior check for custom_formatter and correlation ids
@BVMiko @heitorlessa - added some of the feedback on #645 . Next i can look at some of the documentation work |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a great cleanup, two thoughts:
1/ Can we make BaseRouter an actual class to merge the routing logic between both ApiGatewayResolver and Router?
e.g., Router registers & decorates a route, then re-registers & re-decorates again, and do extra checks on cors and such, then finally gets called by the parent. We could do it later too, as we can launch as-is, have a maintenance issue, and tackle them later as a chore item.
2/ Let's support multiple methods for a given route in the parent so it's aligned and makes it easier to merge logic in the Router later too.
Minors as GH is giving me a hard time annotating in the right LOC:
-
Router.api
->Router.routes
-
method: Union[str, Tuple[str], List[str]],
->method: Union[str, Liststr]],
- I'd typically use
Sequence[str]
orIterable[str]
but it's been deprecated in 3.9; a list of strings suffices
- I'd typically use
- Docstrings for
include_router
as I'll surely forget the logic a few weeks ahead -
include_router
has the prefix logic we accidentally had a bug on "/" before, perhaps 1/ can help in case we find another one in the future.
Lemme know your thoughts on 1, as I think we had chatted about 2 already. Happy with everything else
@heitorlessa - I am going to switch to the docs next. This can merge if we are good at this point. Or I can contribute to add docs to this PR too. |
I’ll merge tomorrow or Friday - let’s start the docs in a separate PR as
there will be plenty of conversations
…On Wed, 13 Oct 2021 at 16:45, Michael Brewer ***@***.***> wrote:
@heitorlessa <https://github.com/heitorlessa> - I am going to switch to
the docs next. This can merge if we are good at this point.
Or I can contribute to add docs to this PR too.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#757 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAZPQBGRSNL73GI56WNYM2DUGWLSHANCNFSM5FWNDPVA>
.
|
@heitorlessa - i will start working on the docs PR next |
I find this clever yet puzzling that I can't shake the feeling this is wrong but it's the quirk of a dynamic language allowing such a thing. Every other solution I could think of like property setter, subclass hook to confirm they have set instance variables... would eventually become a N+1 problem as we'd need to keep track of router instances, loop + inject event and lambda context. Unless we go back to the idea of having a global config (here be dragons...)... I'll have a think for the next hour before merging just in case something comes up. We can always fix it later without impacting customers. |
@cakepietoast had a good idea on using a RequestState class and a route_state pointer so we can separate the concerns while not having a N+1 problem per se.
class BaseRouter:
def __init__(self):
self.router_state = RouterState()
@property
def current_event(self):
return self.router_state.current_event
@property
def lambda_context(self):
return self.router_state.lambda_context
@dataclass
class RouterState:
current_event: str = None
lambda_context: str = None
class ApiGatewayResolver(BaseRouter):
def resolve(self, event, context) -> Dict[str, Any]:
self.router_state.current_event = event
self.router_state.lambda_context = context
def include_router(self, router):
router.router_state = self.router_state
class Router(BaseRouter):
pass
router1 = Router()
router2 = Router() # just pretend this is in another module
app = ApiGatewayResolver()
app.include_router(router1)
app.include_router(router2) |
I'll merge as-is, refactor in a separate PR so you don't have to. Thanks again for making it leaner @michaelbrewer ! |
Issue #, if available:
Updates related to #645
Description of changes:
BaseRouter
which includes theget
,delete
,post
etc..Notes on layouts
This is an example project layout that we can use for the documentation section for this feature. In other cases it could be
src/hello_world/handler.py
(whichhello_world
is a descriptive name of the lambda, useful when there are multiple together in the samesrc
folder.Example source for the SAM
template.yml
, note the handler isapp.main.lambda_handler
and not justapp.lambda_handler
.Source for the lamdba handler:
src/app/main.py
. Other naming examples would behandler.py
,app.py
,index.py
,endpoint.py
. Note how the imports for therouters
are relative.Source for an example router:
src/app/routers/items.py
Source for how the unit testing could work using pytest:
src/tests/unit/test_app_main.py
Checklist
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.