Wednesday, August 28, 2019

Re: Channels: launching a custom co-routine from SyncConsumer

On 8/15/19 11:10 PM, Andrew Godwin wrote:
> SyncConsumer isn't async - it runs inside a separate synchronous thread.
> You'll need to get the event loop from the other thread and use
> call_soon_threadsafe instead!

Sorry for the delay in getting back to you, it took me a while to go
through the different layers to find the appropriate event loop. Thank
you for the pointer, it got me headed down what I hope is the right path.

SyncConsumer is based on AsyncConsumer, with dispatch() ultimately
wrapped in SyncToAsync via DatabaseSyncToAsync. SyncConsumer should
have a guaranteed SyncToAsync instance with threadlocal on the executor
thread, because it is running inside a SyncToAsync to begin with. Is
that correct?

The following "works" as part of my sync consumer but I'm not positive
what the sharp edges are going to be:

def start_coroutine(self, coroutine):
loop = getattr(SyncToAsync.threadlocal, "main_event_loop", None)
if not (loop and loop.is_running()):
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.call_soon_threadsafe(loop.create_task, coroutine())

Where the coroutine is anything awaitable.

The documentation at
https://channels.readthedocs.io/en/latest/topics/consumers.html goes
into the opposite scenario, using Synchronous functions such as django
ORM from an AsyncConsumer, but would really benefit from an example of
something like an idle timeout implementation for a SyncConsumer.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/8bb3ac80-3b70-e8f6-697a-af5d86086612%40gmail.com.

No comments:

Post a Comment