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); }
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); }
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); }
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; } }
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(); } }