Asynchronous signals with asynchronous

My post-processing model uses the post_save signal:

 from django.core.signals import request_finished from django.dispatch import receiver from models import MyModel from pipeline import this_takes_forever @receiver(post_save, sender=MyModel) def my_callback(sender, **kwargs): this_takes_forever(sender) 

this_takes_forever procedure performs an IO, so I want to defer it to avoid too many requests.

I thought this was a great option for the new asyncio module. But it’s not easy for me to understand the whole process.

I think I will need to adapt the signal receiver as follows:

 @receiver(post_save, sender=MyModel) def my_callback(sender, **kwargs): loop = asyncio.get_event_loop() loop.run_until_complete(this_takes_forever(sender)) loop.close() 

Provided that this_takes_forever also a coroutine.

 @coroutine def this_takes_forever(instance): # do something with instance return instance 

Sounds too magical to work. And actually it stops with AssertionError :

 AssertionError at /new/ There is no current event loop in thread 'Thread-1'. 

I do not see where I should start the cycle in this context. Has anyone tried something like this?

+6
source share
1 answer

You do not get any benefit in your case:

 @receiver(post_save, sender=MyModel) def my_callback(sender, **kwargs): this_takes_forever(sender) 

equally

 @receiver(post_save, sender=MyModel) def my_callback(sender, **kwargs): loop = asyncio.get_event_loop() loop.run_until_complete(this_takes_forever(sender)) loop.close() 

in terms of runtime. loop.run_until_complete waits for the completion of the call to this_takes_forever(sender) coroutine, so you get a synchronous call in the second case, as well as in the previous one.

About AssertionError : you start the Django application in multi-threaded mode, but asyncio creates a default event loop for the main thread only β€” you need to register a new loop for each user-created thread where you need to call the asynchronous call code.

But, let us say it again, asyncio cannot solve your specific problem, it is simply incompatible with Django.

The standard way for Django is to defer a long-term code to the celery task (see http://www.celeryproject.org/ )

+3
source

Source: https://habr.com/ru/post/969665/


All Articles