-
Notifications
You must be signed in to change notification settings - Fork 15
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
separate sync_container_context to fix problems with the same contextvar token for every context #93
Conversation
…var token for every context
Codecov ReportAll modified and coverable lines are covered by tests ✅
Flags with carried forward coverage won't be shown. Click here to find out more.
|
@alexanderlazarev0 Hi) there is some problem with new container context. The problem is that contextvar token variable is the same for all requests. To fix this I had to separate sync container context |
@lesnik512 |
@alexanderlazarev0 not right now, in the evening I will make an example |
@alexanderlazarev0 Error was the following: File "that_depends/providers/context_resources.py", line 96, in _async_inner Trying to build small reproducible example now |
@lesnik512 Yes I was trying to reproduce this, but wasn't able to for now. Is this with |
@alexanderlazarev0 it's in kafka consumer. There is a method which called on each message from topic: @container_context(build_di_context("write"))
async def process_one_message(
self,
message,
_: dict[str, typing.Any] | None = None,
) -> None:
... Theres is also another version of this error: ValueError |
@lesnik512 Okay seems the |
@alexanderlazarev0 I think, the problem is occured when decorator used: |
@lesnik512 Ah! I got it I think, its a 2 liner: # container_context class
def __call__(self, func: typing.Callable[P, T]) -> typing.Callable[P, T]:
if inspect.iscoroutinefunction(func):
@wraps(func)
async def _async_inner(*args: P.args, **kwargs: P.kwargs) -> T:
async with self: # <- HERE
return await func(*args, **kwargs) # type: ignore[no-any-return]
return typing.cast(typing.Callable[P, T], _async_inner)
@wraps(func)
def _sync_inner(*args: P.args, **kwargs: P.kwargs) -> T:
with self: # <-- HERE
return func(*args, **kwargs)
return _sync_inner This should fix it: def __call__(self, func: typing.Callable[P, T]) -> typing.Callable[P, T]:
if inspect.iscoroutinefunction(func):
@wraps(func)
async def _async_inner(*args: P.args, **kwargs: P.kwargs) -> T:
async with container_context():
return await func(*args, **kwargs) # type: ignore[no-any-return]
return typing.cast(typing.Callable[P, T], _async_inner)
@wraps(func)
def _sync_inner(*args: P.args, **kwargs: P.kwargs) -> T:
with container_context():
return func(*args, **kwargs)
return _sync_inner This is still on |
@alexanderlazarev0 seems, like this could work. But _initial_context must be passed, I think, in container_context(self._initial_context) |
@alexanderlazarev0 But still I have no idea how to reproduce this in tests) |
@lesnik512 I think you might be able to reproduce it by calling an
Yes you are right this will need to be added. I will let you know if i can reproduce the issue. |
@lesnik512 Yes got It and the suggest fix works! from that_depends import providers
from that_depends.container import BaseContainer
from that_depends.injection import inject
from that_depends.providers.context_resources import container_context
def context_resource_creator():
yield "interesting"
class MyContainer(BaseContainer):
context_resource = providers.ContextResource(context_resource_creator)
@container_context()
@inject
def some_injected(depth, val = MyContainer.context_resource):
if depth ==2:
return val
return some_injected(depth+1)
if __name__ == "__main__":
some_injected(1) # RuntimeError: <Token used var=<ContextVar name='CONTAINER_CONTEXT' at 0x10497e930> at 0x1049b2180> has already been used once
|
@lesnik512 So the question is really then just one of taste:
|
@alexanderlazarev0 Nicely done! So I reverted to the previous version, applied fix and wrote some tests #94. Please, take a look |
separate sync_container_context to fix problems with the same contextvar token for every context