How a lengthy HTTP poll with Django feeds

I am trying to use an HTTP poll for a web request, but cannot find a suitable example in the channel documentation, all about web sockets.

What I need to do if you are using an HTTP message:

  • waiting for a message in a group to be sent when a specific model is saved (possibly using signals)
  • wait timeout if message is not received

and then return something to the customer.

Now I have a code that can be seen in the examples:

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)

So I need to return something in this http_consumerthat will show that I have nothing to send until I can block here. Maybe I just can’t return anything? And then I have to catch a new message in a specific group or reach a timeout and send a response to the client.

, message.reply_channel -, , , :

  • , (-), , ?
+4
1

, , , .

, , , 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

, , answer_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)
+1

Source: https://habr.com/ru/post/1667798/


All Articles