0

I'm trying to access a session variable with AJAX. I have two different views, the main one (index) and another one only returning the session value (refreshSession).

The main one starts a thread that is changing the session value every second but when the view that only returns the session value access to it, the changes that the thread is doing are being lost.

// views.py //

def refreshSession(request):
    sesAlarm = request.session['alarm']
    return JsonResponse({'alm': sesAlarm})

def index(request):
    request.session['alarm'] = 0

    t = Thread(target = threadFunction, args=(request,))
    t.daemon = True
    t.start()

    context={}
    return HttpResponse(template.render(context, request))

def threadFunction(request):
    while True:
        request.session['alarm'] += 1
        time.sleep(1)


// JS //

var idAlarm = setInterval(function(){
        $.ajax({
          type:"POST",
          url:"/app/update_session/",
          cache: 'false',
          success: function(data) {
            alert(data.alm);
          }
        });
      }, 5000);

This code always shows alerts with '0'. I think the problem is that changes in the thread are not being reflected in the request in refreshSession() because request is not passed by "reference" to the thread (I'm a main C programmer).

If I use a global variable instead of a session it works perfect, the alert shows the number increasing. But I've read that using global variables in views is not recommended.

So, what am I missing? How should I share the session with threads? Should I use global variables in this case?

Thank you!

Edit: This is just an example of the problem that I have, I've simplified it to be easy to understand and useful to others. The thread is a complex application and the web app will not be public, just a GUI of easy access to the app.

RbnRncn
  • 51
  • 4
  • What session backend are you using? You would have to save the session to its backend after every change. – mfrackowiak Jan 23 '19 at 11:19
  • Are you sure all requests use the same session (maybe check the `request.session_key`!). – Bernhard Vallant Jan 23 '19 at 11:22
  • @mfrackowiak This may be the problem. I'm using cache as backend. But how do I save the changes to cache? Do I have to do it manually? – RbnRncn Jan 23 '19 at 11:30
  • @BernhardVallant I did that, and yes, they are using the same session. But it is a good one! – RbnRncn Jan 23 '19 at 11:32
  • Welcome to stackoverflow! There is two things that i would recommend firstly. You must join your threads to be sure they will finish before parent and the second question is, the session is a shared space of memory from parent, to avoid unexpected behaviours you must to use Lock functions. Take a look to this one: https://stackoverflow.com/questions/3310049/proper-use-of-mutexes-in-python. – Gabriel Pereira Jan 23 '19 at 11:35
  • @GabrielPereira Thank you! It is necessary/recommended to join threads when they are set as daemon? And about the Lock, I'm not changing the value of the session in more than one thread, only reading, so it should not be a problem, am I wrong? – RbnRncn Jan 23 '19 at 11:44
  • When you set as daemon the main process just dies when all child threads get finished but on your case you are using a web "containered" application and you will try to fill the output buffer with the view content before your threads get finished. Is important in this case to set the wait point to have all data from child before the Django fill the view output buffer. Is a good practice to use Lock when you're not using atomic synchronisation on variables to avoid unexpected behaviours generated by race conditions. – Gabriel Pereira Jan 23 '19 at 11:49
  • 1
    If you want to create process that updates some stateful data i strongly recommend the usage of cache server like Redis or Memcache and separate the process that updates the data from the web application, web apps should be stateless once if it crashes your data will be lost. – Gabriel Pereira Jan 23 '19 at 11:56
  • @GabrielPereira The session variable that I'm using is just to show or hide an image depending on what the thread is doing in the server. So, it doesn't really matters (in my case) if it crashes. – RbnRncn Jan 23 '19 at 12:18
  • In this case a simple way to implement what you want is to process the session alarm on each request your JS does. I don't see a needing to use threads for this and create a new thread each time your index get requested will leak your app and crash at some point. – Gabriel Pereira Jan 23 '19 at 12:23
  • @GabrielPereira I've added an Edit. The problem is simplified to be easy to understand and useful to other people, the thread is doing other things that have to be done in a thread. I just want to use a session to communicate between the client, the server views and the thread in the server. The web will not be public so there is no risk of crashing, it will be controlled. – RbnRncn Jan 23 '19 at 12:44
  • @RbnRncn i get what you mean, in my opinion separate the process and use a cache like Redis or Memcache would be a good option because you can store your session from django and access from another process or application. Create threads on django views doesn't look a good idea considering the request life cycle. I'm not fully sure how django manage sessions but if he stores sessions on files, a thread on request time will not be able to access, since the stream to communicate with the session file should be closed at end of the request. – Gabriel Pereira Jan 23 '19 at 13:52
  • 1
    Threads are absolutely not the answer to anything like this. Apart from anything else, you cannot guarantee that your request will always be served by the same process, so following requests will probably not have access to the thread data. Use an external data store. – Daniel Roseman Jan 23 '19 at 15:52

0 Answers0