tortoise-orm
tortoise-orm copied to clipboard
Unable to perform any orm related stuff from a websocket connection
Describe the bug Whenever I try to connect to a websocket connection from pytest, and I try to run some queries in the database, it crashes and returns the following error
Traceback:
apps/users/selectors.py:7: in get_user
return await User.get_or_none(**kwargs)
/usr/local/lib/python3.8/site-packages/tortoise/queryset.py:885: in _execute
instance_list = await self._db.executor_class(
/usr/local/lib/python3.8/site-packages/tortoise/backends/base/executor.py:124: in execute_select
_, raw_results = await self.db.execute_query(query.get_sql())
/usr/local/lib/python3.8/site-packages/tortoise/backends/asyncpg/client.py:36: in translate_exceptions_
return await func(self, *args)
/usr/local/lib/python3.8/site-packages/tortoise/backends/asyncpg/client.py:186: in execute_query
return len(rows), rows
/usr/local/lib/python3.8/site-packages/tortoise/backends/base/client.py:308: in __aexit__
await self.pool.release(self.connection)
/usr/local/lib/python3.8/site-packages/asyncpg/pool.py:666: in release
return await asyncio.shield(ch.release(timeout))
/usr/local/lib/python3.8/site-packages/asyncpg/pool.py:218: in release
raise ex
/usr/local/lib/python3.8/site-packages/asyncpg/pool.py:208: in release
await self._con.reset(timeout=budget)
/usr/local/lib/python3.8/site-packages/asyncpg/connection.py:1311: in reset
await self.execute(reset_query, timeout=timeout)
/usr/local/lib/python3.8/site-packages/asyncpg/connection.py:297: in execute
return await self._protocol.query(query, timeout)
asyncpg/protocol/protocol.pyx:323: in query
???
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
> ???
E asyncpg.exceptions._base.InterfaceError: cannot perform operation: another operation is in progress
See my code below:
async def is_authenticated(token: str = Security(oauth2_scheme)) -> Union[User, Exception]:
""" Verifies access token, returns user if it is valid (authenticated) else throws an error"""
try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[ALGORITHM])
if payload['token_type'] != "access":
raise CustomHTTPException(status_code=status.HTTP_403_FORBIDDEN,
detail="Could not validate credentials - Wrong token type)")
token_data = TokenData(**payload)
except jwt.JWTError:
raise CustomHTTPException(status_code=status.HTTP_403_FORBIDDEN,
detail="Could not validate credentials - Invalid signature of access token")
user = await get_user(id=token_data.user_id) **# Error is thrown right here**
if not user:
raise CustomHTTPException(status_code=status.HTTP_404_NOT_FOUND,
detail="User not found")
return user
async def is_authenticated_ws(websocket: WebSocket,
token: str = Query("")):
# Websocket specific authentication
try:
return await is_authenticated(token)
except:
await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
@websocket_app.websocket("/")
async def websocket_endpoint(websocket: WebSocket,
current_user: User = Depends(is_authenticated_ws)):
if not current_user:
return
service = await accept_user_connection(user_id=current_user.id, websocket=websocket)
await run_until_first_complete(
(producer_handler, {"service": service}),
(consumer_handler, {"service": service, "current_user": current_user})
)
class TestWebSockets:
@pytest.mark.asyncio
async def test_websocket_events(self, ws_client, actor_user):
token = create_token(actor_user.id, generate_verification_code())
with ws_client.websocket_connect(f"/ws/?token={token['access_token']}") as websocket:
...
Obviously it has to do something with the event loop. It is a huge but since in a production environment I should be able to test websocket events without any issues but right now I cant even query something from the database before I connect to a websocket.
@long2ice Could you please have an input on this? is it a bug or could this be resolved ?
I'm not sure, but tortoise-orm is not related to websocket
I know that it is not related to the websocket in general, all I am saying is that the orm does not work with the websocket tests. Inside websockets I have a normal ORM which works fine on connections but obviously you have to write some unit tests for it right? Therefore when I tried to write unit tests it did not work and threw an error. Therefore the issue is in the implementation of a library.
Did you run Tortoise.init
on start of test?
Did you run
Tortoise.init
on start of test?
Yeah Obviously, I have it as an event when the app is initialized, thing is that HTTP API Endpoints and it's unit tests are working fine with the library, However the websocket unit tests are not working because it throws an exception which is mentioned above
I am regretting that I chose this library for the production, I literally cant write any tests because of this issue.
I would not recommend this library to anyone, It is not a production ready library at all.
- Ton of bugs
- Literally no one cares about the issues that are opened here daily
- Very poor and trivial documentation examples
I am regretting that I chose this library for the production, I literally cant write any tests because of this issue.
I would not recommend this library to anyone, It is not a production ready library at all.
- Ton of bugs
- Literally no one cares about the issues that are opened here daily
- Very poor and trivial documentation examples
I had the same exception ("different loop") using Tortoise and FastAPI. Tortoise and your websocket_app must have the same event loop, Tortoise has a module for such integration (FastAPI), so I just had to create a fixture to instantiate the FastAPI app object and pass it to the register_tortoise function.
@viniciusao Thanks for the reply, I have a different FastAPI instance for tests, and have a websocket as a different instance as well which is mounted to the main app and test app. therefore it should have a two different event loops. I can write ordinary API tests without any issues but when I try to connect to the websocket endpoint from the tests, this error is thrown that I described before. There is something wrong with the dynamic asynchronous db creation (asyncpg) and Tortoise's event loop, they come in conflict and thats why error is thrown
I have been wasting too much time to resolve that issue but I could not, I ended up writing tests in a base database in a CI/CD integration level and I manually remove garbage collect those data as soon as tests are finished so no worries.
Regardless, This library sucks lol