From 4b8b9018a7bdc99248d3364d554374bd7ba35f40 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Fri, 7 Jun 2024 14:22:36 +0800 Subject: [PATCH 1/2] Fix flaky ConnectTimeout_MultipleCalls_AttemptReconnect test --- .../Balancer/Internal/ConnectionManager.cs | 22 ++++++++++++++++--- src/Grpc.Net.Client/Balancer/Subchannel.cs | 8 +++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/Grpc.Net.Client/Balancer/Internal/ConnectionManager.cs b/src/Grpc.Net.Client/Balancer/Internal/ConnectionManager.cs index 68fea1649..803ab021f 100644 --- a/src/Grpc.Net.Client/Balancer/Internal/ConnectionManager.cs +++ b/src/Grpc.Net.Client/Balancer/Internal/ConnectionManager.cs @@ -312,12 +312,20 @@ public void UpdateState(BalancerState state) { case PickResultType.Complete: var subchannel = result.Subchannel!; - var address = subchannel.CurrentAddress; + var (address, state) = subchannel.GetAddressAndState(); if (address != null) { - ConnectionManagerLog.PickResultSuccessful(Logger, subchannel.Id, address, subchannel.Transport.TransportStatus); - return (subchannel, address, result.SubchannelCallTracker); + if (state == ConnectivityState.Ready) + { + ConnectionManagerLog.PickResultSuccessful(Logger, subchannel.Id, address, subchannel.Transport.TransportStatus); + return (subchannel, address, result.SubchannelCallTracker); + } + else + { + ConnectionManagerLog.PickResultSubchannelNotReady(Logger, subchannel.Id, state); + previousPicker = currentPicker; + } } else { @@ -499,6 +507,9 @@ internal static class ConnectionManagerLog private static readonly Action _resolverServiceConfigFallback = LoggerMessage.Define(LogLevel.Debug, new EventId(12, "ResolverServiceConfigFallback"), "Falling back to previously loaded service config. Resolver failure when retreiving or parsing service config with status: {Status}"); + private static readonly Action _pickResultSubchannelNotReady = + LoggerMessage.Define(LogLevel.Debug, new EventId(13, "PickResultSubchannelNotReady"), "Picked subchannel id '{SubchannelId}' with address {CurrentAddress} doesn't have a ready state. Subchannel state: {State}"); + public static void ResolverUnsupportedLoadBalancingConfig(ILogger logger, IList loadBalancingConfigs) { if (logger.IsEnabled(LogLevel.Warning)) @@ -562,5 +573,10 @@ public static void ResolverServiceConfigFallback(ILogger logger, Status status) { _resolverServiceConfigFallback(logger, status, null); } + + public static void PickResultSubchannelNotReady(ILogger logger, string subchannelId, BalancerAddress currentAddress, ConnectivityState state) + { + _pickResultSubchannelNotReady(logger, subchannelId, currentAddress, state, null); + } } #endif diff --git a/src/Grpc.Net.Client/Balancer/Subchannel.cs b/src/Grpc.Net.Client/Balancer/Subchannel.cs index 0f163de9d..dcfdcd8a5 100644 --- a/src/Grpc.Net.Client/Balancer/Subchannel.cs +++ b/src/Grpc.Net.Client/Balancer/Subchannel.cs @@ -86,6 +86,14 @@ public BalancerAddress? CurrentAddress /// public BalancerAttributes Attributes { get; } + internal (BalancerAddress? Address, ConnectivityState State) GetAddressAndState() + { + lock (Lock) + { + return (CurrentAddress, State); + } + } + internal Subchannel(ConnectionManager manager, IReadOnlyList addresses) { Lock = new object(); From 9765c1a674981cdfdfc4b35e75bff597eea0c09e Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Fri, 7 Jun 2024 14:23:27 +0800 Subject: [PATCH 2/2] Fix --- src/Grpc.Net.Client/Balancer/Internal/ConnectionManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Grpc.Net.Client/Balancer/Internal/ConnectionManager.cs b/src/Grpc.Net.Client/Balancer/Internal/ConnectionManager.cs index 803ab021f..b64a4557c 100644 --- a/src/Grpc.Net.Client/Balancer/Internal/ConnectionManager.cs +++ b/src/Grpc.Net.Client/Balancer/Internal/ConnectionManager.cs @@ -323,7 +323,7 @@ public void UpdateState(BalancerState state) } else { - ConnectionManagerLog.PickResultSubchannelNotReady(Logger, subchannel.Id, state); + ConnectionManagerLog.PickResultSubchannelNotReady(Logger, subchannel.Id, address, state); previousPicker = currentPicker; } }