def test_invalidate(self):
        cache = DeferredCache("test")
        cache.prefill(("foo",), 123)
        cache.invalidate(("foo",))

        with self.assertRaises(KeyError):
            cache.get(("foo",))
Beispiel #2
0
    def test_invalidate(self):
        cache = DeferredCache("test")
        cache.prefill(("foo", ), 123)
        cache.invalidate(("foo", ))

        failed = False
        try:
            cache.get(("foo", ))
        except KeyError:
            failed = True

        self.assertTrue(failed)
Beispiel #3
0
    def __get__(self, obj, owner):
        cache = DeferredCache(
            name=self.orig.__name__,
            max_entries=self.max_entries,
            keylen=self.num_args,
            tree=self.tree,
            iterable=self.iterable,
        )  # type: DeferredCache[CacheKey, Any]

        get_cache_key = self.cache_key_builder

        @functools.wraps(self.orig)
        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)

            cache_key = get_cache_key(args, kwargs)

            try:
                ret = cache.get(cache_key, callback=invalidate_callback)
            except KeyError:
                # Add our own `cache_context` to argument list if the wrapped function
                # has asked for one
                if self.add_cache_context:
                    kwargs["cache_context"] = _CacheContext.get_instance(
                        cache, cache_key
                    )

                ret = defer.maybeDeferred(preserve_fn(self.orig), obj, *args, **kwargs)
                ret = cache.set(cache_key, ret, callback=invalidate_callback)

            return make_deferred_yieldable(ret)

        wrapped = cast(_CachedFunction, _wrapped)

        if self.num_args == 1:
            wrapped.invalidate = lambda key: cache.invalidate(key[0])
            wrapped.prefill = lambda key, val: cache.prefill(key[0], val)
        else:
            wrapped.invalidate = cache.invalidate
            wrapped.invalidate_many = cache.invalidate_many
            wrapped.prefill = cache.prefill

        wrapped.invalidate_all = cache.invalidate_all
        wrapped.cache = cache
        wrapped.num_args = self.num_args

        obj.__dict__[self.orig.__name__] = wrapped

        return wrapped
Beispiel #4
0
    def __get__(self, obj, owner):
        cache = DeferredCache(
            name=self.orig.__name__,
            max_entries=self.max_entries,
            keylen=self.num_args,
            tree=self.tree,
            iterable=self.iterable,
        )  # type: DeferredCache[CacheKey, Any]

        def get_cache_key_gen(args, kwargs):
            """Given some args/kwargs return a generator that resolves into
            the cache_key.

            We loop through each arg name, looking up if its in the `kwargs`,
            otherwise using the next argument in `args`. If there are no more
            args then we try looking the arg name up in the defaults
            """
            pos = 0
            for nm in self.arg_names:
                if nm in kwargs:
                    yield kwargs[nm]
                elif pos < len(args):
                    yield args[pos]
                    pos += 1
                else:
                    yield self.arg_defaults[nm]

        # By default our cache key is a tuple, but if there is only one item
        # then don't bother wrapping in a tuple.  This is to save memory.
        if self.num_args == 1:
            nm = self.arg_names[0]

            def get_cache_key(args, kwargs):
                if nm in kwargs:
                    return kwargs[nm]
                elif len(args):
                    return args[0]
                else:
                    return self.arg_defaults[nm]

        else:

            def get_cache_key(args, kwargs):
                return tuple(get_cache_key_gen(args, kwargs))

        @functools.wraps(self.orig)
        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)

            cache_key = get_cache_key(args, kwargs)

            try:
                ret = cache.get(cache_key, callback=invalidate_callback)
            except KeyError:
                # Add our own `cache_context` to argument list if the wrapped function
                # has asked for one
                if self.add_cache_context:
                    kwargs["cache_context"] = _CacheContext.get_instance(
                        cache, cache_key)

                ret = defer.maybeDeferred(preserve_fn(self.orig), obj, *args,
                                          **kwargs)
                ret = cache.set(cache_key, ret, callback=invalidate_callback)

            return make_deferred_yieldable(ret)

        wrapped = cast(_CachedFunction, _wrapped)

        if self.num_args == 1:
            wrapped.invalidate = lambda key: cache.invalidate(key[0])
            wrapped.prefill = lambda key, val: cache.prefill(key[0], val)
        else:
            wrapped.invalidate = cache.invalidate
            wrapped.invalidate_all = cache.invalidate_all
            wrapped.invalidate_many = cache.invalidate_many
            wrapped.prefill = cache.prefill

        wrapped.invalidate_all = cache.invalidate_all
        wrapped.cache = cache
        wrapped.num_args = self.num_args

        obj.__dict__[self.orig.__name__] = wrapped

        return wrapped