Open david-de2 opened 8 years ago
It depends what you want to do. Normally its easier to do it via a classic Ajax request, but consider the overhead of a TCP/IP handshake and teardown. Sending data via the websocket is possible, but then you may either broadcast it via Redis to other ws-connectors or keep it in a Redis data-bucket. A normal Django view then may look into that bucket and do whatever it likes.
Please close, if everything is clear.
I going to get status updates (what posts user exploring at the moment). So, I going to storage this posts in Redis. Like: PostId => UserIds. And when some post updated, I'll get all users for this post and send them notification.
So, basically I need to receive data on server side put it in reds. And send updates to clients.
By the docs I see that I can only send data. (Just to avoid excess IO file operations and DB calls - ,) but what about redis
? If my purpose of using redis is there any way to use django-websocket-redis
for receiving messages?
I would happy to use RESTful interface to send updates from client. But I going to storage currently visible entities on screen. It would generate a lot of requests to keep server updated.
I would glad to do my own push for this project by adding this functionality if it doesn't exists. We could restrict user to use only redis
, do you think it makes sense?
Could you please tell how can I receive data to put it in Redis data-bucket? Thanks.
@david-de2 if you really want to receive data from your websocket, you can use a custom subscriber http://django-websocket-redis.readthedocs.org/en/latest/installation.html?highlight=subscriber .
This is quite dangerous as you have to make sure to wrap any custom code in a try/except but "all you have to do" is override publish_message
with something like that
class MySubscriber(RedisSubscriber):
def publish_message(self, message, expire=None):
try:
# custom code goes here
except Exception:
# I mean it, catch everything, log it if needed but do catch everything
pass
return super(MySubscriber, self).publish_message(message, expire)
Keep in mind that your custom code also has the potential to considerably slow down your websocket so don't do any heavy lifting there. Creating a celery task might be your best option here.
nanuxbe, thank you for your response. Are you suggesting to even not put data in redis-bucket, I should do it through celery task, right?
You can put data in a redis bucket (if you configured celery to use redis, data will go through redis anyways) it's a matter of choice. Just don't do any database inserts or things like that which would considerably slow down your your application.
I was thinking of a celery task because the case where I had to use this was for a high load logging API which had to receive thousands of JSON messages a second and they needed to be parsed and inserted in a db.
Thank you for your help!
@nanuxbe thanks for explaining this so well. BTW, about celery: I recently discovered that if you use uWSGI, there is a built-in cron and timer. This means that if, for example you use django-post_office, you can send queued mail every 5 seconds by adding
from django.core.management import call_command
import uwsgidecorators
@uwsgidecorators.timer(5)
def send_queued_mail(num):
call_command('send_queued_mail')
to your wsgi.py
file. I therefore do not need celery anymore.
@david-de2 you're welcome
@jrief you're welcome as well. And thanks for the tip I didn't know about that. I think I'm going to be updating a few websites :-)
I'm sorry, I can't realise how to get current user (or request) in overridden publish_message
of RedisSubscriber
.
Could you please explain this?
@david-de2 you don't have access to the request at that stage of the cycle (due to how websockets work, ie: the connection is opened once and re-used after that). You do have access to the request during the initial setup of the connection in set_pusub_channels https://github.com/jrief/django-websocket-redis/blob/11b2b0f3981c088b1975e524383ae6132132c3e6/ws4redis/subscriber.py#L23 . If I wanted to have access to the user I would override this method and store the user id (once again, websockets are meant to be lightweight and fast, store as little as you can)
Something along the lines of:
user_id = None
def set_pubsub_channels(self, request, channels):
super(MySubscriber, self).set_pubsub_channels(request, channels)
try:
this.user_id = request.user.id
except AttributeError:
# Once again if anything were to happen inside your code,
# it would prevent the connection to work.
# So make sure to catch everything.
pass
I have never tried this approach but that's where I'd start if this was something I wanted to implement.
By the documentation I understand well how to send data from server through websockets, but I don't understand how to receive.
Basically I have client app and I want to send periodically from the client to server status. I don't understand how I can handle receiving messages from the client on server side? What URL I should use on client? Do I need to create django view add this into url.py and receive by someway through sockets?
Sorry for grammar mistakes.