def cached(method):
 @gen.coroutine
 def cached_method(self, *args, **kwargs):
  uri = self.request.path
  short_url = self.truncate(uri)
  if self.get_argument('flush_cache', False):
   app_log.info('flushing cache %s', short_url)
   (yield method(self, *args, **kwargs))
   return
  pending_future = self.pending.get(uri, None)
  loop = IOLoop.current()
  if pending_future:
   app_log.info('Waiting for concurrent request at %s', short_url)
   tic = loop.time()
   (yield pending_future)
   toc = loop.time()
   app_log.info('Waited %.3fs for concurrent request at %s', (toc - tic), short_url)
  try:
   with time_block(('cache get %s' % short_url)):
    cached_pickle = (yield self.cache.get(self.cache_key))
   if (cached_pickle is not None):
    cached = pickle.loads(cached_pickle)
   else:
    cached = None
  except Exception as e:
   app_log.error('Exception getting %s from cache', short_url, exc_info=True)
   cached = None
  if (cached is not None):
   app_log.debug('cache hit %s', short_url)
   for (key, value) in cached['headers'].items():
    self.set_header(key, value)
   self.write(cached['body'])
  else:
   app_log.debug('cache miss %s', short_url)
   future = self.pending[uri] = Future()
   try:
    (yield method(self, *args, **kwargs))
   finally:
    self.pending.pop(uri, None)
    future.set_result(None)
 return cached_method

def cached ( method ) : @ gen . coroutine def cached_method ( self , * args , ** kwargs ) : uri = self . request . path short_url = self . truncate ( uri ) if self . get_argument ( 'flush_cache' , False ) : app_log . info ( 'flushing cache %s' , short_url ) ( yield method ( self , * args , ** kwargs ) ) return pending_future = self . pending . get ( uri , None ) loop = IOLoop . current ( ) if pending_future : app_log . info ( 'Waiting for concurrent request at %s' , short_url ) tic = loop . time ( ) ( yield pending_future ) toc = loop . time ( ) app_log . info ( 'Waited %.3fs for concurrent request at %s' , ( toc - tic ) , short_url ) try : with time_block ( ( 'cache get %s' % short_url ) ) : cached_pickle = ( yield self . cache . get ( self . cache_key ) ) if ( cached_pickle is not None ) : cached = pickle . loads ( cached_pickle ) else : cached = None except Exception as e : app_log . error ( 'Exception getting %s from cache' , short_url , exc_info = True ) cached = None if ( cached is not None ) : app_log . debug ( 'cache hit %s' , short_url ) for ( key , value ) in cached [ 'headers' ] . items ( ) : self . set_header ( key , value ) self . write ( cached [ 'body' ] ) else : app_log . debug ( 'cache miss %s' , short_url ) future = self . pending [ uri ] = Future ( ) try : ( yield method ( self , * args , ** kwargs ) ) finally : self . pending . pop ( uri , None ) future . set_result ( None ) return cached_method
a caching decorator based on parameter objects .