#33297: ASGI: Dead persistent postgres connections are not closed sometimes
-----------------------------------------+------------------------
               Reporter:  Matt Davis     |          Owner:  nobody
                   Type:  Bug            |         Status:  new
              Component:  Uncategorized  |        Version:  3.2
               Severity:  Normal         |       Keywords:
           Triage Stage:  Unreviewed     |      Has patch:  0
    Needs documentation:  0              |    Needs tests:  0
Patch needs improvement:  0              |  Easy pickings:  0
                  UI/UX:  0              |
-----------------------------------------+------------------------
 I have a two node cluster running a container with ASGI and Django backend
 for the ORM with uvicorn and fastapi--after 3 days one of the two nodes
 has resulted in a permanent Internal Server Error due to the DB connection
 being closed, the other node is still running fine.  I found a similar
 closed ticket (https://code.djangoproject.com/ticket/31905) but it was
 specifically about middleware, and this issue is not in the middleware.  I
 apologize if this issue ends up being one of the other libraries at play
 (DRF, uvicorn, fastapi), but I think that the actual cause of the stack
 trace is the closed Django DB connection which is contained in the top of
 the stack trace, `django/utils/asyncio.py", line 26, in inner` is always
 calling for the same stale connection once the error condition happens, as
 in nothing ever refreshes it.

 Django versions:
 Django==3.2.8

 {{{
 django.db.utils.OperationalError: SSL SYSCALL error: EOF detected
 INFO:     10.244.0.195:46240 - "GET /blog/posts HTTP/1.1" 500 Internal
 Server Error
 ERROR:    Exception in ASGI application
 Traceback (most recent call last):
   File "/usr/local/lib/python3.10/site-
 packages/django/db/backends/base/base.py", line 237, in _cursor
     return self._prepare_cursor(self.create_cursor(name))
   File "/usr/local/lib/python3.10/site-packages/django/utils/asyncio.py",
 line 26, in inner
     return func(*args, **kwargs)
   File "/usr/local/lib/python3.10/site-
 packages/django/db/backends/postgresql/base.py", line 236, in
 create_cursor
     cursor = self.connection.cursor()
 psycopg2.InterfaceError: connection already closed
 The above exception was the direct cause of the following exception:
 Traceback (most recent call last):
   File "/usr/local/lib/python3.10/site-
 packages/uvicorn/protocols/http/httptools_impl.py", line 375, in run_asgi
     result = await app(self.scope, self.receive, self.send)
   File "/usr/local/lib/python3.10/site-
 packages/uvicorn/middleware/proxy_headers.py", line 75, in __call__
     return await self.app(scope, receive, send)
   File "/usr/local/lib/python3.10/site-packages/fastapi/applications.py",
 line 208, in __call__
     await super().__call__(scope, receive, send)
   File "/usr/local/lib/python3.10/site-
 packages/starlette/applications.py", line 112, in __call__
     await self.middleware_stack(scope, receive, send)
   File "/usr/local/lib/python3.10/site-
 packages/starlette/middleware/errors.py", line 181, in __call__
     raise exc
   File "/usr/local/lib/python3.10/site-
 packages/starlette/middleware/errors.py", line 159, in __call__
     await self.app(scope, receive, _send)
   File "/usr/local/lib/python3.10/site-packages/starlette/exceptions.py",
 line 82, in __call__
     raise exc
   File "/usr/local/lib/python3.10/site-packages/starlette/exceptions.py",
 line 71, in __call__
     await self.app(scope, receive, sender)
   File "/usr/local/lib/python3.10/site-packages/starlette/routing.py",
 line 656, in __call__
     await route.handle(scope, receive, send)
   File "/usr/local/lib/python3.10/site-packages/starlette/routing.py",
 line 259, in handle
     await self.app(scope, receive, send)
   File "/usr/local/lib/python3.10/site-packages/starlette/routing.py",
 line 61, in app
     response = await func(request)
   File "/usr/local/lib/python3.10/site-packages/fastapi/routing.py", line
 226, in app
     raw_response = await run_endpoint_function(
   File "/usr/local/lib/python3.10/site-packages/fastapi/routing.py", line
 161, in run_endpoint_function
     return await run_in_threadpool(dependant.call, **values)
   File "/usr/local/lib/python3.10/site-packages/starlette/concurrency.py",
 line 39, in run_in_threadpool
     return await anyio.to_thread.run_sync(func, *args)
   File "/usr/local/lib/python3.10/site-packages/anyio/to_thread.py", line
 28, in run_sync
     return await get_asynclib().run_sync_in_worker_thread(func, *args,
 cancellable=cancellable,
   File "/usr/local/lib/python3.10/site-
 packages/anyio/_backends/_asyncio.py", line 805, in
 run_sync_in_worker_thread
     return await future
   File "/usr/local/lib/python3.10/site-
 packages/anyio/_backends/_asyncio.py", line 743, in run
     result = func(*args)
   File "/code/whitewhale/./fapi/blog.py", line 47, in blog_posts
     return serializer.data
   File "/usr/local/lib/python3.10/site-
 packages/rest_framework/serializers.py", line 745, in data
     ret = super().data
   File "/usr/local/lib/python3.10/site-
 packages/rest_framework/serializers.py", line 246, in data
     self._data = self.to_representation(self.instance)
   File "/usr/local/lib/python3.10/site-
 packages/rest_framework/serializers.py", line 663, in to_representation
     return [
   File "/usr/local/lib/python3.10/site-
 packages/django/db/models/query.py", line 280, in __iter__
     self._fetch_all()
   File "/usr/local/lib/python3.10/site-
 packages/django/db/models/query.py", line 1324, in _fetch_all
     self._result_cache = list(self._iterable_class(self))
   File "/usr/local/lib/python3.10/site-
 packages/django/db/models/query.py", line 51, in __iter__
     results = compiler.execute_sql(chunked_fetch=self.chunked_fetch,
 chunk_size=self.chunk_size)
   File "/usr/local/lib/python3.10/site-
 packages/django/db/models/sql/compiler.py", line 1173, in execute_sql
     cursor = self.connection.cursor()
   File "/usr/local/lib/python3.10/site-packages/django/utils/asyncio.py",
 line 26, in inner
     return func(*args, **kwargs)
   File "/usr/local/lib/python3.10/site-
 packages/django/db/backends/base/base.py", line 259, in cursor
     return self._cursor()
   File "/usr/local/lib/python3.10/site-
 packages/django/db/backends/base/base.py", line 236, in _cursor
     with self.wrap_database_errors:
   File "/usr/local/lib/python3.10/site-packages/django/db/utils.py", line
 90, in __exit__
     raise dj_exc_value.with_traceback(traceback) from exc_value
   File "/usr/local/lib/python3.10/site-
 packages/django/db/backends/base/base.py", line 237, in _cursor
     return self._prepare_cursor(self.create_cursor(name))
   File "/usr/local/lib/python3.10/site-packages/django/utils/asyncio.py",
 line 26, in inner
     return func(*args, **kwargs)
   File "/usr/local/lib/python3.10/site-
 packages/django/db/backends/postgresql/base.py", line 236, in
 create_cursor
     cursor = self.connection.cursor()
 django.db.utils.InterfaceError: connection already closed
 }}}

 Only a restart of the application fixes the problem.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/33297>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/051.599351fb932638b83261455965c4456d%40djangoproject.com.

Reply via email to