private async Task RefreshLocationPrivateAsync(CosmosAccountSettings databaseAccount)
        {
            if (this.cancellationTokenSource.IsCancellationRequested)
            {
                return;
            }

            DefaultTrace.TraceInformation("RefreshLocationAsync() refreshing locations");

            if (databaseAccount != null)
            {
                this.locationCache.OnDatabaseAccountRead(databaseAccount);
            }

            bool canRefreshInBackground = false;

            if (this.locationCache.ShouldRefreshEndpoints(out canRefreshInBackground))
            {
                if (databaseAccount == null && !canRefreshInBackground)
                {
                    databaseAccount = await this.RefreshDatabaseAccountInternalAsync();

                    this.locationCache.OnDatabaseAccountRead(databaseAccount);
                }

                this.StartRefreshLocationTimerAsync();
            }
            else
            {
                this.isRefreshing = false;
            }
        }
        private async void StartRefreshLocationTimerAsync()
        {
            if (this.cancellationTokenSource.IsCancellationRequested)
            {
                return;
            }

            try
            {
                await Task.Delay(this.backgroundRefreshLocationTimeIntervalInMS, this.cancellationTokenSource.Token);

                DefaultTrace.TraceInformation("StartRefreshLocationTimerAsync() - Invoking refresh");

                CosmosAccountSettings databaseAccount = await this.RefreshDatabaseAccountInternalAsync();

                await this.RefreshLocationPrivateAsync(databaseAccount);
            }
            catch (Exception ex)
            {
                if (this.cancellationTokenSource.IsCancellationRequested && (ex is TaskCanceledException || ex is ObjectDisposedException))
                {
                    return;
                }

                DefaultTrace.TraceCritical("StartRefreshLocationTimerAsync() - Unable to refresh database account from any location. Exception: {0}", ex.ToString());

                this.StartRefreshLocationTimerAsync();
            }
        }
        private async Task RefreshLocationPrivateAsync(CosmosAccountSettings databaseAccount)
        {
            DefaultTrace.TraceInformation("RefreshLocationAsync() refreshing locations");

            if (databaseAccount != null)
            {
                this.locationCache.OnDatabaseAccountRead(databaseAccount);
            }

            bool canRefreshInBackground = false;

            if (this.locationCache.ShouldRefreshEndpoints(out canRefreshInBackground))
            {
                if (databaseAccount == null && !canRefreshInBackground)
                {
                    databaseAccount = await GlobalEndpointManager.GetDatabaseAccountFromAnyLocationsAsync(this.defaultEndpoint, this.connectionPolicy.PreferredLocations, this.GetDatabaseAccountAsync);

                    this.locationCache.OnDatabaseAccountRead(databaseAccount);
                }

                this.StartRefreshLocationTimerAsync();
            }
            else
            {
                this.isRefreshing = false;
            }
        }
        public async Task RefreshLocationAsync(CosmosAccountSettings databaseAccount, bool forceRefresh = false)
        {
            if (this.cancellationTokenSource.IsCancellationRequested)
            {
                return;
            }

            if (forceRefresh)
            {
                CosmosAccountSettings refreshedDatabaseAccount = await this.RefreshDatabaseAccountInternalAsync();

                this.locationCache.OnDatabaseAccountRead(refreshedDatabaseAccount);
                return;
            }

            lock (this.refreshLock)
            {
                if (this.isRefreshing)
                {
                    return;
                }

                this.isRefreshing = true;
            }

            try
            {
                await this.RefreshLocationPrivateAsync(databaseAccount);
            }
            catch
            {
                this.isRefreshing = false;
                throw;
            }
        }
 /// <summary>
 /// Invoked when <see cref="CosmosAccountSettings"/> is read
 /// </summary>
 /// <param name="databaseAccount">Read DatabaseAccoaunt </param>
 public void OnDatabaseAccountRead(CosmosAccountSettings databaseAccount)
 {
     this.UpdateLocationCache(
         databaseAccount.WritableLocations,
         databaseAccount.ReadableLocations,
         preferenceList: null,
         enableMultipleWriteLocations: databaseAccount.EnableMultipleWriteLocations);
 }
Exemple #6
0
        public async Task GetCosmosDatabaseAccountSettings()
        {
            CosmosAccountSettings settings = await this.cosmosClient.GetAccountSettingsAsync();

            Assert.IsNotNull(settings);
            Assert.IsNotNull(settings.Id);
            Assert.IsNotNull(settings.ReadableLocations);
            Assert.IsTrue(settings.ReadableLocations.Count() > 0);
            Assert.IsNotNull(settings.WritableLocations);
            Assert.IsTrue(settings.WritableLocations.Count() > 0);
        }
Exemple #7
0
        public void CosmosAccountSettingsSerializationTest()
        {
            CosmosAccountSettings cosmosAccountSettings = new CosmosAccountSettings();

            cosmosAccountSettings.Id = "someId";
            cosmosAccountSettings.EnableMultipleWriteLocations = true;
            cosmosAccountSettings.ResourceId             = "/uri";
            cosmosAccountSettings.ETag                   = "etag";
            cosmosAccountSettings.WriteLocationsInternal = new Collection <CosmosAccountLocation>()
            {
                new CosmosAccountLocation()
                {
                    Name = "region1", DatabaseAccountEndpoint = "endpoint1"
                }
            };
            cosmosAccountSettings.ReadLocationsInternal = new Collection <CosmosAccountLocation>()
            {
                new CosmosAccountLocation()
                {
                    Name = "region2", DatabaseAccountEndpoint = "endpoint2"
                }
            };
            cosmosAccountSettings.AddressesLink      = "link";
            cosmosAccountSettings.ConsistencySetting = new CosmosAccountConsistency()
            {
                DefaultConsistencyLevel = Cosmos.ConsistencyLevel.BoundedStaleness
            };
            cosmosAccountSettings.ReplicationPolicy = new ReplicationPolicy()
            {
                AsyncReplication = true
            };
            cosmosAccountSettings.ReadPolicy = new ReadPolicy()
            {
                PrimaryReadCoefficient = 10
            };

            string cosmosSerialized = SettingsContractTests.CosmosSerialize(cosmosAccountSettings);

            CosmosAccountSettings accountDeserSettings = SettingsContractTests.CosmosDeserialize <CosmosAccountSettings>(cosmosSerialized);

            Assert.AreEqual(cosmosAccountSettings.Id, accountDeserSettings.Id);
            Assert.AreEqual(cosmosAccountSettings.EnableMultipleWriteLocations, accountDeserSettings.EnableMultipleWriteLocations);
            Assert.AreEqual(cosmosAccountSettings.ResourceId, accountDeserSettings.ResourceId);
            Assert.AreEqual(cosmosAccountSettings.ETag, accountDeserSettings.ETag);
            Assert.AreEqual(cosmosAccountSettings.WriteLocationsInternal[0].Name, accountDeserSettings.WriteLocationsInternal[0].Name);
            Assert.AreEqual(cosmosAccountSettings.WriteLocationsInternal[0].DatabaseAccountEndpoint, accountDeserSettings.WriteLocationsInternal[0].DatabaseAccountEndpoint);
            Assert.AreEqual(cosmosAccountSettings.ReadLocationsInternal[0].Name, accountDeserSettings.ReadLocationsInternal[0].Name);
            Assert.AreEqual(cosmosAccountSettings.ReadLocationsInternal[0].DatabaseAccountEndpoint, accountDeserSettings.ReadLocationsInternal[0].DatabaseAccountEndpoint);
            Assert.AreEqual(cosmosAccountSettings.AddressesLink, accountDeserSettings.AddressesLink);
            Assert.AreEqual(cosmosAccountSettings.ConsistencySetting.DefaultConsistencyLevel, accountDeserSettings.ConsistencySetting.DefaultConsistencyLevel);
            Assert.AreEqual(cosmosAccountSettings.ReplicationPolicy.AsyncReplication, accountDeserSettings.ReplicationPolicy.AsyncReplication);
            Assert.AreEqual(cosmosAccountSettings.ReadPolicy.PrimaryReadCoefficient, accountDeserSettings.ReadPolicy.PrimaryReadCoefficient);
        }
Exemple #8
0
        private async Task ValidateGetDatabaseAccountFromGatewayAsync()
        {
            Uri    writeRegionUri = new Uri(ConfigurationManager.AppSettings["GatewayEndpoint"]);
            string authKey        = ConfigurationManager.AppSettings["MasterKey"];

            using (DocumentClient client = new DocumentClient(writeRegionUri, authKey, connectionPolicy: null))
            {
                CosmosAccountSettings databaseAccount = await client.GetDatabaseAccountAsync();

                Assert.AreEqual(1, databaseAccount.WriteLocationsInternal.Count);
                Assert.AreEqual(1, databaseAccount.ReadLocationsInternal.Count);
            }
        }
        public static async Task <CosmosAccountSettings> GetDatabaseAccountFromAnyLocationsAsync(
            Uri defaultEndpoint, IList <string> locations, Func <Uri, Task <CosmosAccountSettings> > getDatabaseAccountFn)
        {
            try
            {
                CosmosAccountSettings databaseAccount = await getDatabaseAccountFn(defaultEndpoint);

                return(databaseAccount);
            }
            catch (Exception e)
            {
                DefaultTrace.TraceInformation("Fail to reach global gateway {0}, {1}", defaultEndpoint, e.ToString());
                if (locations.Count == 0)
                {
                    throw;
                }
            }

            for (int index = 0; index < locations.Count; index++)
            {
                try
                {
                    CosmosAccountSettings databaseAccount = await getDatabaseAccountFn(LocationHelper.GetLocationEndpoint(defaultEndpoint, locations[index]));

                    return(databaseAccount);
                }
                catch (Exception e)
                {
                    DefaultTrace.TraceInformation("Fail to reach location {0}, {1}", locations[index], e.ToString());
                    if (index == locations.Count - 1)
                    {
                        // if is the last one, throw exception
                        throw;
                    }
                }
            }

            // we should never reach here. Make compiler happy
            throw new Exception();
        }
        private void Initialize(
            bool useMultipleWriteLocations,
            bool enableEndpointDiscovery,
            bool isPreferredLocationsListEmpty)
        {
            this.databaseAccount = LocationCacheTests.CreateDatabaseAccount(useMultipleWriteLocations);

            this.preferredLocations = isPreferredLocationsListEmpty ? new List <string>().AsReadOnly() : new List <string>()
            {
                "location1",
                "location2",
                "location3"
            }.AsReadOnly();

            this.cache = new LocationCache(
                this.preferredLocations,
                LocationCacheTests.DefaultEndpoint,
                enableEndpointDiscovery,
                10,
                useMultipleWriteLocations);

            this.cache.OnDatabaseAccountRead(this.databaseAccount);

            this.mockedClient = new Mock <IDocumentClientInternal>();
            mockedClient.Setup(owner => owner.ServiceEndpoint).Returns(LocationCacheTests.DefaultEndpoint);
            mockedClient.Setup(owner => owner.GetDatabaseAccountInternalAsync(It.IsAny <Uri>(), It.IsAny <CancellationToken>())).ReturnsAsync(this.databaseAccount);

            ConnectionPolicy connectionPolicy = new ConnectionPolicy()
            {
                EnableEndpointDiscovery   = enableEndpointDiscovery,
                UseMultipleWriteLocations = useMultipleWriteLocations,
            };

            foreach (string preferredLocation in this.preferredLocations)
            {
                connectionPolicy.PreferredLocations.Add(preferredLocation);
            }

            this.endpointManager = new GlobalEndpointManager(mockedClient.Object, connectionPolicy);
        }
        private static CosmosAccountSettings CreateDatabaseAccount(bool useMultipleWriteLocations)
        {
            CosmosAccountSettings databaseAccount = new CosmosAccountSettings()
            {
                EnableMultipleWriteLocations = useMultipleWriteLocations,
                ReadLocationsInternal        = new Collection <CosmosAccountLocation>()
                {
                    { new CosmosAccountLocation()
                      {
                          Name = "location1", DatabaseAccountEndpoint = LocationCacheTests.Location1Endpoint.ToString()
                      } },
                    { new CosmosAccountLocation()
                      {
                          Name = "location2", DatabaseAccountEndpoint = LocationCacheTests.Location2Endpoint.ToString()
                      } },
                    { new CosmosAccountLocation()
                      {
                          Name = "location4", DatabaseAccountEndpoint = LocationCacheTests.Location4Endpoint.ToString()
                      } },
                },
                WriteLocationsInternal = new Collection <CosmosAccountLocation>()
                {
                    { new CosmosAccountLocation()
                      {
                          Name = "location1", DatabaseAccountEndpoint = LocationCacheTests.Location1Endpoint.ToString()
                      } },
                    { new CosmosAccountLocation()
                      {
                          Name = "location2", DatabaseAccountEndpoint = LocationCacheTests.Location2Endpoint.ToString()
                      } },
                    { new CosmosAccountLocation()
                      {
                          Name = "location3", DatabaseAccountEndpoint = LocationCacheTests.Location3Endpoint.ToString()
                      } },
                }
            };

            return(databaseAccount);
        }
        public async Task RefreshLocationAsync(CosmosAccountSettings databaseAccount)
        {
            lock (this.refreshLock)
            {
                if (this.isRefreshing)
                {
                    return;
                }

                this.isRefreshing = true;
            }

            try
            {
                await this.RefreshLocationPrivateAsync(databaseAccount);
            }
            catch
            {
                this.isRefreshing = false;
                throw;
            }
        }
Exemple #13
0
        private async void StartRefreshLocationTimerAsync()
        {
            if (this.isDisposed)
            {
                return;
            }

            try
            {
                await Task.Delay(this.backgroundRefreshLocationTimeIntervalInMS);

                DefaultTrace.TraceInformation("StartRefreshLocationTimerAsync() - Invoking refresh");

                CosmosAccountSettings databaseAccount = await this.RefreshDatabaseAccountInternalAsync();

                await this.RefreshLocationPrivateAsync(databaseAccount);
            }
            catch (Exception ex)
            {
                DefaultTrace.TraceCritical("StartRefreshLocationTimerAsync() - Unable to refresh database account from any location. Exception: {0}", ex.ToString());
                this.StartRefreshLocationTimerAsync();
            }
        }
        private async void StartRefreshLocationTimerAsync()
        {
            if (this.isDisposed)
            {
                return;
            }

            try
            {
                await Task.Delay(this.backgroundRefreshLocationTimeIntervalInMS);

                DefaultTrace.TraceInformation("StartRefreshLocationTimerAsync() - Invoking refresh");

                CosmosAccountSettings databaseAccount = await GlobalEndpointManager.GetDatabaseAccountFromAnyLocationsAsync(this.defaultEndpoint, this.connectionPolicy.PreferredLocations, this.GetDatabaseAccountAsync);

                await this.RefreshLocationPrivateAsync(databaseAccount);
            }
            catch (Exception ex)
            {
                DefaultTrace.TraceCritical("StartRefreshLocationTimerAsync() - Unable to refresh database account from any location. Exception: {0}", ex.ToString());
                this.StartRefreshLocationTimerAsync();
            }
        }