-
Notifications
You must be signed in to change notification settings - Fork 227
Description
While doing some work on a Django project, I ran into an issue that I can't add a task to be run in an already running loop from a model_save signal using the method meant for this very action: asyncio.run_coroutine_threadsafe
I might be wrong in some of my assumptions, but I think using run_coroutine_threadsafe should not require the thread_sensitive argument to be given as false. (which is specially a hard problem in Django since I don't control things like await model_instance.asave()
)
A bit more context, here is the part of the code that runs on django signals:
def model_changed( self, signal_name, sender, signal, instance, **kwargs ):
asyncio.run_coroutine_threadsafe(
self.start_task_now( task, reason = f"Change ({signal_name}) on {instance}" ),
self.loop
)
which then, running something like this in the start_task_now function gives an error:
await sync_to_async( lambda: None )()
>>> RuntimeError: Single thread executor already being used, would deadlock
My current workaround:
def start( self, is_robust = False ):
...
self.loop = asyncio.new_event_loop()
asyncio.set_event_loop( self.loop )
#Run tasks from other threads, explicitly safe
self.task_reason_jobs_queue = asyncio.Queue()
self.create_task( self.consume_task_reason_jobs_queue() )
...
async def consume_task_reason_jobs_queue( self ):
while True:
task, reason = await self.task_reason_jobs_queue.get()
await self.start_task_now( task, reason )
self.task_reason_jobs_queue.task_done()
I could be wrong thinking the run_coroutine_threadsafe should work in the first place my work around might just be the correct solution, but I guessed I might as well create an issue and let those that know better decide.