Django Каналы потребителя потребляют 1 звонок дважды - PullRequest
0 голосов
/ 01 мая 2020

Я использую комбинацию DRF 3.11.0 и каналов 2.4.0 для реализации бэкэнда, и он размещен на Heroku 1 dyno с подключенным ресурсом Redis. У меня есть сокет на моем интерфейсе React, который успешно отправляет / получает от внутреннего сервера.

У меня возникают проблемы, когда любое сообщение, отправляемое обратно во внешний интерфейс через сокет, отправляется дважды. Через console.log я подтвердил, что передний конец пингует задний конец только один раз. Я могу подтвердить через print() внутри вызова API, что функция также вызывает async_to_sync(channel_layer.group_send) только один раз. Проблема исходит от моего потребителя - когда я использую print(self.channel_name) внутри share_document_via_videocall(), я вижу, что вызываются два экземпляра с разными self.channel_name (specific.AOQenhTn!fUybdYEsViaP и specific.AOQenhTn!NgtWxuiHtHBw. Похоже, что потребитель имеет подключен к двум отдельным каналам, но я не уверен, почему. Когда я помещаю операторы print() в свой connect(), я вижу его только go через процесс подключения один раз.

Как я могу гарантировать, что Я подключен только к одному каналу?

в settings.py:

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            #"hosts": [('127.0.0.1', 6379)],
            "hosts": [(REDIS_HOST)],
        },
    },
}

Потребитель:

import json
from asgiref.sync import async_to_sync
from channels.db import database_sync_to_async

from channels.generic.websocket import AsyncWebsocketConsumer
from rest_framework.authtoken.models import Token
from django.contrib.auth.models import AnonymousUser
from .exceptions import ClientError
import datetime
from django.utils import timezone

class HeaderConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        print("connecting")

        await self.accept()
        print("starting")
        print(self.channel_name)
        await self.send("request_for_token")


    async def continue_connect(self):
        print("continuing")
        print(self.channel_name)

        await self.get_user_from_token(self.scope['token'])

        await self.channel_layer.group_add(
            "u_%d" % self.user['id'],
            self.channel_name,
        )
        #... more stuff


    async def disconnect(self, code):
        await self.channel_layer.group_discard(
            "u_%d" % self.user['id'],
            self.channel_name,
        )


    async def receive(self, text_data):
        text_data_json = json.loads(text_data)
        if 'token' in text_data_json:
            self.scope['token'] = text_data_json['token']
            await self.continue_connect()


    async def share_document_via_videocall(self, event):

        # Send a message down to the client
        print("share_document received")
        print(event)
        print(self.channel_name)
        print(self.user['id'])

        await self.send(text_data=json.dumps(
            {
                "type": event['type'],
                "message": event["message"],
            },
        ))

    @database_sync_to_async
    def get_user_from_token(self, t):
        try:
            print("trying token" + t)
            token = Token.objects.get(key=t)
            self.user = token.user.get_profile.json()
        except Token.DoesNotExist:
            print("failed")
            self.user = AnonymousUser()

Вызов API REST:

class ShareViaVideoChat(APIView):
    permission_classes = (permissions.IsAuthenticated,)

    def post(self, request, format=None):
        data = request.data
        recipient_list = data['recipient_list']

        channel_layer = get_channel_layer()
        for u in recipient_list:
            if u['id'] != None:
                print("sending to:")
                print('u_%d' % u['id'])
                async_to_sync(channel_layer.group_send)(
                    'u_%d' % u['id'],
                    {'type': 'share_document_via_videocall',
                     'message': {
                             'document': {'data': {}},
                             'sender': {'name': 'some name'}
                         }
                     }
                )

        return Response()

1 Ответ

1 голос
/ 01 мая 2020

в связи с тем, что вы получаете звонки с разными названиями каналов, вы уверены, что ваш веб-интерфейс дважды не подключался к потребителю? Проверьте в консоли отладки в вашем браузере.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...