-
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
ContextManager doesn't work with async, or maybe ExplicitContainer? #253
Comments
@meadsteve I got it working by looking at the A couple things that tripped me up though:
import asyncio
import dataclasses
from typing import Any, AsyncIterator, Awaitable # noqa
import lagom
from lagom.experimental.context_based import AsyncContextContainer, AwaitableSingleton
class Transaction:
def __init__(self) -> None:
pass
async def __aenter__(self) -> "Transaction":
return self
async def commit(self) -> None:
return
async def rollback(self) -> None:
return
async def close(self) -> None:
return
async def __aexit__(self, exc_type: type[BaseException] | None, *args: Any, **kwargs: Any) -> None:
if exc_type is None:
# Auto commit if there was no exception
await self.commit()
else:
# Auto rollback is there was an exception
await self.rollback()
return None
@dataclasses.dataclass
class UserModel:
user_id: int
class UserRepository:
def __init__(self, transaction: Transaction) -> None:
self._transaction = transaction
async def find_user(self, user_id: int) -> UserModel:
user = None
async with self._transaction:
# do some db stuff here, maybe create the user if it doesn't exist or something...
user = UserModel(user_id=user_id)
return user
class FindUserUseCase:
def __init__(self, user_repo: UserRepository) -> None:
self._user_repo = user_repo
async def execute(self, user_id: int) -> UserModel:
return await self._user_repo.find_user(user_id=user_id)
container = lagom.ExplicitContainer()
@lagom.context_dependency_definition(container) # type: ignore[misc]
async def provide_transaction() -> AsyncIterator[Transaction]:
transaction = Transaction()
try:
yield transaction
finally:
await transaction.close()
@lagom.dependency_definition(container) # type: ignore[misc]
async def provide_user_repository(c: lagom.Container) -> UserRepository:
transaction = await c[AwaitableSingleton[Transaction]].get()
return UserRepository(transaction)
@lagom.dependency_definition(container) # type: ignore[misc]
async def provide_find_user_use_case(c: lagom.Container) -> FindUserUseCase:
user_repository = await c[Awaitable[UserRepository]] # type:ignore[type-abstract]
return FindUserUseCase(user_repository)
context_container = AsyncContextContainer(container=container, context_types=[], context_singletons=[Transaction])
@lagom.bind_to_container(context_container)
async def find_user(user_id: int, find_user_use_case_awaitable: Awaitable[FindUserUseCase] = lagom.injectable) -> None:
find_user_use_case = await find_user_use_case_awaitable
user = await find_user_use_case.execute(user_id=user_id)
print(user)
if __name__ == "__main__":
asyncio.run(find_user(1)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Trying to use the context container to create a "transaction" for the whole "request". Here is some code to give an example:
When I run this I get:
Am I doing something wrong? If so, what?
The text was updated successfully, but these errors were encountered: