public async Task SequentialCreatesOnlyUseOneChannel() { //SpannerClients if created sequentially should only use a single channel. //This is to faciliate good session pool hits (which is per channel). If we always //round robin'd clients, then we would get hard cache misses until we populated all //of the caches per channel. //Since channels are lazily created, this also saves resources for scenarios like rich clients //that may only need a single session for multiple sequential workloads. //Our default setting for # channels = 4 needs to work well for all scenarios. var firstReturnedClient = new Mock <SpannerClient>(); var mockClientFactory = SetupMockClientFactory(firstReturnedClient); var testPool = new ClientPool(mockClientFactory); var expectedClient = firstReturnedClient.Object; Assert.Same(expectedClient, await testPool.AcquireClientAsync(s_defaultConnectionStringBuilder)); testPool.ReleaseClient(expectedClient, s_defaultConnectionStringBuilder); Assert.Same(expectedClient, await testPool.AcquireClientAsync(s_defaultConnectionStringBuilder)); testPool.ReleaseClient(expectedClient, s_defaultConnectionStringBuilder); Assert.Same(expectedClient, await testPool.AcquireClientAsync(s_defaultConnectionStringBuilder)); testPool.ReleaseClient(expectedClient, s_defaultConnectionStringBuilder); var s = new StringBuilder(); Assert.Equal(0, testPool.GetPoolInfo(s)); Logger.DefaultLogger.Info(() => s.ToString()); Assert.Equal(1, mockClientFactory.Invocations); }
private static async Task <SpannerClient> GetSpannerClientAsync(ClientPool pool) { //immediately yield to increase contention for stress testing. await Task.Yield(); return(await pool.AcquireClientAsync(s_defaultConnectionStringBuilder)); }
public async Task RoundRobin() { var mockClientFactory = SetupMockClientFactory(); var testPool = new ClientPool(mockClientFactory); var clientList = new List <SpannerClient>(); for (var i = 0; i < SpannerOptions.Instance.MaximumGrpcChannels; i++) { var newClient = await testPool.AcquireClientAsync(s_defaultConnectionStringBuilder); Assert.DoesNotContain(newClient, clientList); clientList.Add(newClient); } //now we wrap around. var firstReusedClient = await testPool.AcquireClientAsync(s_defaultConnectionStringBuilder); Assert.Same(clientList[0], firstReusedClient); testPool.ReleaseClient(firstReusedClient, s_defaultConnectionStringBuilder); foreach (var client in clientList) { testPool.ReleaseClient(client, s_defaultConnectionStringBuilder); } var s = new StringBuilder(); Assert.Equal(0, testPool.GetPoolInfo(s)); Logger.DefaultLogger.Info(() => s.ToString()); //now that everything got released, lets ensure the client order is preserved so //that we again get the first client. Assert.Same(firstReusedClient, await testPool.AcquireClientAsync(s_defaultConnectionStringBuilder)); testPool.ReleaseClient(firstReusedClient, s_defaultConnectionStringBuilder); Assert.Equal(SpannerOptions.Instance.MaximumGrpcChannels, mockClientFactory.Invocations); }
public async Task ClientsCreatedOnDemandAsync() { //SpannerClients should not be precreated, but be created lazily. var mockClientFactory = SetupMockClientFactory(); var testPool = new ClientPool(mockClientFactory); var clientAcquired = await testPool.AcquireClientAsync(s_defaultConnectionStringBuilder); testPool.ReleaseClient(clientAcquired, s_defaultConnectionStringBuilder); Assert.Equal(1, mockClientFactory.Invocations); var s = new StringBuilder(); Assert.Equal(0, testPool.GetPoolInfo(s)); Logger.DefaultLogger.Info(() => s.ToString()); }