Search code examples
pythondjangopollinglong-polling

Django long polling request timed-out


  1. Django 3.2
  2. DRF
  3. run using ./mange runserver
  4. when deploying planing to use 'nginx, uwsgi'

here is my backend code

class ChatHandler(APIView):
queryset = Chat.objects.all()
serialzier_class = MessageSerializer



def get_queryset(self):
    return self.queryset.filter(name=self.kwargs['room']).get()

def get(self, request, room):
    optionail_last_message_time  = request.data.get('at')
    new_messages = self.get_queryset().messages.filter(is_viewed=False)
    while not new_messages.exists():
        print(timezone.localtime().time(), 'no new messages')
        sleep(3)


    print(dir(self))
    print(dir(self.request))
    print('oh here it is')
    last_time = new_messages.last().created_at.timestamp()
    serializered_new_messages  = self.serialzier_class(instance=new_messages, many=True).data
    new_messages.update(is_viewed=True)

    return Response(
        {
            'messages': serializered_new_messages,
            'last_time': last_time,
            'initial': False
        }, status=200
    )

and here is the front-end code

 function textRequest(last_time) {
    $.ajax({
        method:'GET',
        url:long_url,
        data: {'at': last_time},                
        timeout:2000,   
        success : (data, status, xqhr) => {
            console.log(last_time)
            let messages = data['messages']
            console.log(messages)
            if (messages) {
                for (let message of messages) {
                    console.log(message)
                    inject_message(message)
                }
            }

            setTimeout(()=>{
                textRequest(data['last_time'])
            }, 5000)    
        },
        error: (error, status_text, xqhr)=> {
            if ((error.readyState == 0) && (status_text =='timeout')) {
                console.log(status_text)
                textRequest()
                console.log('sent')
            }
        },
    })

}

window.addEventListener('load', ()=>{
    textRequest()
})

issues:

  1. when i make refresh to the page it sends a new request to the
    back-end, and will continue in its recreation sending the requests, and back-end server receives a hundreds of requests

question: How to limit the received number of request?

  1. when the server finds the data, and processes it back to the front-end, the response doesn't arrive over there ' in front-end side' because the the request it is already died ' reached the timeout its limit'

question: What should i do to avoid that? question: Is there a way to know from the back-end if the request already reached its timeout?

request: could you please, provide me to implement long polling in Django, i am stuck in this issues for a days ?

thanks in advance


Solution

  • i was able to make it work through this code below in the backend:

    class ChatLongPolling(MainConfig):
    serializer_class = MessageSerializer 
    
    def get(self, request, name):
        messages = self.get_queryset().messages
        messages_filter = messages.filter(is_sent=False)
        while not messages_filter.exists():
            print('searching..')
            sleep(1)
            return JsonResponse({'empty':'empty'})
        else:    
            messages = self.serializer_class(instance=messages_filter, many=True).data
            messages_filter.update(is_sent=True)
            print(messages)
            return JsonResponse({'messages': messages})
    

    and here is the front-end side

    function make_json_request(url){
        let request = new XMLHttpRequest()
        request.open('get', url)
        request.responseType = 'json'
        request.addEventListener('load', function() {
            let response = request.response
            if (response['messages']){
                let messages = response['messages']
                console.log(messages)
                for (let message of messages) {
                    append(message)
                }
            }
        });
    
        request.addEventListener('abort', function(){
            console.log('abort')
        });
    
        request.addEventListener('error', function(){
            console.log('error')
            setTimeout(()=>{make_json_request(url)}, 1000);
        });
    
        request.send()        
    }
    
    function get_all_messages(url){
        make_json_request(url)
    }
    
    function longpolling(url) {
        make_json_request(url)
        setTimeout(()=>{longpolling(url)}, 1000);
    }
    
    send_message()
    get_all_messages(store_url)
    longpolling(long_url)