Asynchronous view with client update for long running processes / views - django

I have one view in my app that can take quite a long time to be served to the client when requested. In order to inform the user that the server is working I want to present the user some kind like a progress bar, but it is not really a progress bar, it s more like this:
a) client is requesting /myapp/longrunningview/
b) server returns part of the html side, including someting animated that looks like the server is working. At the same time server is calculating the rest of the response, the process which takes very long
c) server finished and returns the response to the client
d) at client side the response is presented
It is not really a progress bar, since the user may request this page from a page outside my app, and I want to return instantly something to the user, without the need to wait for the entire process to be finished. The progress bar implementations that I have found are all based upon some form which is send to the server, while the client showing a progress bar, while waiting for the response.

I would use a celery task for this sort of thing. When the user makes the request, start the task and then send back a page with a progress spinner or whatever, then either have a piece of AJAX hit the server every few seconds asking if it's done, or utilize socketio and django-socketio or a similar package to push a "finished" notification to the client, which can then redirect you to wherever you need to go.
Resources:
Django-SocketIO https://github.com/stephenmcd/django-socketio
SocketIO http://socket.io/
Celery http://celeryproject.org/
Django-Celery http://docs.celeryproject.org/en/latest/django/index.html

Related

Django kills older requests

I am running a Django website over IIS. When a user saves an object it can take some time, so rather than have them wait for it to finish an AJAX request is sent to the server with the submission information and the page is immediately redirected. However, if the server gets many more requests that old saving request is killed rather inelegantly. The log files show that it ends mid execution with no error messages or other indication that it failed.
How do I keep older requests alive in Django?
P.S. I have already investigated starting a new multithreading Process but encountered issues around Django models, and I am looking for something more simple than Celery.
Turns out Django wasn't killing the requests, IIS was. There is a timeout setting for FastCGI, the medium between Django and IIS, that was set to 30 seconds. So when my saving request hit that time limit it just ended with no warning.
You can change this by clicking on the server name in IIS, then clicking the "FastCGI Settings" icon, then clicking the FastCGI application being used. Under "Process Model", change "Activity Timeout" and "Request Timeout" to a higher limit, I used 300 for 5 minutes to be safe.

Django Channels code is working on Chrome but not Firefox

I am writing a chat application using Django and Channels (new websocket implementation for Django). Users first enter a wait room, until at least 3 other people have joined, then they are directed to a chat room. The code works fine for Chrome, but is not working correctly for Firefox. Here is how it works:
On a new connect to the channel/websocket the server checks to see if at least three people are in the wait room (in consumers.py).
If at least three people are present it broadcasts a message to the channel/websocket using the Group function telling them to redirect.
The message is received by the clients and it executes a redirection in javascript.
Here are the steps I’ve taken to debug the problem:
The code works in browsers other than Firefox (e.g. Chrome).
The code works if the first two clients arriving to the wait room are Firefox and the last one (that triggers the server) is Chrome. It redirects all three clients.
If the first two clients are Chrome and the last client (that triggers the server) is Firefox it redirects the Chrome clients but not the Firefox client.
The problem is unlikely to be with the javascript running the redirection because replacing the code with a simple alert message (upon the client receiving the Group statement) is also not working in Firefox (but does work in Chrome). It is as if the Firefox client never receives the Group message when it is the client that triggers the server.
The chat uses channels and works on all browsers including Firefox. It successfully connects, sends messages, receives messages, and disconnects.
Based on these debugging steps I think something is going wrong when Firefox instigates the server code that executes the Group redirect. Do you have any suggestions for what might be going wrong? Do you have any suggestions that would help identify the problem?
Here is the code in consumers.py that I think is causing the problem:
#channel_session_user_from_http
#channel_session
def wait_connect(message):
try:
wait_room, created = WaitRoom.objects.get_or_create(title=title)
except WaitRoom.DoesNotExist:
log.debug('ws room does not exist title=%s', title)
return
Group('wait-'+title, channel_layer=message.channel_layer).add(message.reply_channel)
wait_user,created = wait_room.users.get_or_create(user=message.user)
userlist = WaitUser.objects.filter(wait_room=wait_room,is_active=1)
if len(userlist)>=3:
t = {t['url']='redirecturl'}
Group('wait-'+title, channel_layer=message.channel_layer).send({'text': json.dumps(t)})
Here is the javascript code that is executing the redirect:
$(function() {
var ws_scheme = window.location.protocol == "https:" ? "wss" : "ws";
var chatsock = new ReconnectingWebSocket(ws_scheme + '://' + window.location.host + window.location.pathname);
chatsock.onmessage = function(message) {
var data = JSON.parse(message.data);
window.location.replace(data.url);
};});

504 gateway timeout django site with nginx+fastcgi

we added ability for admin users to change server date&time through the portal. Changing the date&time back is working fine, but changing forward(more than fastcgi_read_timeout) is returning '504 gateway timeout' even though server time successfully changed behind the scenes.
Please advice how to handle this?
Thanks.
I had a very similar issue with another project. Maybe it is best to submit the date&time credentials (I assume you would be using NTP servers IPs to do this) through the portal asynchronously via a JavaScript AJAX request. Then, let the server then do its thing with the date&time.
Meanwhile, have the client side JavaScript, continuously probe the server with interval AJAX requests (perhaps every 5 seconds) to get back a response message on the server time. That way, each subsequent AJAX request initiates a new Nginx session and if the first fails/timeouts, then try a second time, if that fails, then try a third time, and so on.
This worked on our system. However, I do not know if your product has login/authentication credentials. If it does, then the user may have to log back in once all set and done because a change in time may also expire their log-in session. I don't think this is such a big deal though because theoretically they should only need to change the date/time once in a while if not just one time only. So it shouldn't have too much of an impact on the user experience.
tags: nginx, NTP, timeout, 504

making WebResponse GetResponse WebBot wait for redirect

I am making a bot that simulates a human user using a specific website.
When the user uses the site here is what happens
the user uploads a file by using the site's Browse button and then clicks Upload
the server responds immediately and the user sees a Please Wait gif
in the meantime the server is evaluating the file for errors. When it is done it redirects, and the user is take to a new .aspx page where they can correct the errors.
What I am not able to do w the bot is make it wait to get the redirect info.
The bot hits the website with this line of code (VB.NET)
Dim Response As HttpWebResponse = CType(Request.GetResponse(), HttpWebResponse)
The Response has the Please Wait gif in it, not the Errors.aspx page. Somehow I need to make the bot, execute that line of code above then, sorta listen to the same port(?) and wait for the web server to send another response.
Ideas?
I ended up just sleeping the thread, then hitting the url again, repeatedly till I got the response I wanted.

Connecting a desktop application with a website

I made an application using Qt/C++ that reads some values every 5-7 seconds and sends them to a website.
My approach is very simple. I am just reading the values i want to send and then i make an HTTP POST to the website. I also send the username and password to the website.
The problem is that i cannot find out if the request is successful. I mean that if i send the request and server gets it, i will get an HTTP:200 always. For example if the password is not correct, there is no way to know it. It is the way HTTP works.
Now i think i will need some kind of a protocol to take care the communication between the application and the website.
The question is what protocol to use?
If the action performed completes before the response header is sent you have the option of adding a custom status to it. If your website is built on PHP you can call header() to add the custom status of the operation.
header('XAppRequest-Status: complete');
if you can modify the server side script you could do the following
on one end :
You can make the HTTP post request via ajax
and evaluate the result of the ajax request.
On the serve side
On the HTTP request you do your process and if everything goes accordingly you can send data back to the ajax script that called it.
solves your problem .. ?