Skip to main content

Decorator for Memcache Get/Set in python

I have suggested some time back that you could modularize and stitch together fragments of js and css to spit out in one HTTP connection. That makes the page load faster. I also indicated that there ways to tune them by adding cache-control headers.

On the server-side however, you could have a memcache layer on the stitching operation. This saves a lot of Resources (CPU) on your server. I will demonstrate this using a python script I use currently on my site to generate the combined js and css fragments.

So My stitching method is like this
@memize(region="jscss")
def joinAndPut(files, ext):
    res = files.split("/")
    o = StringIO.StringIO()
    for f in res:
        writeFileTo(o, ext + "/" + f + "." + ext)  #writes file out
    ret = o.getvalue()
    o.close()
    return ret;

The method joinAndPut is *decorated* by memize. What this means is, all calls to joinAndPut are now wrapped (at runtime) with the logic in memize. All you want do is use the someregion+files+ext as your key in memcache. I extended an example in App Engine CookBook.
def memize(region="", time=3600):
    """Decorator to memoize functions using memcache.
       The calling function must give a memizekey named parameter
    """
    def decorator(fxn):
        def wrapper(*args, **kwargs):
    
            if (not "memizekey" in kwargs):
                raise Exception("memize-d function does not send key")
            key = region + kwargs["memizekey"]
            del kwargs["memizekey"]

            data = memcache.get(key)
            if data is None or not settings.DEBUG:
                data = fxn(*args, **kwargs)
                memcache.set(key, data, time)
                logging.info("Cached");
            else: logging.info("Cache hit");
            
            return data
        return wrapper
    return decorator

This version of memize takes a region instead of key. The intention is a key is generally given at runtime, and is controlled by application logic, so it goes into the *actual* call (ex given below). But the region is (generally a prefix) decided at coding time to avoid runtime collisions. You could also update memcache by force at runtime. A sample call would be something like
class MainPage(webapp.RequestHandler):
  def get(self, files, ext):
      if ext == "css":
          self.response.headers['Content-Type'] = 'text/css'
      elif ext == "js":
          self.response.headers['Content-Type'] = 'text/javascript'
      
      forceUp = self.request.get("force");
      if 'true' == forceUp:
          forceUp = True
      else:
          forceUp = False
          self.response.headers["Cache-Control"] = "public, max-age=432000"
      
      con = joinAndPut(files, ext , memizekey=files + "." + ext, memizeforce=forceUp) 
      self.response.out.write(con);
  

For people coming from java background, this is similar to an around Advice in Aspect Oriented Programming. If I get time, may be I'll post another sample in AOP :)

Popular posts from this blog

Powered By

As it goes, We ought to give thanks to people who power us. This page will be updated, like the version page , to show all the tools, and people this site is Powered By! Ubuntu GIMP Firebug Blogger Google [AppEngine, Ajax and other Apis] AddtoAny Project Fondue jQuery

One page Stock

Alright.. That was a long absence. The whole last week I dint blog. I dint go away. I was "occupied". I was learning stock trading. Its very fascinating. I have a good weeeked blog for you all. Here is my experience. I can literally hyper-link every word from the following paragraphs, but I am writing it as simple as I can so you can look up the italicised words in wikipedia . I got a paper trading account from a brokerage firm . You need one brokerage account first. Then it can be an Equity account where all your money is yours or a Margin account , where some of the money is lent by the brokerage firm. Then I get Buying power , which is the dollor value of how much stocks you can buy. I can make profit by simple rules. Buy when Price is low. Sell when price is high. There is another more intersting way of earning money. Selling short . Thats when price is not high, per say, but when are confident that the price WILL go down. then buy back when its lowest. This is what