11

This is specifically related to the Google App Engine Memcache API, but I'm sure it also applies to other Memcache tools.

The dictionary .get() method allows you to specify a default value, such as dict.get('key', 'defaultval')

This can be useful if it's possible you might want to store None as a value in a dictionary.

However, the memcache.get() does not let you to do this. I've modified my @memoize decorator so it looks like this:

def memoize(keyformat, time=1000000):

    """Decorator to memoize functions using memcache."""
    def decorator(fxn):
        def wrapper(*args, **kwargs):
            key = keyformat + str(args[1:]) + str(kwargs)
            from google.appengine.api import memcache
            data = memcache.get(key)
            if Debug(): return fxn(*args, **kwargs) 
            if data:
                if data is 'None': data =  None
                return data
            data = fxn(*args, **kwargs)
            if data is None: data = 'None' 
            memcache.set(key, data, time)
            return data
        return wrapper
    return decorator  

Now I'm sure there's a good argument that I shouldn't be storing None values in the first place, but let's put that aside for now. Is there a better way I can handle this besides converting None vals to strings and back?

JJ.
  • 4,974
  • 5
  • 39
  • 48

3 Answers3

7

A possible way to do this is to create new class that defines None for this purpose, and assign instances of this to the cache (unfortunately you cannot extend None). Alternatively, you could use the empty string "", or avoid storing None/null values altogether (absence of the key implies None).

Then check for instances of your 'None' class when you check the result of mc.get(key) (is None, == "", etc)

Dana the Sane
  • 14,762
  • 8
  • 58
  • 80
4

You could do something like what Haskell and Scala does and store an Option dictionary. The dictionary contains two keys: one key to indicate that it is valid and one key that is used to hold the data. Something like this:

{valid: true, data: whatyouwanttostore}

Then if get return None, you know that the cache was missed; if the result is a dictionary with None as the data, the you know that the data was in the cache but that it was false.

tomjen
  • 3,779
  • 3
  • 29
  • 35
0

Not really.

You could store a None value as an empty string, but there isn't really a way to store special data in a memcache.

What's the difference between the cache key not existing and the cache value being None? It's probably better to unify these two situations.

habnabit
  • 9,906
  • 3
  • 32
  • 26
  • 2
    Actually, it can be useful to distinguish them. For example, suppose I have a (expensive) way to authenticate users, and I cache the results - the user's details - in memcache. If I get back a 'no such user' response, I probably want to cache that negative response, or else a user can DoS my service by trying to log in with invalid usernames over and over. – Nick Johnson May 22 '09 at 10:52
  • 1
    This is exactly the type of situation which I found myself in. Sometimes you want to know that a function returned 'None' but also that it's been done recently enough so that it shouldn't be executed again. – JJ. May 29 '09 at 01:06