2017-01-25 5 views
3

Я пытаюсь реализовать длительный опрос HTTP для веб-запроса, но не могу найти подходящий пример в документации по каналам, все о веб-сокетах.Как сделать длительный опрос HTTP с каналами Django

Что мне нужно сделать, потребляя сообщение HTTP или:

  • ждать сообщения о группе, которая будет отправлена, когда определенная модель сохраняется (с использованием сигналов, вероятно)
  • ожидания для таймаут, если не получено ни одного сообщения

, а затем вернуть что-то клиенту.

Сейчас у меня есть код, который можно увидеть в примерах:

def http_consumer(message): 
    # Make standard HTTP response - access ASGI path attribute directly 
    response = HttpResponse("Hello world! You asked for %s" % message.content['path']) 
    # Encode that response into message format (ASGI) 
    for chunk in AsgiHandler.encode_response(response): 
     message.reply_channel.send(chunk) 

Так что я должен вернуть что-то в этом http_consumer, что будет означать, что у меня нет ничего, чтобы отправить, на данный момент, но я не могу Здесь нет блока. Может быть, я просто ничего не могу вернуть? И тогда я должен поймать новое сообщение в определенной группе или достигнуть таймаута и отправить ответ клиенту.

Кажется, что мне нужно будет хранить message.reply_channel где-то так, что я могу ответить позже, но я в недоумении относительно того, как:

  • поймать сообщение группы и сгенерировать ответ
  • генерировать ответ, когда сообщение не получено (тайм-аут), может быть, сервер задержки может работать здесь?

ответ

0

Итак, способ, которым я закончил это, описан ниже.

У потребителя, если я нахожу, что у меня нет немедленного ответа на отправку, я буду хранить message.reply_channel в группе, которая будет уведомлена в случае соответствующих событий, и запланировать сообщение с задержкой, которое будет срабатывать, когда максимальное время ожидания достигнуто.

group_name = group_name_from_mac(mac_address) 
Group(group_name).add(message.reply_channel) 
message.channel_session['will_wait'] = True 

delayed_message = { 
    'channel': 'long_polling_terminator', 
    'content': {'mac_address': mac_address, 
       'reply_channel': message.reply_channel.name, 
       'group_name': group_name}, 
    'delay': settings.LONG_POLLING_TIMEOUT 
} 
Channel('asgi.delay').send(delayed_message, immediately=True) 

Тогда могут произойти две вещи. Либо мы получаем сообщение в соответствующей Группе, и ответ отправляется раньше, либо приходит сообщение с задержкой, сигнализирующее, что мы исчерпали время, которое нам пришлось ждать, и должны вернуть ответ, указывающий на отсутствие событий.

Для того, чтобы вызвать сообщение, когда соответствующее событие происходит, я полагаться на Django сигналы:

class PortalConfig(AppConfig): 
    name = 'portal' 

    def ready(self): 
     from .models import STBMessage 

     post_save.connect(notify_new_message, sender=STBMessage) 

def notify_new_message(sender, **kwargs): 
    mac_address = kwargs['instance'].set_top_box.id 
    layer = channel_layers['default'] 
    group_name = group_name_from_mac(mac_address) 
    response = JsonResponse({'error': False, 'new_events': True}) 
    group = Group(group_name) 
    for chunk in AsgiHandler.encode_response(response): 
     group.send(chunk) 

Когда истекает время ожидания, я получаю сообщение о long_polling_terminator канале, и мне нужно отправить сообщение что указывает на то, что нет никаких событий:

def long_polling_terminator(message): 
    reply_channel = Channel(message['reply_channel']) 
    group_name = message['group_name'] 
    mac_address = message['mac_address'] 
    layer = channel_layers['default'] 
    boxes = layer.group_channels(group_name) 
    if message['reply_channel'] in boxes: 
     response = JsonResponse({'error': False, 'new_events': False}) 
     write_http_response(response, reply_channel) 
     return 

Последнее, что нужно сделать, это удалить эту reply_channel из группы, и я делаю это в http.disconnect потребителя:

def process_disconnect(message, group_name_from_mac): 
    if message.channel_session.get('will_wait', False): 
     reply_channel = Channel(message['reply_channel']) 
     mac_address = message.channel_session['mac_address'] 
     group_name = group_name_from_mac(mac_address) 
     Group(group_name).discard(reply_channel) 

 Смежные вопросы

  • Нет связанных вопросов^_^