cache.ram doesnt return a result until a certain request finishes

56 views
Skip to first unread message

Alfonso Serra

unread,
May 2, 2016, 12:16:27 PM5/2/16
to web...@googlegroups.com
Im trying to use cache.ram for a progress bar and i have this problem.

I have 2 controllers,
progress: that changes cache.ram each second
getprog: that retrieves the cache.ram value whenever i like.

import json as Json

#convert a variable into a json response
def json(var):
    response
.headers['Content-Type'] = "application/json; charset=utf-8"
   
return Json.dumps(var, ensure_ascii=False)

#get progress status
def getprog():
    msg
= cache.ram('message', lambda: None, None)
   
return json({"msg": msg})

#start a process that updates the progress
def progress():
   
from time import sleep
   
# when a form is submitted, change progress each second
   
if request.ajax:
       
for i in range(10):
            cache
.ram('message', lambda: i, time_expire=0)
           
print "main:", i
            sleep
(1)
       
return "done"
   
else:
        cache
.ram('message', lambda: -1, time_expire=0)
   
return locals()

When progress is triggered it begins to change cache.ram("message") each second

If i visit getprog when progress is working, on localhost works well, i get the current value, but on pythonanywhere, getprog returns a response when progress is finished, not while at it.

Is there any parameter or way to tell cache.ram to return the current value without waiting for other controllers to finish?

Thanks.

PD: i have tried without time.sleep, but i get the same result, cant ask for the progress until the main controller (the one that updates cache.ram finishes)

Niphlod

unread,
May 2, 2016, 4:17:58 PM5/2/16
to web2py-users
two possible issues:
a) you're not using session.forget(response). To avoid concurrent modification of the same value in session, by default requests insisting on the same session will be serialized. Whenever you use ajax and you don't use session, use session.forget(response)
b) cache.ram tries to avoid concurrent modifications of the same key: this means that both reads and writes are blocked if something else is reading/writing the value... this is infinitesimally less noticeable than a).

Alfonso Serra

unread,
May 2, 2016, 10:50:19 PM5/2/16
to web2py-users
Thanks Niphlod.

With session.forget on both controllers and while progress is working, getprog returns a response right away with the initial value, not the current one.

It seems that cache.ram acts like the session object, it doesnt change until the initial request (progress) finishes. Which is something that doesnt happen on localhost only on production. Looks like there are some blocking operations on this case.

Any suggestion?

is there any simpler way to implement a progress bar without having to smash the db if posible?



Niphlod

unread,
May 3, 2016, 8:23:24 AM5/3/16
to web2py-users
I smashed my head around it too and if the "animation" doesn't take a huge variation (i.e. one second OR 60 seconds) I usually get away with animating it with javascript until finished.

Anthony

unread,
May 3, 2016, 11:06:03 AM5/3/16
to web2py-users
I don't think this has anything to do with cache.ram. If you're using the Pythonanywhere free tier, you only get 1 uWSGI worker, so your app can only handle one request at a time. You should observe the same issue if you make any concurrent requests, whether you're reading/writing to cache.ram or not.

Note, switching to a paid plan with multiple workers may not help either -- depending on how uWSGI is set up, there may be multiple processes, each with its own independent cache.ram (so different requests may hit different caches).

Anthony
Reply all
Reply to author
Forward
0 new messages