OLD | NEW |
(Empty) | |
| 1 import operator |
| 2 from ..util.compat import py3k |
| 3 |
| 4 |
| 5 class NoValue(object): |
| 6 """Describe a missing cache value. |
| 7 |
| 8 The :attr:`.NO_VALUE` module global |
| 9 should be used. |
| 10 |
| 11 """ |
| 12 @property |
| 13 def payload(self): |
| 14 return self |
| 15 |
| 16 if py3k: |
| 17 def __bool__(self): # pragma NO COVERAGE |
| 18 return False |
| 19 else: |
| 20 def __nonzero__(self): # pragma NO COVERAGE |
| 21 return False |
| 22 |
| 23 NO_VALUE = NoValue() |
| 24 """Value returned from ``get()`` that describes |
| 25 a key not present.""" |
| 26 |
| 27 |
| 28 class CachedValue(tuple): |
| 29 """Represent a value stored in the cache. |
| 30 |
| 31 :class:`.CachedValue` is a two-tuple of |
| 32 ``(payload, metadata)``, where ``metadata`` |
| 33 is dogpile.cache's tracking information ( |
| 34 currently the creation time). The metadata |
| 35 and tuple structure is pickleable, if |
| 36 the backend requires serialization. |
| 37 |
| 38 """ |
| 39 payload = property(operator.itemgetter(0)) |
| 40 """Named accessor for the payload.""" |
| 41 |
| 42 metadata = property(operator.itemgetter(1)) |
| 43 """Named accessor for the dogpile.cache metadata dictionary.""" |
| 44 |
| 45 def __new__(cls, payload, metadata): |
| 46 return tuple.__new__(cls, (payload, metadata)) |
| 47 |
| 48 def __reduce__(self): |
| 49 return CachedValue, (self.payload, self.metadata) |
| 50 |
| 51 |
| 52 class CacheBackend(object): |
| 53 """Base class for backend implementations.""" |
| 54 |
| 55 key_mangler = None |
| 56 """Key mangling function. |
| 57 |
| 58 May be None, or otherwise declared |
| 59 as an ordinary instance method. |
| 60 |
| 61 """ |
| 62 |
| 63 def __init__(self, arguments): # pragma NO COVERAGE |
| 64 """Construct a new :class:`.CacheBackend`. |
| 65 |
| 66 Subclasses should override this to |
| 67 handle the given arguments. |
| 68 |
| 69 :param arguments: The ``arguments`` parameter |
| 70 passed to :func:`.make_registry`. |
| 71 |
| 72 """ |
| 73 raise NotImplementedError() |
| 74 |
| 75 @classmethod |
| 76 def from_config_dict(cls, config_dict, prefix): |
| 77 prefix_len = len(prefix) |
| 78 return cls( |
| 79 dict( |
| 80 (key[prefix_len:], config_dict[key]) |
| 81 for key in config_dict |
| 82 if key.startswith(prefix) |
| 83 ) |
| 84 ) |
| 85 |
| 86 def has_lock_timeout(self): |
| 87 return False |
| 88 |
| 89 def get_mutex(self, key): |
| 90 """Return an optional mutexing object for the given key. |
| 91 |
| 92 This object need only provide an ``acquire()`` |
| 93 and ``release()`` method. |
| 94 |
| 95 May return ``None``, in which case the dogpile |
| 96 lock will use a regular ``threading.Lock`` |
| 97 object to mutex concurrent threads for |
| 98 value creation. The default implementation |
| 99 returns ``None``. |
| 100 |
| 101 Different backends may want to provide various |
| 102 kinds of "mutex" objects, such as those which |
| 103 link to lock files, distributed mutexes, |
| 104 memcached semaphores, etc. Whatever |
| 105 kind of system is best suited for the scope |
| 106 and behavior of the caching backend. |
| 107 |
| 108 A mutex that takes the key into account will |
| 109 allow multiple regenerate operations across |
| 110 keys to proceed simultaneously, while a mutex |
| 111 that does not will serialize regenerate operations |
| 112 to just one at a time across all keys in the region. |
| 113 The latter approach, or a variant that involves |
| 114 a modulus of the given key's hash value, |
| 115 can be used as a means of throttling the total |
| 116 number of value recreation operations that may |
| 117 proceed at one time. |
| 118 |
| 119 """ |
| 120 return None |
| 121 |
| 122 def get(self, key): # pragma NO COVERAGE |
| 123 """Retrieve a value from the cache. |
| 124 |
| 125 The returned value should be an instance of |
| 126 :class:`.CachedValue`, or ``NO_VALUE`` if |
| 127 not present. |
| 128 |
| 129 """ |
| 130 raise NotImplementedError() |
| 131 |
| 132 def get_multi(self, keys): # pragma NO COVERAGE |
| 133 """Retrieve multiple values from the cache. |
| 134 |
| 135 The returned value should be a list, corresponding |
| 136 to the list of keys given. |
| 137 |
| 138 .. versionadded:: 0.5.0 |
| 139 |
| 140 """ |
| 141 raise NotImplementedError() |
| 142 |
| 143 def set(self, key, value): # pragma NO COVERAGE |
| 144 """Set a value in the cache. |
| 145 |
| 146 The key will be whatever was passed |
| 147 to the registry, processed by the |
| 148 "key mangling" function, if any. |
| 149 The value will always be an instance |
| 150 of :class:`.CachedValue`. |
| 151 |
| 152 """ |
| 153 raise NotImplementedError() |
| 154 |
| 155 def set_multi(self, mapping): # pragma NO COVERAGE |
| 156 """Set multiple values in the cache. |
| 157 |
| 158 ``mapping`` is a dict in which |
| 159 the key will be whatever was passed |
| 160 to the registry, processed by the |
| 161 "key mangling" function, if any. |
| 162 The value will always be an instance |
| 163 of :class:`.CachedValue`. |
| 164 |
| 165 When implementing a new :class:`.CacheBackend` or cutomizing via |
| 166 :class:`.ProxyBackend`, be aware that when this method is invoked by |
| 167 :meth:`.Region.get_or_create_multi`, the ``mapping`` values are the |
| 168 same ones returned to the upstream caller. If the subclass alters the |
| 169 values in any way, it must not do so 'in-place' on the ``mapping`` dict |
| 170 -- that will have the undesirable effect of modifying the returned |
| 171 values as well. |
| 172 |
| 173 .. versionadded:: 0.5.0 |
| 174 |
| 175 """ |
| 176 raise NotImplementedError() |
| 177 |
| 178 def delete(self, key): # pragma NO COVERAGE |
| 179 """Delete a value from the cache. |
| 180 |
| 181 The key will be whatever was passed |
| 182 to the registry, processed by the |
| 183 "key mangling" function, if any. |
| 184 |
| 185 The behavior here should be idempotent, |
| 186 that is, can be called any number of times |
| 187 regardless of whether or not the |
| 188 key exists. |
| 189 """ |
| 190 raise NotImplementedError() |
| 191 |
| 192 def delete_multi(self, keys): # pragma NO COVERAGE |
| 193 """Delete multiple values from the cache. |
| 194 |
| 195 The key will be whatever was passed |
| 196 to the registry, processed by the |
| 197 "key mangling" function, if any. |
| 198 |
| 199 The behavior here should be idempotent, |
| 200 that is, can be called any number of times |
| 201 regardless of whether or not the |
| 202 key exists. |
| 203 |
| 204 .. versionadded:: 0.5.0 |
| 205 |
| 206 """ |
| 207 raise NotImplementedError() |
OLD | NEW |