Django Channels: long running async function and where to save ORM object

149 views
Skip to first unread message

Sebastian Haase

unread,
Jul 15, 2018, 9:03:20 AM7/15/18
to Django users
Hi,
I'm still in the process of migration from channels 1 to channels 2...

One thing I'm interested in is related to [ http://channels.readthedocs.io/en/latest/one-to-two.html#application-instances ]
"""ASGI applications are now instantiated once per socket and can use local variables on self to store information"""

So, we have an `AsyncJsonWebsocketConsumer` where websocket clients want to operate on a django model instance - each websocket mostly on the same object.
With channels 1 we would always send with each message the `objID` - doing `obj=model.objects.get(pk=objID)` and read/write on `obj`.
In channels 2 I could save the `objID` server side in the consumer class - like `self.objID` with one initial message like `set-obj-id`.
For the ORM access I now have to do `obj = await database_sync_to_async( model.objects.get )(pk=self.objID)` 

QUESTION: Is is legitimate to store the "model instance itself" like `self.obj = await database_sync_to_async( model.objects.get )(pk=objID)` and keep that instance around for the lifetime of that socket -- doing some `await database_sync_to_async( self.obj.save )()` on some respective  messages ?
Note:  multiple websockets might operate on the same obj/objID ! So my feeling is that  would work as long as I keep testing with the `runserver` or in production as long as I know that I have only ONE PROCESS -- but in general the django caching mechanism might cause inconsistencies ... !?


Another, somewhat related question is regarding a kind of "background routine"  that I started to implement as an asyncio Task.  
Note:  It was kind of tricky to realize that I needed `asyncio.ensure_future` to get it run asynchronously -- ref. https://stackoverflow.com/questions/48871831/django-channels-async-consumer-does-not-appear-to-execute-asynchronously
Maybe that could be worked into the channels docs maybe here: http://channels.readthedocs.io/en/latest/topics/worker.html
Since that "routine" should be able to be canceled and pauses (I'm using an asyncio.event) from any websocket consumer:
QUESTION: What is the  best place to store that Task object ?  Again with `runserver` I can just use a global module-level `dict` to keep those Task objects.

The whole async experience is really twisting my mind  and interesting at the same time ;-)
Regards,
Sebastian


Andrew Godwin

unread,
Jul 16, 2018, 5:06:32 PM7/16/18
to django...@googlegroups.com
You are correct in that you could store the model instance on "self" but this would result in caching issues, as that instance would not be updated after the initial socket connection.

If you want to run "background routines", I would discourage you from doing these as random orphaned tasks launched from web processes - there's no provision in the server to track that task and clean up after it. Instead, I'd recommend running those kinds of tasks in a separate process.

Andrew

--
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...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/123c14e2-65c6-499e-9a27-b3a256aab099%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Sebastian Haase

unread,
Jul 16, 2018, 6:21:09 PM7/16/18
to django...@googlegroups.com
Thanks for the reply.   Should I still use async code inside that worker process ? 
While developing I simply do a    run_server    on the command line  --  then I would always have to do a    run_worker   in addition  -- right ?

-Sebastian

Andrew Godwin

unread,
Jul 18, 2018, 11:12:32 PM7/18/18
to django...@googlegroups.com
You can use async inside if you want, it's your choice. You will always have to run the separate process, though, yes. That's just a cleaner way of doing background tasks.

Andrew

--
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...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
Reply all
Reply to author
Forward
0 new messages