What role does Redis serve in Django Channels - django

Recently I've been using django channels makes its support websocket protocol, I use a microservice way, other components through connection django channels, but I have to write a Consumer class for each connection for receiving and handling, for example class Consumer(AsyncWebsocketConsumer):, which still use the redis, pointed out that this part is the official document as a channel layer storage, so it is as a message queue, the cache or other commonly used functions exist?
I write to find out if there is a Consumer for each connection, and whether I can think of it as acting as a message queue.
However, I have not found relevant materials to support my point of view.
Could you please tell me whether my understanding is correct or not? I sincerely hope that you can provide relevant materials for reference whether it is correct or not.

It depends on how you are using it. The primary purpose of redis in django-channel_layers is to store the necessary information required for different instances of consumers to communicate with one another.
For example, in the tutorial section of channels documentation, it is clear that Redis is used as a storage layer for channel names and group names. These are stored within Redis so that they can be accessed from any consumer instance. If for example, I create a group called 'users' and then add 3 different channel names to it, this information is stored in Redis. Now, whenever I want to send data to the channels in the group I can simply reference the group from my consumer and Django-channels will automatically retrieve the channel names stored under that group in Redis.
On the other hand, if you want to use consumers in a non-conventional way, that is, as background workers then Redis becomes a message queue. That's because when you send a message containing a task to be done by one of the background workers (a consumer that 'consumes' the tasks) those messages have to be stored somewhere so that the background workers can retrieve them as they finish up other tasks.

Related

Notifying clients about an event via DRF

I want to know if there really is a way of notifying clients about a certain event, VIA Djangorestframework. I know it can be achieved with websockets via channels, but I couldn't find any material that explains everything in a step by step process. If anyone can help me than thanks already.
After a long time, I find the solution.
Actually I am using django rest framework(DRF) and django channels. What I wanted to achieve was to send message to a particular user and not to broadcast it in a group, by the api request. That is of course, a call from asynchronous code.
You can achieve this by sending message to specific channels as mentioned in django channels official docs.
This is possible because whenever client joins the group, it is automatically assigned a channel that can uniquely identify that client. So what we need is that we save that channel into the database and whenever required, get it from database, as specified here. You can save the channel to the database like so
I hope this was helpful.

Go/C++ gRPC client channel and stub lifecycle

I have several Go and C++ services, that act as servers and clients, i.e. those are long-living services, that from time-to-time talk to other services.
I cannot find anywhere in gRPC docs whether the client channels and stubs should be long-lasting reusable objects or they should be created on every call. Or, maybe, I should create some kind of a channel/stub pool, where a pair of a channel and a stub exists, for example, for each thread and gets updated, refreshed on some interval or condition.
According to official docs, you are encouraged to reuse stubs and channels when possible.
https://grpc.io/docs/guides/performance/

Dynamically handle channels to publish to with Redis in C++

I have 2 applications (a GUI in javascript and another in C++) which need to communicate to each other.
The C++ application (server) contains multiple realtime sensor data which it has to stream to the GUI (client). The data is buffered and sent as a big chunk. The GUI simply renders the data and doesn't buffer it locally (current library renders relatively slow).
We want to use Redis where each channel is a sensor. On the client side the user can select which sensor has to be streamed. This requires to let the server somehow know which channels to publish to.
Now the question is more about performance and extensibility. Which scenario is best?
Publish all sensor data. +-30 sensors with data at max 64 bit. Each up to 10,000 samples streamed at up to 50hz. (This is maxing out absolutely everything, but does give a ballpark).
Store the channel names in Redis as a JSON object or namespaced keys. Listen for a set event server-side, get the channels and cache them and dynamically publish to the channels.
Same as above but get the channels during every cycle from Redis without listening to any set event.
Use a configuration channel where the client publishes the configuration (via JSON string) when it's changed. Server side we subscribe to the configuration channel and handle the new channels appropriately.
Something else. Please elaborate.
Try to use redis streams feature from recently released redis 5.0. If you are looking for performant C++ library, which supports redis streams try to use bredis, for example.

Is there any way to build an interactive terminal using Django Channels with it's current limitations?

It seems with Django Channels each time anything happens on the websocket there is no persistent state. Even within the same websocket connection, you can not preserve anything between each call to receive() on a class based consumer. If it can't be serialized into the channel_session, it can't be stored.
I assumed that the class based consumer would be persisted for the duration of the web socket connection.
What I'm trying to build is a simple terminal emulator, where a shell session would be created when the websocket connects. Read data would be passed as input to the shell and the shell's output would be passed out the websocket.
I can not find a way to persist anything between calls to receive(). It seems like they took all the bad things about HTTP and brought them over to websockets. With each call to conenct(), recieve(), and disconnect() the whole Consumer class is reinstantiated.
So am I missing something obvious. Can I make another thread and have it read from a Group?
Edit: The answers to this can be found in the comments below. You can hack around it. Channels 3.0 will not instantiate the Consumers on every receive call.
The new version of Channels does not have this limitation. Consumers stay in memory for the duration of the websocket request.

django-channels databinding on model.save()

I have a channels app that is using databinding. When changes are made with django admin they are being pushed to the web as expected. I have loop set up on a socket connection to do some long polling on a gpio unit and update the db, these changes are not being pushed to the web. Channels documentation says:
Signals are used to power outbound binding, so if you change the values of a model outside of Django (or use the .update() method on a QuerySet), the signals are not triggered and the change will not be sent out. You can trigger changes yourself, but you’ll need to source the events from the right place for your system.
How do I go about triggering these changes, as it happens with admin?
Thanks and please let me know if this is to vague.
The relevant low-level code is in lines 121-187 of channels/binding/base.py (at least in version 1.1.6). That's where the signals are received and processed. It involves a few different things, such as keeping track of which groups to send the messages to. So it's a little involved, but you can probably tease out how to do it, looking at that code.
The steps involved are basically:
Find the right groups for the client
Format your message in the same way that the databinding code would (see this section of the docs)
Send the message to all the relevant groups you found in step 1.
Alternatively, you might consider using a REST API such that the socket code submits a POST to the API (which would create a database record via the ORM in the normal way) rather than directly creating database records. Your signals will happen automatically in that case. djangorestframework (server-side) and requests (client-side, if you're using python for the long-polling code) are your friends if you want to go that way, for sure. If you're using another language for the long-polling client, there are many equivalent packages for REST API client work.
Good luck!