Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(484)

Side by Side Diff: appengine/findit/common/cache_decorator.py

Issue 2456603003: [Predator] Add local cache for get command output. (Closed)
Patch Set: . Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright 2015 The Chromium Authors. All rights reserved. 1 # Copyright 2015 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """This module provides a decorator to cache the results of a function. 5 """This module provides a decorator to cache the results of a function.
6 6
7 Examples: 7 Examples:
8 1. Decorate a function: 8 1. Decorate a function:
9 @cache_decorator.Cached() 9 @cache_decorator.Cached()
10 def Test(a): 10 def Test(a):
(...skipping 21 matching lines...) Expand all
32 32
33 d2 = Downloader('http://url', 5) 33 d2 = Downloader('http://url', 5)
34 d2.Download('path') # Returned the cached downloaded data. 34 d2.Download('path') # Returned the cached downloaded data.
35 """ 35 """
36 36
37 import cStringIO 37 import cStringIO
38 import functools 38 import functools
39 import hashlib 39 import hashlib
40 import inspect 40 import inspect
41 import logging 41 import logging
42 import os
42 import pickle 43 import pickle
44 import threading
43 import zlib 45 import zlib
44 46
45 from google.appengine.api import memcache 47 from google.appengine.api import memcache
46 48
49 _DEFAULT_LOCAL_CACHE_DIR = os.path.join(os.path.expanduser('~'), '.cache')
Martin Barbella 2016/10/26 23:21:20 This shouldn't use such a generic name. This will
wrengr 2016/10/27 16:36:47 Seconded.
Sharu Jiang 2016/10/27 21:59:05 Done. Use .culprit_finder/local_cache since it's s
50
47 51
48 class Cacher(object): 52 class Cacher(object):
wrengr 2016/10/27 16:36:47 Using "-er" names for classes is weird. Why not ju
Sharu Jiang 2016/10/27 21:59:05 I think it means 'Cacher' caches.
wrengr 2016/10/28 18:02:00 In all the communities I've programmed in, we don'
Sharu Jiang 2016/11/08 01:17:12 This make senses, added a todo.
49 """An interface to cache and retrieve data. 53 """An interface to cache and retrieve data.
50 54
51 Subclasses should implement the Get/Set functions. 55 Subclasses should implement the Get/Set functions.
52 TODO: Add a Delete function (default to no-op) if needed later. 56 TODO: Add a Delete function (default to no-op) if needed later.
53 """ 57 """
54 def Get(self, key): 58 def Get(self, key):
55 """Returns the cached data for the given key if available. 59 """Returns the cached data for the given key if available.
56 60
57 Args: 61 Args:
58 key (str): The key to identify the cached data. 62 key (str): The key to identify the cached data.
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 num += 1 130 num += 1
127 131
128 all_data[key] = _CachedItemMetaData(num) 132 all_data[key] = _CachedItemMetaData(num)
129 else: 133 else:
130 all_data[key] = compressed_data 134 all_data[key] = compressed_data
131 135
132 keys_not_set = memcache.set_multi(all_data, time=expire_time) 136 keys_not_set = memcache.set_multi(all_data, time=expire_time)
133 return len(keys_not_set) == 0 137 return len(keys_not_set) == 0
134 138
135 139
140 class LocalCacher(object):
Martin Barbella 2016/10/26 23:21:20 Solely for the sake of consistency, it seems like
Sharu Jiang 2016/10/27 21:59:05 Oops, it should.
141 """Cacher that uses local files to cache data."""
142
143 lock = threading.Lock()
144
145 def __init__(self, cache_dir=_DEFAULT_LOCAL_CACHE_DIR):
146 self.cache_dir = cache_dir
147 if not os.path.exists(cache_dir): # pragma: no cover.
148 os.mkdir(cache_dir)
149
150 def Get(self, key):
151 with LocalCacher.lock:
152 path = os.path.join(self.cache_dir, key)
153 if not os.path.exists(path):
154 return None
155
156 try:
157 with open(path) as f:
158 return pickle.loads(zlib.decompress(f.read()))
159 except Exception: # pragma: no cover.
160 logging.error('Failed load cache.')
Martin Barbella 2016/10/26 23:21:20 Could you make this error a bit more descriptive,
Sharu Jiang 2016/10/27 21:59:05 Done.
161 return None
162
163 def Set(self, key, data): # pylint: disable=W
164 with LocalCacher.lock:
165 try:
166 with open(os.path.join(self.cache_dir, key), 'wb') as f:
167 f.write(zlib.compress(pickle.dumps(data)))
168 except Exception: # pragma: no cover.
169 logging.error('Failed to cache key %s', key)
170
171
136 def _DefaultKeyGenerator(func, args, kwargs): 172 def _DefaultKeyGenerator(func, args, kwargs):
137 """Generates a key from the function and arguments passed to it. 173 """Generates a key from the function and arguments passed to it.
138 174
139 Args: 175 Args:
140 func (function): An arbitrary function. 176 func (function): An arbitrary function.
141 args (list): Positional arguments passed to ``func``. 177 args (list): Positional arguments passed to ``func``.
142 kwargs (dict): Keyword arguments passed to ``func``. 178 kwargs (dict): Keyword arguments passed to ``func``.
143 179
144 Returns: 180 Returns:
145 A string to represent a call to the given function with the given arguments. 181 A string to represent a call to the given function with the given arguments.
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 except Exception: # pragma: no cover. 255 except Exception: # pragma: no cover.
220 logging.exception( 256 logging.exception(
221 'Failed to cache data for function %s.%s, args=%s, kwargs=%s', 257 'Failed to cache data for function %s.%s, args=%s, kwargs=%s',
222 func.__module__, func.__name__, repr(args), repr(kwargs)) 258 func.__module__, func.__name__, repr(args), repr(kwargs))
223 259
224 return result 260 return result
225 261
226 return Wrapped 262 return Wrapped
227 263
228 return Decorator 264 return Decorator
OLDNEW
« no previous file with comments | « no previous file | appengine/findit/common/repo_util.py » ('j') | appengine/findit/common/repo_util.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698