1

I am trying to add memcache to my webapp deployed on GAE, and to do this I am using memcache.Client() to prevent damage from any racing conditions:

from google.appengine.api import memcache

client = memcache.Client()
class BlogFront(BlogHandler):
    def get(self):       
        global client 
        val = client.gets(FRONT_PAGE_KEY)
        posts = list()

        if val is not None:
            posts = list(val)
        else:
            posts = db.GqlQuery("select * from Post order by created desc limit 10")
            client.cas(FRONT_PAGE_KEY, list(posts))

        self.render('front.html', posts = posts)

To test the problem I have a front page for a blog that displays the 10 most recent entries. If there is nothing in the cache, I hit the DB with a request, otherwise I just present the cached results to the user.

The problem is that no matter what I do, I always get val == None, thus meaning that I always hit the database with a useless request.

I have sifted through the documentation:

And it appears that I am doing everything correctly. What am I missing?

(PS: I am a python newb, if this is a retarded error, please bear with me xD )

10
  • don't worry about race conditions right now. Just make it work as simply as you can using "add" and "get". And if what you are trying to save is over the limit for the size of a single object in memcache that might explain your issue. Commented May 8, 2014 at 15:27
  • If I replace the client.gets(key) and client.cas(key, val) by memcache.get(key) and memcache.set(key, val) everything works perfectly. The problem is using memcache.Client and the race conditions are a real problem :S Commented May 8, 2014 at 15:31
  • right you are then. Your "newb" threw me :P Dunno then... Commented May 8, 2014 at 15:33
  • Is there really a race condition ? How has it manifested itself in your situation ? You aren't really updating a value that needs to be atomic. The only real problem that could occurr is more of a dogpile effect. Also you don't even appear to be using CAS correctly as you current approach won't protect against a race condition, it will only detect it. You need a loop and a retry, as per the docs developers.google.com/appengine/docs/python/memcache and CAS only updates, it doesn't add. See the examples in the doc I have linked here Commented May 8, 2014 at 15:36
  • Also are posts the only dynamic element of the page ? If so why cache the posts and re-render the page, why not cache the rendered page ? Commented May 8, 2014 at 15:41

2 Answers 2

1

from google.appengine.api import memcache

class BlogFront(BlogHandler):
    def get(self):       
        client = memcache.Client() 
        client.gets(FRONT_PAGE_KEY)
        client.cas(FRONT_PAGE_KEY, 'my content')

For a reason I cannot yet possible understand, the solution lies in having a gets right before having a cas call ...

I think I will stick with the memcache non-thread-safe version of the code for now ...

Sign up to request clarification or add additional context in comments.

1 Comment

0

I suspect that the client.cas call is failing because there is no object. Perhaps client.cas only works to update and existing object (not to set a new object if there is none currently)? You might try client.add() (which will fail if an object already exists with the specified key, which I think is what you want?) instead of client.cas()

4 Comments

I want to use cas because cas protects against race conditions, while add does not :S Also, if there is no Object, then client would be None, and an exception would occur right? That is not the case :S
I disagree that add does not protect against race conditions. Add "[s]ets a key's value, if and only if the item is not already in memcache." (from developers.google.com/appengine/docs/python/memcache/…)
re: "Also, if there is no Object, then client would be None, and an exception would occur right?" No, I'm not sure why you think the client would be None in this case. The client is created by "memcache.Client()". val is None if there is no object.
This piece of code is used to update the cache. Add does not allow that, while cas allows that, ie, I can update the value of a key using cas.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.