private void UpdateSubchannelState(Subchannel subchannel, SubchannelState state) { var index = FindSubchannel(_addressSubchannels, subchannel); if (index == null) { SubchannelsLoadBalancerLog.IgnoredSubchannelStateChange(_logger, subchannel.Id); return; } SubchannelsLoadBalancerLog.ProcessingSubchannelStateChanged(_logger, subchannel.Id, state.State, state.Status); UpdateBalancingState(state.Status); if (state.State == ConnectivityState.TransientFailure || state.State == ConnectivityState.Idle) { SubchannelsLoadBalancerLog.RefreshingResolverForSubchannel(_logger, subchannel.Id, state.State); Controller.RefreshResolver(); } if (state.State == ConnectivityState.Idle) { SubchannelsLoadBalancerLog.RequestingConnectionForSubchannel(_logger, subchannel.Id, state.State); subchannel.RequestConnection(); } }
/// <inheritdoc /> public override void UpdateChannelState(ChannelState state) { if (state.Status.StatusCode != StatusCode.OK) { ResolverError(state.Status); return; } if (state.Addresses == null || state.Addresses.Count == 0) { ResolverError(new Status(StatusCode.Unavailable, "Resolver returned no addresses.")); return; } var allUpdatedSubchannels = new List <AddressSubchannel>(); var newSubchannels = new List <Subchannel>(); var currentSubchannels = _addressSubchannels.ToList(); // The state's addresses is the new authoritative list of addresses. // However, we want to keep existing subchannels when possible. foreach (var address in state.Addresses) { // Check existing subchannels for a match. var i = FindSubchannelByAddress(currentSubchannels, address); AddressSubchannel newOrCurrentSubConnection; if (i != null) { // There is a match so take current subchannel. newOrCurrentSubConnection = currentSubchannels[i.GetValueOrDefault()]; // Remove from current collection because any subchannels // remaining in this collection at the end will be disposed. currentSubchannels.RemoveAt(i.GetValueOrDefault()); } else { // No match so create a new subchannel. var c = Controller.CreateSubchannel(new SubchannelOptions(new[] { address })); c.OnStateChanged(s => UpdateSubchannelState(c, s)); newSubchannels.Add(c); newOrCurrentSubConnection = new AddressSubchannel(c, address); } allUpdatedSubchannels.Add(newOrCurrentSubConnection); } // Any sub-connections still in this collection are no longer returned by the resolver. // This can all be removed. var removedSubConnections = currentSubchannels; if (removedSubConnections.Count == 0 && newSubchannels.Count == 0) { SubchannelsLoadBalancerLog.ConnectionsUnchanged(_logger); return; } foreach (var removedSubConnection in removedSubConnections) { RemoveSubchannel(removedSubConnection.Subchannel); } _addressSubchannels.Clear(); _addressSubchannels.AddRange(allUpdatedSubchannels); // Start new connections after collection on balancer has been updated. foreach (var c in newSubchannels) { c.RequestConnection(); } UpdateBalancingState(state.Status); }