Skip to content

Instantly share code, notes, and snippets.

@lxyu
Created June 5, 2013 10:13
Show Gist options
  • Save lxyu/5712915 to your computer and use it in GitHub Desktop.
Save lxyu/5712915 to your computer and use it in GitHub Desktop.
get or create multi for dogpile.cache based on @zzzeek's 33.patch
def get_or_create_multi(self, keys, creator, expiration_time=None,
should_cache_fn=None):
def get_value():
value = values.get(key, NO_VALUE)
if value is NO_VALUE or \
value.metadata['v'] != value_version or \
(self._invalidated and
value.metadata["ct"] < self._invalidated):
invalidated.append(key)
return invalid, expiration_time
else:
return value.payload, value.metadata["ct"]
def gen_value():
raise NotImplementedError()
def async_creator(mutex):
mutexes.append(mutex)
# sort keys to prevent deadlock
keys = sorted(keys)
if self.key_mangler:
keys = [self.key_mangler(k) for k in keys]
if expiration_time is None:
expiration_time = self.expiration_time
invalidated = []
mutexes = []
keys_to_get = []
invalid = object()
values = self.backend.get_multi(keys)
for key in keys:
with Lock(self._mutex(key),
gen_value,
get_value,
expiration_time,
async_creator) as value:
if value is invalid:
keys_to_get.append(key)
try:
# create new keys if needed
if keys_to_get:
created_values = creator(keys_to_get)
new_values = dict(
(k, self._value(v))
for k, v in created_values.items()
)
values.update(new_values)
self.backend.set_multi(dict(
(k, new_values[k])
for k, v in created_values.items()
if not should_cache_fn or should_cache_fn(v)
))
return dict((k, v.payload) for k, v in values.items())
finally:
for mutex in mutexes:
mutex.release()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment