Fix async generator exception handling in database dependencies
This commit is contained in:
@@ -118,3 +118,93 @@ For each task completed:
|
|||||||
---
|
---
|
||||||
|
|
||||||
## TODO List:
|
## TODO List:
|
||||||
|
|
||||||
|
1. fix the exception
|
||||||
|
|
||||||
|
INFO: 127.0.0.1:36902 - "POST /api/anime/search HTTP/1.1" 200
|
||||||
|
INFO: 127.0.0.1:36902 - "POST /api/anime/add HTTP/1.1" 500
|
||||||
|
ERROR: Exception in ASGI application
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "/home/lukas/miniconda3/envs/AniWorld/lib/python3.13/site-packages/anyio/streams/memory.py", line 98, in receive
|
||||||
|
return self.receive_nowait()
|
||||||
|
|
||||||
|
```^^
|
||||||
|
File "/home/lukas/miniconda3/envs/AniWorld/lib/python3.13/site-packages/anyio/streams/memory.py", line 93, in receive_nowait
|
||||||
|
raise WouldBlock
|
||||||
|
anyio.WouldBlock
|
||||||
|
|
||||||
|
During handling of the above exception, another exception occurred:
|
||||||
|
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "/home/lukas/miniconda3/envs/AniWorld/lib/python3.13/site-packages/starlette/middleware/base.py", line 78, in call_next
|
||||||
|
message = await recv_stream.receive()
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/home/lukas/miniconda3/envs/AniWorld/lib/python3.13/site-packages/anyio/streams/memory.py", line 118, in receive
|
||||||
|
raise EndOfStream
|
||||||
|
anyio.EndOfStream
|
||||||
|
|
||||||
|
During handling of the above exception, another exception occurred:
|
||||||
|
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "/home/lukas/miniconda3/envs/AniWorld/lib/python3.13/site-packages/uvicorn/protocols/http/httptools_impl.py", line 426, in run_asgi
|
||||||
|
result = await app( # type: ignore[func-returns-value]
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
self.scope, self.receive, self.send
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
)
|
||||||
|
^
|
||||||
|
File "/home/lukas/miniconda3/envs/AniWorld/lib/python3.13/site-packages/uvicorn/middleware/proxy_headers.py", line 84, in **call**
|
||||||
|
return await self.app(scope, receive, send)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/home/lukas/miniconda3/envs/AniWorld/lib/python3.13/site-packages/fastapi/applications.py", line 1106, in **call**
|
||||||
|
await super().**call**(scope, receive, send)
|
||||||
|
File "/home/lukas/miniconda3/envs/AniWorld/lib/python3.13/site-packages/starlette/applications.py", line 122, in **call**
|
||||||
|
await self.middleware_stack(scope, receive, send)
|
||||||
|
File "/home/lukas/miniconda3/envs/AniWorld/lib/python3.13/site-packages/starlette/middleware/errors.py", line 184, in **call**
|
||||||
|
raise exc
|
||||||
|
File "/home/lukas/miniconda3/envs/AniWorld/lib/python3.13/site-packages/starlette/middleware/errors.py", line 162, in **call**
|
||||||
|
await self.app(scope, receive, \_send)
|
||||||
|
File "/home/lukas/miniconda3/envs/AniWorld/lib/python3.13/site-packages/starlette/middleware/base.py", line 108, in **call**
|
||||||
|
response = await self.dispatch_func(request, call_next)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/home/lukas/Volume/repo/Aniworld/src/server/middleware/auth.py", line 209, in dispatch
|
||||||
|
return await call_next(request)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/home/lukas/miniconda3/envs/AniWorld/lib/python3.13/site-packages/starlette/middleware/base.py", line 84, in call_next
|
||||||
|
raise app_exc
|
||||||
|
File "/home/lukas/miniconda3/envs/AniWorld/lib/python3.13/site-packages/starlette/middleware/base.py", line 70, in coro
|
||||||
|
await self.app(scope, receive_or_disconnect, send_no_error)
|
||||||
|
File "/home/lukas/miniconda3/envs/AniWorld/lib/python3.13/site-packages/starlette/middleware/base.py", line 108, in **call**
|
||||||
|
response = await self.dispatch_func(request, call_next)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/home/lukas/Volume/repo/Aniworld/src/server/middleware/setup_redirect.py", line 147, in dispatch
|
||||||
|
return await call_next(request)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/home/lukas/miniconda3/envs/AniWorld/lib/python3.13/site-packages/starlette/middleware/base.py", line 84, in call_next
|
||||||
|
raise app_exc
|
||||||
|
File "/home/lukas/miniconda3/envs/AniWorld/lib/python3.13/site-packages/starlette/middleware/base.py", line 70, in coro
|
||||||
|
await self.app(scope, receive_or_disconnect, send_no_error)
|
||||||
|
File "/home/lukas/miniconda3/envs/AniWorld/lib/python3.13/site-packages/starlette/middleware/cors.py", line 91, in **call**
|
||||||
|
await self.simple_response(scope, receive, send, request_headers=headers)
|
||||||
|
File "/home/lukas/miniconda3/envs/AniWorld/lib/python3.13/site-packages/starlette/middleware/cors.py", line 146, in simple_response
|
||||||
|
await self.app(scope, receive, send)
|
||||||
|
File "/home/lukas/miniconda3/envs/AniWorld/lib/python3.13/site-packages/starlette/middleware/exceptions.py", line 79, in **call**
|
||||||
|
raise exc
|
||||||
|
File "/home/lukas/miniconda3/envs/AniWorld/lib/python3.13/site-packages/starlette/middleware/exceptions.py", line 68, in **call**
|
||||||
|
await self.app(scope, receive, sender)
|
||||||
|
File "/home/lukas/miniconda3/envs/AniWorld/lib/python3.13/site-packages/fastapi/middleware/asyncexitstack.py", line 14, in **call**
|
||||||
|
async with AsyncExitStack() as stack:
|
||||||
|
~~~~~~~~~~~~~~^^
|
||||||
|
File "/home/lukas/miniconda3/envs/AniWorld/lib/python3.13/contextlib.py", line 768, in **aexit**
|
||||||
|
raise exc
|
||||||
|
File "/home/lukas/miniconda3/envs/AniWorld/lib/python3.13/contextlib.py", line 751, in **aexit**
|
||||||
|
cb_suppress = await cb(\*exc_details)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/home/lukas/miniconda3/envs/AniWorld/lib/python3.13/contextlib.py", line 271, in **aexit**
|
||||||
|
raise RuntimeError("generator didn't stop after athrow()")
|
||||||
|
RuntimeError: generator didn't stop after athrow()
|
||||||
|
|
||||||
|
2. add actions
|
||||||
|
|
||||||
|
make sure that on a add only the added series is searched. so nfo and logo is loaded only for that one serie
|
||||||
|
```
|
||||||
|
|||||||
@@ -124,19 +124,15 @@ async def get_database_session() -> AsyncGenerator:
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
from src.server.database import get_db_session
|
from src.server.database import get_db_session
|
||||||
|
|
||||||
async with get_db_session() as session:
|
|
||||||
try:
|
|
||||||
yield session
|
|
||||||
except Exception:
|
|
||||||
# Re-raise the exception to let FastAPI handle it
|
|
||||||
# This prevents "generator didn't stop after athrow()" error
|
|
||||||
raise
|
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_501_NOT_IMPLEMENTED,
|
status_code=status.HTTP_501_NOT_IMPLEMENTED,
|
||||||
detail="Database functionality not installed"
|
detail="Database functionality not installed"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
async with get_db_session() as session:
|
||||||
|
yield session
|
||||||
except RuntimeError as e:
|
except RuntimeError as e:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||||
@@ -168,17 +164,17 @@ async def get_optional_database_session() -> AsyncGenerator:
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
from src.server.database import get_db_session
|
from src.server.database import get_db_session
|
||||||
|
|
||||||
async with get_db_session() as session:
|
|
||||||
try:
|
|
||||||
yield session
|
|
||||||
except Exception:
|
|
||||||
# Re-raise to let FastAPI handle it properly
|
|
||||||
# This prevents "generator didn't stop after athrow()" error
|
|
||||||
raise
|
|
||||||
except (ImportError, RuntimeError):
|
except (ImportError, RuntimeError):
|
||||||
# Database not available - yield None
|
# Database not available - yield None
|
||||||
yield None
|
yield None
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
async with get_db_session() as session:
|
||||||
|
yield session
|
||||||
|
except (ImportError, RuntimeError):
|
||||||
|
# Database became unavailable - this shouldn't happen but handle it
|
||||||
|
yield None
|
||||||
|
|
||||||
|
|
||||||
def get_current_user(
|
def get_current_user(
|
||||||
|
|||||||
Reference in New Issue
Block a user