public async Task SetAndGetTestCacheKeyEquality()
        {
            var store = new ImmutableInMemoryCacheStore();

            var resp = new HttpResponseMessage();

            var cacheKey = new CacheKey("key", null);
            await store.SetAsync(cacheKey, new CacheEntry(resp));

            var fromCache = await store.GetAsync(new CacheKey("key", null));

            // check
            Assert.AreEqual(resp, fromCache.HttpResponse);
        }
        public async Task SetAndGetExisting()
        {
            var store = new ImmutableInMemoryCacheStore();

            var resp = new HttpResponseMessage();
            var cacheKey = new CacheKey("key", null);
            await store.SetAsync(cacheKey, new CacheEntry(resp));

            var respNew = new HttpResponseMessage();

            // overwrite
            await store.SetAsync(cacheKey, new CacheEntry(respNew));

            var fromCache = await store.GetAsync(cacheKey);

            // check
            Assert.AreEqual(respNew, fromCache.HttpResponse);
        }
        public async Task SetAndGetMultiple()
        {
            var store = new ImmutableInMemoryCacheStore();

            var resp = new HttpResponseMessage();
            var resp2 = new HttpResponseMessage();

            var cacheKey = new CacheKey("key", null);
            var cacheKey2 = new CacheKey("key2", null);

            await store.SetAsync(cacheKey, new CacheEntry(resp));
            await store.SetAsync(cacheKey2, new CacheEntry(resp2));

            var fromCache = await store.GetAsync(cacheKey);
            var fromCache2 = await store.GetAsync(cacheKey2);

            // check
            Assert.AreEqual(resp, fromCache.HttpResponse);
            // check
            Assert.AreEqual(resp2, fromCache2.HttpResponse);
        }
        public async Task GetNonExisting()
        {
            var store = new ImmutableInMemoryCacheStore();

            var resp = new HttpResponseMessage();
            var cacheKey = new CacheKey("key", null);

            await store.SetAsync(cacheKey, new CacheEntry(resp));

            var fromCache = await store.GetAsync("key2");

            // check
            Assert.AreEqual(default(CacheEntry), fromCache);
         

        }
        public async Task GetNonExistingFromEmpty()
        {
            var store = new ImmutableInMemoryCacheStore();
            var cacheKey = new CacheKey("key", null);
            var fromCache = await store.GetAsync(cacheKey);

            // check
            Assert.AreEqual(default(CacheEntry), fromCache);
        }
        public Task SetAsync(CacheKey key, CacheEntry value)
        {
            do
            {

                var oldCache = _cache;
                IImmutableDictionary<CacheKey, CacheEntry> newCache;

                if (oldCache.ContainsKey(key))
                {
                    // overwrite.  Dic is immutable: no lock needed.
                    newCache = oldCache.SetItem(key, value);
                }
                else
                {
                    // Add the value to cache dictionary.  Dic is immutable: no lock needed.
                    newCache = oldCache.Add(key, value);
                }

                // newCache = new cache dic, containing value.  Check.

                // Interlocked.CompareExchange(ref _cache, newCache, oldCache):
                //
                // => if _cache is the same as oldcache, then  replace
                // _cache by newCache.  This is an effective check: if _cache is no longer the
                // same as oldCache, another thread has made a change to _cache.  If that's the
                // case, we need to do the add again, as we'll want to make sure we always work
                // on the latest version - we don't want to loose changes to the cache.
                //
                // Call checks for reference equality, not an overridden Equals => we need
                // this reference check, new instance = different reference.
                //
                // CompareExchange always returns the value in "location", eg the first
                // parameter, BEFORE the exchange.  So, if we check that value (_cache before
                // exchange) against the oldCache and if these are the same, add was succesful,
                // and thanks to the CompareExchange call, _cache is now set to newCache

                // compares oldCache with newCache - if these are now the s
                if (oldCache == Interlocked.CompareExchange(ref _cache, newCache, oldCache))
                {
                    // we can get out of the loop

                    return Task.FromResult(true);
                }

                // CompareExchange failed => another thread has made a change to _cache.
                // We need to do the add again, as we'll want to make sure we always work
                // on the latest version - we don't want to loose changes to the cache.

            } while (true);
        }
        public Task RemoveAsync(CacheKey key)
        {
            do
            {

                var oldCache = _cache;
                IImmutableDictionary<CacheKey, CacheEntry> newCache;

                if (oldCache.ContainsKey(key))
                {
                    // Remove.  Dic is immutable: no lock needed.
                    newCache = oldCache.Remove(key);
                }
                else
                {
                    newCache = oldCache;
                }

                // compares oldCache with newCache - if these are now the s
                if (oldCache == Interlocked.CompareExchange(ref _cache, newCache, oldCache))
                {
                    // we can get out of the loop

                    return Task.FromResult(true);
                }

                // CompareExchange failed => another thread has made a change to _cache.
                // We need to do the add again, as we'll want to make sure we always work
                // on the latest version - we don't want to loose changes to the cache.

            } while (true);
        }
 public Task<CacheEntry> GetAsync(CacheKey key)
 {
     CacheEntry value;
     if (_cache.TryGetValue(key, out value))
     {
         return Task.FromResult((CacheEntry)value);
     }
     else
     {
         return Task.FromResult(default(CacheEntry));
     }
 }
Beispiel #9
0
        private Task<HttpResponseMessage> HandleSendAndContinuationForPutPatch(CacheKey cacheKey, HttpRequestMessage request,
           System.Threading.CancellationToken cancellationToken)
        {
            return base.SendAsync(request, cancellationToken)
                   .ContinueWith(
                    task =>
                    {

                        var serverResponse = task.Result;

                        if (serverResponse.IsSuccessStatusCode)
                        {

                            // ensure no NULL dates
                            if (serverResponse.Headers.Date == null)
                            {
                                serverResponse.Headers.Date = DateTimeOffset.UtcNow;
                            }

                            // should we clear?

                            if ((_enableClearRelatedResourceRepresentationsAfterPut && request.Method == HttpMethod.Put)
                                ||
                                (_enableClearRelatedResourceRepresentationsAfterPatch && request.Method.Method.ToLower() == "patch"))
                            {
                                // clear related resources
                                //
                                // - remove resource with cachekey.  This must be done, as there's no
                                // guarantee the new response is cacheable.
                                //
                                // - look for resources in cache that start with
                                // the cachekey + "?" for querystring.

                                _cacheStore.RemoveAsync(cacheKey);
                                _cacheStore.RemoveRangeAsync(cacheKey.PrimaryKey + "?");
                            }

                            // check the response: is this response allowed to be cached?
                            bool isCacheable = HttpResponseHelpers.CanBeCached(serverResponse);

                            if (isCacheable)
                            {
                                // add the response to cache
                                _cacheStore.SetAsync(cacheKey, new CacheEntry(serverResponse));
                            }

                            // what about vary by headers (=> key should take this into account)?

                        }

                        return serverResponse;

                    });
        }
Beispiel #10
0
        private Task<HttpResponseMessage> HandleSendAndContinuation(CacheKey cacheKey, HttpRequestMessage request,
         System.Threading.CancellationToken cancellationToken, bool mustRevalidate)
        {
            return base.SendAsync(request, cancellationToken)
                   .ContinueWith(
                    task =>
                    {

                        var serverResponse = task.Result;

                        // if we had to revalidate & got a 304 returned, that means
                        // we can get the response message from cache.
                        if (mustRevalidate && serverResponse.StatusCode == HttpStatusCode.NotModified)
                        {
                            var cacheEntry = _cacheStore.GetAsync(cacheKey).Result;
                            var responseFromCacheEntry = cacheEntry.HttpResponse;
                            responseFromCacheEntry.RequestMessage = request;

                            return responseFromCacheEntry;
                        }

                        if (serverResponse.IsSuccessStatusCode)
                        {

                            // ensure no NULL dates
                            if (serverResponse.Headers.Date == null)
                            {
                                serverResponse.Headers.Date = DateTimeOffset.UtcNow;
                            }

                            // check the response: is this response allowed to be cached?
                            bool isCacheable = HttpResponseHelpers.CanBeCached(serverResponse);

                            if (isCacheable)
                            {
                                // add the response to cache
                                _cacheStore.SetAsync(cacheKey, new CacheEntry(serverResponse));
                            }

                            // what about vary by headers (=> key should take this into account)?

                        }

                        return serverResponse;
                    });
        }