Как испустить событие SocketIO на сервере
Я запускаю приложение gangent-socketio Django.
У меня что-то похожее на этот класс
@namespace('/connect')
class ConnectNamespace(BaseNamespace):
def on_send(self, data):
# ...
Однако, если я получаю события от javascript-клиента, все работает и, например, событие send
обрабатывается правильно
Я немного потерял, если хочу emit
какое-то событие на стороне сервера. Я могу сделать это внутри класса с помощью socket.send_packet
Но теперь я хочу связать какое-то событие с сигналом post_save
, поэтому я хотел бы send_packet
извне этого класса пространства имен, одним из способов сделать это было бы
ConnectNamespaceInstance.on_third_event('someeventname')
Я просто не могу понять, как я могу получить экземпляр ConnectNamespaceInstance
Чтобы подвести итог, я просто хочу отправить событие клиенту javascript после получения сигнала post_save
Ответы
Ответ 1
Что вы, вероятно, хотите сделать, это добавить переменную модуля для отслеживания соединений, например _connections
, например:
_connections = {}
@namespace('/connect')
class ConnectNamespace(BaseNamespace):
а затем добавьте методы initialize
и disconnect
, которые используют некоторый счастливый идентификатор, который вы можете ссылаться позже:
def initialize(self, *args, **kwargs):
_connections[id(self)] = self
super(ConnectNamespace, self).initialize(*args, **kwargs)
def disconnect(self, *args, **kwargs):
del _connections[id(self)]
super(ConnectNamespace, self).disconnect(*args, **kwargs)
Когда вам нужно сгенерировать событие, вы можете просто найти правильное соединение в переменной _connections
и отключить событие с помощью emit
.
(Не пробовал ничего из этого, но я использовал аналогичную модель на многих других языках: не вижу причин, почему это не будет работать и на Python).
Ответ 2
Другой, тогда ответ Femi, который, я думаю, безусловно работает. Использование Redis, вероятно, даст вам немного большую гибкость, и использование greenlet от gevent может квалифицировать этот подход как немного более "в рамках", поскольку вы уже используете gevent-socketio: D
REDIS_HOST = getattr(settings, 'REDIS_HOST', '127.0.0.1')
class YourNamespace(BaseNamespace):
def _listener(self, channel_label_you_later_call_in_post_save):
pubsub = redis.StrictRedis(REDIS_HOST).pubsub()
pubsub.subscribe(chan)
while True:
for i in pubsub.listen():
self.send({'message_data': i}, json=True)
def recv_message(self, message):
if is_message_to_subscribe(message):
self.spawn(self.listener, get_your_channel_label(message))
И в вашем post_save вы можете сделать
red = redis.StrictRedis(REDIS_HOST)
red.publish(channel_label, message_data)