#35583: asgiref.sync.sync_to_async cannot be affected by close_old_connections
------------------------------+-----------------------------------------
     Reporter:  AlexandrOnuf  |                     Type:  Uncategorized
       Status:  new           |                Component:  Uncategorized
      Version:                |                 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
------------------------------+-----------------------------------------
 Rel. to https://code.djangoproject.com/ticket/34914#comment:3
 partially rel. to this implementation
 https://github.com/django/channels/blob/main/channels/db.py

 1. Let's assume, that we have django command, that creates a "server" that
 listening for a message from queue, or periodically do some job.
 2. Second point - our service have async function and requires DB calls
 (dummy example in ''_test'' function)
 3. let's assume. that we have Postgres DB running in docker compose - and
 to reproduce this bug, we should call **docker compose restart db**

 Similar to Django itself and, for example, to Django channels
 https://github.com/django/channels/blob/main/channels/db.py we want to be
 able to close closed connection (simplest way to reproduce - DB was
 restarted).

 **Expected behavior:** we are assuming, that we do same steps as we can
 see in Django project examples and we should see **success** message in
 logs.
 **Actual**: we will see ''failure: the connection is closed''

 **What we can see in code itself:**
 1. sync_to_async class will use its own isolated ThreadPoolExecutor
 2. django connections will be created withing this ThreadPoolExecutor and
 will be unavailable for us (this is my assumption)

 **Found workaround**
 Calling this code will implicitly have access to hidden DB pool and will
 close closed connections

 {{{
 syncio.run(sync_to_async(close_old_connections)())
 }}}


 Notes:
 1. I'm not really sure - is it a feature request or a bug (taking into
 account, how hard to find theoretical reason of it)
 2. I didn't dive into details of **async_to_sync** function/class

 Code snippet for Django command
 {{{
 import asyncio
 import time

 from asgiref.sync import sync_to_async
 from django.db import close_old_connections
 from django.core.management.base import BaseCommand

 # This can be any model
 from django.contrib.auth.models import User


 class Command(BaseCommand):
     def handle(self, *args, **options):
         while True:
             process_message()
             time.sleep(3)


 def process_message():
     print("close_old_connections")
     close_old_connections()

     print("run test")
     try:
         test()
         print("success")
     except Exception as e:
         print("failure:", str(e))
     print("done test")


 def test():
     asyncio.run(_test())


 async def _test():
     """
     Synthetic case - most likely, we will use ``sync_to_async`` as
 decorator for part of functions
     and will use it directly for other calls ``sync_to_async``.
     """
     await User.objects.afirst()
     await sync_to_async(
         User.objects.first
     )()
     await sync_to_async(
         User.objects.first,
         thread_sensitive=False,
     )()
 }}}
-- 
Ticket URL: <https://code.djangoproject.com/ticket/35583>
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/010701909183fac3-95fd11ee-f2e0-42ac-94a6-0992a68bf6d1-000000%40eu-central-1.amazonses.com.

Reply via email to