-
Notifications
You must be signed in to change notification settings - Fork 37
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
Fix usage of a single object instances for multiple concurrent requests #70
Conversation
moto/core/responses.py
Outdated
@classmethod | ||
def method_dispatch( # type: ignore[misc] | ||
cls, to_call: Callable[[ResponseShape, Any, str, Any], TYPE_RESPONSE] | ||
) -> Callable[[Any, str, Any], TYPE_RESPONSE]: | ||
""" | ||
Takes a given unbound function (part of a Response class) and executes it for a new instance of this | ||
response class. | ||
Can be used wherever we want to specify different methods for dispatching in urls.py | ||
:param to_call: Unbound method residing in this Response class | ||
:return: A wrapper executing the given method on a new instance of this class | ||
""" | ||
|
||
def _inner(request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE: | ||
return getattr(cls(), to_call.__name__)(request, full_url, headers) | ||
|
||
return _inner | ||
|
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.
This is the main logic used for this change.
:return: A wrapper executing the given method on a new instance of this class | ||
""" | ||
|
||
@functools.wraps(to_call) # type: ignore |
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.
This is currently needed to pass the test test_core.test_server.test_domain_dispatched_with_service
(with modifications). It not really wraps the method completely, so this should be discussed.
Merged upstream in getmoto#6746 |
Motivation
Currently, for the following services:
we use a single instance of the respective
...Response
class to handle all the requests.In LocalStack, this leads to issues with parallel requests influencing each others state, most notably of region and account.
There are a couple of different ways to fix this, we chose one that was minimally intrusive to the existing logic, but ensured a separate instance of the Response class for every request.
Unaffected services use the
dispatch
method. There are some services which use the classmethoddispatch
on an instance, but since that does not make a difference (even though it can be confusing), we did not change it with this PR.Changes
method_dispatch
class method in the BaseResponse class, which will take an unbound function as input, and execute the corresponding method on a new instance on the class. This ensures proper typing and having the type checker catch potential errors, while being able to keep the current pattern of dispatching.