def wrapped(*args, **kwargs): arg_dict = inspect.getcallargs(self.orig, obj, *args, **kwargs) keyargs = [arg_dict[arg_nm] for arg_nm in self.arg_names] list_args = arg_dict[self.list_name] # cached is a dict arg -> deferred, where deferred results in a # 2-tuple (`arg`, `result`) cached = {} missing = [] for arg in list_args: key = list(keyargs) key[self.list_pos] = arg try: res = self.cache.get(tuple(key)).observe() res.addCallback(lambda r, arg: (arg, r), arg) cached[arg] = res except KeyError: missing.append(arg) if missing: sequence = self.cache.sequence args_to_call = dict(arg_dict) args_to_call[self.list_name] = missing ret_d = defer.maybeDeferred( preserve_context_over_fn, self.function_to_call, **args_to_call ) ret_d = ObservableDeferred(ret_d) # We need to create deferreds for each arg in the list so that # we can insert the new deferred into the cache. for arg in missing: with PreserveLoggingContext(): observer = ret_d.observe() observer.addCallback(lambda r, arg: r.get(arg, None), arg) observer = ObservableDeferred(observer) key = list(keyargs) key[self.list_pos] = arg self.cache.update(sequence, tuple(key), observer) def invalidate(f, key): self.cache.invalidate(key) return f observer.addErrback(invalidate, tuple(key)) res = observer.observe() res.addCallback(lambda r, arg: (arg, r), arg) cached[arg] = res return preserve_context_over_deferred(defer.gatherResults( cached.values(), consumeErrors=True, ).addErrback(unwrapFirstError).addCallback(lambda res: dict(res)))
def wrapped(*args, **kwargs): arg_dict = inspect.getcallargs(self.orig, obj, *args, **kwargs) keyargs = [arg_dict[arg_nm] for arg_nm in self.arg_names] list_args = arg_dict[self.list_name] # cached is a dict arg -> deferred, where deferred results in a # 2-tuple (`arg`, `result`) cached = {} missing = [] for arg in list_args: key = list(keyargs) key[self.list_pos] = arg try: res = self.cache.get(tuple(key)).observe() res.addCallback(lambda r, arg: (arg, r), arg) cached[arg] = res except KeyError: missing.append(arg) if missing: sequence = self.cache.sequence args_to_call = dict(arg_dict) args_to_call[self.list_name] = missing ret_d = defer.maybeDeferred( preserve_context_over_fn, self.function_to_call, **args_to_call ) ret_d = ObservableDeferred(ret_d) # We need to create deferreds for each arg in the list so that # we can insert the new deferred into the cache. for arg in missing: with PreserveLoggingContext(): observer = ret_d.observe() observer.addCallback(lambda r, arg: r.get(arg, None), arg) observer = ObservableDeferred(observer) key = list(keyargs) key[self.list_pos] = arg self.cache.update(sequence, tuple(key), observer) def invalidate(f, key): self.cache.invalidate(key) return f observer.addErrback(invalidate, tuple(key)) res = observer.observe() res.addCallback(lambda r, arg: (arg, r), arg) cached[arg] = res return preserve_context_over_deferred(defer.gatherResults( cached.values(), consumeErrors=True, ).addErrback(unwrapFirstError).addCallback(lambda res: dict(res)))
def wrapped(*args, **kwargs): # If we're passed a cache_context then we'll want to call its invalidate() # whenever we are invalidated invalidate_callback = kwargs.pop("on_invalidate", None) arg_dict = inspect.getcallargs(self.orig, obj, *args, **kwargs) keyargs = [arg_dict[arg_nm] for arg_nm in self.arg_names] list_args = arg_dict[self.list_name] # cached is a dict arg -> deferred, where deferred results in a # 2-tuple (`arg`, `result`) results = {} cached_defers = {} missing = [] # If the cache takes a single arg then that is used as the key, # otherwise a tuple is used. if num_args == 1: def cache_get(arg): return cache.get(arg, callback=invalidate_callback) else: key = list(keyargs) def cache_get(arg): key[self.list_pos] = arg return cache.get(tuple(key), callback=invalidate_callback) for arg in list_args: try: res = cache_get(arg) if not isinstance(res, ObservableDeferred): results[arg] = res elif not res.has_succeeded(): res = res.observe() res.addCallback(lambda r, arg: (arg, r), arg) cached_defers[arg] = res else: results[arg] = res.get_result() except KeyError: missing.append(arg) if missing: args_to_call = dict(arg_dict) args_to_call[self.list_name] = missing ret_d = defer.maybeDeferred( logcontext.preserve_fn(self.function_to_call), **args_to_call) ret_d = ObservableDeferred(ret_d) # We need to create deferreds for each arg in the list so that # we can insert the new deferred into the cache. for arg in missing: observer = ret_d.observe() observer.addCallback(lambda r, arg: r.get(arg, None), arg) observer = ObservableDeferred(observer) if num_args == 1: cache.set(arg, observer, callback=invalidate_callback) def invalidate(f, key): cache.invalidate(key) return f observer.addErrback(invalidate, arg) else: key = list(keyargs) key[self.list_pos] = arg cache.set(tuple(key), observer, callback=invalidate_callback) def invalidate(f, key): cache.invalidate(key) return f observer.addErrback(invalidate, tuple(key)) res = observer.observe() res.addCallback(lambda r, arg: (arg, r), arg) cached_defers[arg] = res if cached_defers: def update_results_dict(res): results.update(res) return results return logcontext.make_deferred_yieldable( defer.gatherResults( list(cached_defers.values()), consumeErrors=True, ).addCallback(update_results_dict).addErrback( unwrapFirstError)) else: return results
def wrapped(*args, **kwargs): # If we're passed a cache_context then we'll want to call its invalidate() # whenever we are invalidated invalidate_callback = kwargs.pop("on_invalidate", None) arg_dict = inspect.getcallargs(self.orig, obj, *args, **kwargs) keyargs = [arg_dict[arg_nm] for arg_nm in self.arg_names] list_args = arg_dict[self.list_name] # cached is a dict arg -> deferred, where deferred results in a # 2-tuple (`arg`, `result`) results = {} cached_defers = {} missing = [] for arg in list_args: key = list(keyargs) key[self.list_pos] = arg try: res = cache.get(tuple(key), callback=invalidate_callback) if not res.has_succeeded(): res = res.observe() res.addCallback(lambda r, arg: (arg, r), arg) cached_defers[arg] = res else: results[arg] = res.get_result() except KeyError: missing.append(arg) if missing: sequence = cache.sequence args_to_call = dict(arg_dict) args_to_call[self.list_name] = missing ret_d = defer.maybeDeferred( preserve_context_over_fn, self.function_to_call, **args_to_call ) ret_d = ObservableDeferred(ret_d) # We need to create deferreds for each arg in the list so that # we can insert the new deferred into the cache. for arg in missing: with PreserveLoggingContext(): observer = ret_d.observe() observer.addCallback(lambda r, arg: r.get(arg, None), arg) observer = ObservableDeferred(observer) key = list(keyargs) key[self.list_pos] = arg cache.update( sequence, tuple(key), observer, callback=invalidate_callback ) def invalidate(f, key): cache.invalidate(key) return f observer.addErrback(invalidate, tuple(key)) res = observer.observe() res.addCallback(lambda r, arg: (arg, r), arg) cached_defers[arg] = res if cached_defers: def update_results_dict(res): results.update(res) return results return preserve_context_over_deferred(defer.gatherResults( cached_defers.values(), consumeErrors=True, ).addCallback(update_results_dict).addErrback( unwrapFirstError )) else: return results