diff -r 06c0a566d537 dogpile/cache/region.py --- a/dogpile/cache/region.py Fri May 24 17:24:58 2013 -0400 +++ b/dogpile/cache/region.py Fri May 31 11:29:51 2013 -0400 @@ -559,6 +559,64 @@ async_creator) as value: return value + 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) + + 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: + new_values = creator(keys_to_get) + + values_w_created = dict( + (k, self._value(v)) + for k, v in zip(keys_to_get, new_values) + ) + self.backend.set_multi(values_w_created) + + values.update(values_w_created) + return [values[k].payload for k in keys] + finally: + for mutex in mutexes: + mutex.release() + + def _value(self, value): """Return a :class:`.CachedValue` given a value.""" return CachedValue(value, {