コード例 #1
0
        public async Task ValidateNegativeNotAwaitedScenario()
        {
            AsyncCacheNonBlocking <string, string> asyncCache = new AsyncCacheNonBlocking <string, string>();
            Task task1 = asyncCache.GetAsync(
                "test",
                async(_) =>
            {
                await Task.Delay(TimeSpan.FromMilliseconds(5));
                throw new NotFoundException("testNotFoundException");
            },
                (_) => false);

            try
            {
                await asyncCache.GetAsync(
                    "test",
                    (_) => throw new BadRequestException("testBadRequestException"),
                    (_) => false);

                Assert.Fail("Should have thrown a NotFoundException");
            }
            catch (NotFoundException)
            {
            }

            await task1;
        }
コード例 #2
0
        public GatewayAddressCache(
            Uri serviceEndpoint,
            Protocol protocol,
            ICosmosAuthorizationTokenProvider tokenProvider,
            IServiceConfigurationReader serviceConfigReader,
            CosmosHttpClient httpClient,
            long suboptimalPartitionForceRefreshIntervalInSeconds = 600,
            bool enableTcpConnectionEndpointRediscovery           = false)
        {
            this.addressEndpoint                        = new Uri(serviceEndpoint + "/" + Paths.AddressPathSegment);
            this.protocol                               = protocol;
            this.tokenProvider                          = tokenProvider;
            this.serviceEndpoint                        = serviceEndpoint;
            this.serviceConfigReader                    = serviceConfigReader;
            this.serverPartitionAddressCache            = new AsyncCacheNonBlocking <PartitionKeyRangeIdentity, PartitionAddressInformation>();
            this.suboptimalServerPartitionTimestamps    = new ConcurrentDictionary <PartitionKeyRangeIdentity, DateTime>();
            this.serverPartitionAddressToPkRangeIdMap   = new ConcurrentDictionary <ServerKey, HashSet <PartitionKeyRangeIdentity> >();
            this.suboptimalMasterPartitionTimestamp     = DateTime.MaxValue;
            this.enableTcpConnectionEndpointRediscovery = enableTcpConnectionEndpointRediscovery;

            this.suboptimalPartitionForceRefreshIntervalInSeconds = suboptimalPartitionForceRefreshIntervalInSeconds;

            this.httpClient = httpClient;

            this.protocolFilter =
                string.Format(CultureInfo.InvariantCulture,
                              GatewayAddressCache.protocolFilterFormat,
                              Constants.Properties.Protocol,
                              GatewayAddressCache.ProtocolString(this.protocol));
        }
コード例 #3
0
        public async Task ValidateMultipleBackgroundRefreshesScenario()
        {
            AsyncCacheNonBlocking <string, string> asyncCache = new AsyncCacheNonBlocking <string, string>();

            string expectedValue = "ResponseValue";
            string response      = await asyncCache.GetAsync(
                "test",
                async (_) =>
            {
                await Task.Delay(TimeSpan.FromMilliseconds(5));
                return(expectedValue);
            },
                (_) => false);

            Assert.AreEqual(expectedValue, response);

            for (int i = 0; i < 10; i++)
            {
                string forceRefreshResponse = await asyncCache.GetAsync(
                    key : "test",
                    singleValueInitFunc : async(_) =>
                {
                    await Task.Delay(TimeSpan.FromMilliseconds(5));
                    return(expectedValue + i);
                },
                    forceRefresh : (_) => true);

                Assert.AreEqual(expectedValue + i, forceRefreshResponse);
            }
        }
コード例 #4
0
        public async Task ValidateCacheValueIsRemovedAfterException()
        {
            AsyncCacheNonBlocking <string, string> asyncCache = new AsyncCacheNonBlocking <string, string>();
            string result = await asyncCache.GetAsync(
                "test",
                () => Task.FromResult("test2"),
                false,
                null);

            Assert.AreEqual("test2", result);

            string cachedResults = await asyncCache.GetAsync(
                "test",
                () => throw new Exception("should not refresh"),
                false,
                null);

            Assert.AreEqual("test2", cachedResults);

            // Simulate a slow connection on a refresh operation. The async call will
            // be blocked to verify a read can still be done using the stale value.
            bool delayException = true;
            Task task           = Task.Run(async() =>
            {
                try
                {
                    await asyncCache.GetAsync(
                        "test",
                        async() =>
                    {
                        while (delayException)
                        {
                            await Task.Delay(TimeSpan.FromMilliseconds(1));
                        }

                        throw new NotFoundException("testNotFoundException");
                    },
                        true,
                        null);
                    Assert.Fail();
                }
                catch (NotFoundException nfe)
                {
                    Assert.IsTrue(nfe.Message.Contains("testNotFoundException"), $"NotFoundException message is missing: {nfe.Message}");
                }
            });

            cachedResults = await asyncCache.GetAsync(
                "test",
                () => throw new Exception("should not refresh"),
                false,
                null);

            Assert.AreEqual("test2", cachedResults);

            delayException = false;

            await task;
        }
コード例 #5
0
 public async Task ValidateNegativeScenario(bool forceRefresh)
 {
     AsyncCacheNonBlocking <string, string> asyncCache = new AsyncCacheNonBlocking <string, string>();
     await asyncCache.GetAsync(
         "test",
         () => throw new NotFoundException("testNotFoundException"),
         forceRefresh,
         null);
 }
コード例 #6
0
 public PartitionKeyRangeCache(
     ICosmosAuthorizationTokenProvider authorizationTokenProvider,
     IStoreModel storeModel,
     CollectionCache collectionCache)
 {
     this.routingMapCache = new AsyncCacheNonBlocking <string, CollectionRoutingMap>(
         keyEqualityComparer: StringComparer.Ordinal);
     this.authorizationTokenProvider = authorizationTokenProvider;
     this.storeModel      = storeModel;
     this.collectionCache = collectionCache;
 }
コード例 #7
0
 public async Task ValidateNegativeScenario(bool forceRefresh)
 {
     AsyncCacheNonBlocking <string, string> asyncCache = new AsyncCacheNonBlocking <string, string>();
     await asyncCache.GetAsync(
         "test",
         async (_) =>
     {
         await Task.Delay(TimeSpan.FromMilliseconds(5));
         throw new NotFoundException("testNotFoundException");
     },
         (_) => forceRefresh);
 }
コード例 #8
0
        public async Task ValidateAsyncCacheNonBlocking()
        {
            AsyncCacheNonBlocking <string, string> asyncCache = new AsyncCacheNonBlocking <string, string>();
            string result = await asyncCache.GetAsync(
                "test",
                () => Task.FromResult("test2"),
                false,
                (x, y) => throw new Exception("Should not be called since there is no refresh"));

            string cachedResults = await asyncCache.GetAsync(
                "test",
                () => throw new Exception("should not refresh"),
                false,
                (x, y) => throw new Exception("Should not be called since there is no refresh"));

            string        oldValue   = null;
            string        newValue   = null;
            Task <string> updateTask = asyncCache.GetAsync(
                key: "test",
                singleValueInitFunc: async() =>
            {
                await Task.Delay(TimeSpan.FromSeconds(1));
                return("Test3");
            },
                forceRefresh: true,
                callBackOnForceRefresh: (x, y) => { oldValue = x; newValue = y; });

            Stopwatch concurrentOperationStopwatch = Stopwatch.StartNew();
            string    concurrentUpdateTask         = await asyncCache.GetAsync(
                "test",
                () => throw new Exception("should not refresh"),
                false,
                (x, y) => throw new Exception("Should not be called since there is no refresh"));

            Assert.AreEqual("test2", result);
            concurrentOperationStopwatch.Stop();

            Assert.IsTrue(concurrentOperationStopwatch.Elapsed.TotalMilliseconds < 500);

            result = await updateTask;
            Assert.AreEqual("Test3", result);
            Assert.AreEqual(oldValue, "test2", "The call back was not done.");
            Assert.AreEqual(newValue, "Test3", "The call back was not done.");
        }
コード例 #9
0
        public async Task ValidateConcurrentCreateWithFailureAsyncCacheNonBlocking()
        {
            AsyncCacheNonBlocking <string, string> asyncCache = new AsyncCacheNonBlocking <string, string>();
            int totalLazyCalls = 0;

            Random      random = new Random();
            List <Task> tasks  = new List <Task>();

            for (int i = 0; i < 50; i++)
            {
                // Insert a random delay to simulate multiple request coming at different times
                await Task.Delay(random.Next(0, 5));

                tasks.Add(Task.Run(async() =>
                {
                    try
                    {
                        await asyncCache.GetAsync(
                            "key",
                            async() =>
                        {
                            Interlocked.Increment(ref totalLazyCalls);
                            await Task.Delay(random.Next(0, 3));
                            throw new NotFoundException("test");
                        },
                            forceRefresh: false,
                            (x, y) => throw new Exception("Should not be called since there is no refresh"));
                        Assert.Fail();
                    }
                    catch (DocumentClientException dce)
                    {
                        Assert.AreEqual(dce.StatusCode, HttpStatusCode.NotFound);
                    }
                }));
            }

            await Task.WhenAll(tasks);

            Assert.IsTrue(totalLazyCalls > 1, $"Expected multiple async refresh call. TotalCount {totalLazyCalls}");
        }
コード例 #10
0
        public async Task ValidateConcurrentCreateAsyncCacheNonBlocking()
        {
            AsyncCacheNonBlocking <string, string> asyncCache = new AsyncCacheNonBlocking <string, string>();
            int totalLazyCalls = 0;

            List <Task> tasks = new List <Task>();

            for (int i = 0; i < 500; i++)
            {
                tasks.Add(Task.Run(() => asyncCache.GetAsync(
                                       key: "key",
                                       singleValueInitFunc: (_) =>
                {
                    Interlocked.Increment(ref totalLazyCalls);
                    return(Task.FromResult("Test"));
                },
                                       forceRefresh: (_) => false)));
            }

            await Task.WhenAll(tasks);

            Assert.AreEqual(1, totalLazyCalls);
        }
コード例 #11
0
        public async Task ValidateConcurrentCreateAsyncCacheNonBlocking()
        {
            AsyncCacheNonBlocking <string, string> asyncCache = new AsyncCacheNonBlocking <string, string>();
            int totalLazyCalls = 0;

            List <Task> tasks = new List <Task>();

            for (int i = 0; i < 500; i++)
            {
                tasks.Add(Task.Run(() => asyncCache.GetAsync(
                                       "key",
                                       () =>
                {
                    Interlocked.Increment(ref totalLazyCalls);
                    return(Task.FromResult("Test"));
                },
                                       forceRefresh: false,
                                       (x, y) => throw new Exception("Should not be called since there is no refresh"))));
            }

            await Task.WhenAll(tasks);

            Assert.AreEqual(1, totalLazyCalls);
        }
コード例 #12
0
        public async Task ValidateExceptionScenariosCacheNonBlocking()
        {
            AsyncCacheNonBlocking <string, string> asyncCache = new AsyncCacheNonBlocking <string, string>();
            int totalLazyCalls = 0;

            try
            {
                await asyncCache.GetAsync(
                    "key",
                    async() =>
                {
                    // Use a dummy await to make it simulate a real async network call
                    await Task.CompletedTask;
                    Interlocked.Increment(ref totalLazyCalls);
                    throw new DocumentClientException("test", HttpStatusCode.NotFound, SubStatusCodes.Unknown);
                },
                    forceRefresh : false,
                    null);

                Assert.Fail();
            }
            catch (DocumentClientException dce)
            {
                Assert.AreEqual(dce.StatusCode, HttpStatusCode.NotFound);
                Assert.AreEqual(1, totalLazyCalls);
            }

            // Verify cache removes the Task that hit the exception and the new task
            // is used to try to get the value.
            totalLazyCalls = 0;
            try
            {
                await asyncCache.GetAsync(
                    "key",
                    async() =>
                {
                    // Use a dummy await to make it simulate a real async network call
                    await Task.CompletedTask;
                    Interlocked.Increment(ref totalLazyCalls);
                    throw new DocumentClientException("test", HttpStatusCode.BadRequest, SubStatusCodes.Unknown);
                },
                    forceRefresh : false,
                    null);

                Assert.Fail();
            }
            catch (DocumentClientException dce)
            {
                Assert.AreEqual(dce.StatusCode, HttpStatusCode.BadRequest);
                Assert.AreEqual(1, totalLazyCalls);
            }

            // Verify cache success after failures
            totalLazyCalls = 0;
            string result = await asyncCache.GetAsync(
                "key",
                async() =>
            {
                // Use a dummy await to make it simulate a real async network call
                await Task.CompletedTask;
                Interlocked.Increment(ref totalLazyCalls);
                return("Test3");
            },
                forceRefresh : false,
                null);

            Assert.AreEqual(1, totalLazyCalls);
            Assert.AreEqual("Test3", result);
        }
コード例 #13
0
        public async Task ValidateNotFoundOnBackgroundRefreshRemovesFromCacheScenario()
        {
            string value1 = "Response1Value";
            AsyncCacheNonBlocking <string, string> asyncCache = new AsyncCacheNonBlocking <string, string>();
            string response1 = await asyncCache.GetAsync(
                "test",
                async (_) =>
            {
                await Task.Delay(TimeSpan.FromMilliseconds(5));
                return(value1);
            },
                (staleValue) =>
            {
                Assert.AreEqual(null, staleValue);
                return(false);
            });

            Assert.AreEqual(value1, response1);

            string response2 = await asyncCache.GetAsync(
                "test",
                async (_) =>
            {
                await Task.Delay(TimeSpan.FromMilliseconds(5));
                throw new Exception("Should use cached value");
            },
                (staleValue) =>
            {
                Assert.AreEqual(value1, staleValue);
                return(false);
            });

            Assert.AreEqual(value1, response2);

            NotFoundException notFoundException = new NotFoundException("Item was deleted");

            try
            {
                await asyncCache.GetAsync(
                    "test",
                    async (_) =>
                {
                    await Task.Delay(TimeSpan.FromMilliseconds(5));
                    throw notFoundException;
                },
                    (_) => true);

                Assert.Fail("Should have thrown a NotFoundException");
            }
            catch (NotFoundException exception)
            {
                Assert.AreEqual(notFoundException, exception);
            }

            string valueAfterNotFound = "response4Value";
            string response4          = await asyncCache.GetAsync(
                "test",
                async (_) =>
            {
                await Task.Delay(TimeSpan.FromMilliseconds(5));
                return(valueAfterNotFound);
            },
                (_) => false);

            Assert.AreEqual(valueAfterNotFound, response4);
        }