Repository: grpc/grpc-go
File: balancer/pickfirst/pickfirstleaf/pickfirstleaf.go (Go)

Code before:
	})
}

func (b *pickfirstBalancer) updateSubConnState(sd *scData, newState balancer.SubConnState) {
	b.mu.Lock()
	defer b.mu.Unlock()
	oldState := sd.state
	// Record a connection attempt when exiting CONNECTING.
	if newState.ConnectivityState == connectivity.TransientFailure {
		sd.connectionFailedInFirstPass = true
	}
	sd.state = newState.ConnectivityState
	// Previously relevant SubConns can still callback with state updates.
	// To prevent pickers from returning these obsolete SubConns, this logic
	// is included to check if the current list of active SubConns includes this
	// SubConn.
	if activeSD, found := b.subConns.Get(sd.addr); !found || activeSD != sd {
		return
	}
	if newState.ConnectivityState == connectivity.Shutdown {
		return
	}

	if oldState == connectivity.Connecting && newState.ConnectivityState == connectivity.TransientFailure {
		pickFirstConnectionAttemptsFailed.Record(b.metricsRecorder, 1, b.target)
	}

	if newState.ConnectivityState == connectivity.Ready {
		pickFirstConnectionAttemptsSucceeded.Record(b.metricsRecorder, 1, b.target)
		b.shutdownRemainingLocked(sd)
		if !b.addressList.seekTo(sd.addr) {
			// This should not fail as we should have only one SubConn after
			// entering READY. The SubConn should be present in the addressList.
			b.logger.Errorf("Address %q not found address list in  %v", sd.addr, b.addressList.addresses)
			return
		}
		b.state = connectivity.Ready
		b.cc.UpdateState(balancer.State{
			ConnectivityState: connectivity.Ready,
			Picker:            &picker{result: balancer.PickResult{SubConn: sd.subConn}},
		})
		return
	}

	// If the LB policy is READY, and it receives a subchannel state change,
	// it means that the READY subchannel has failed.
	// A SubConn can also transition from CONNECTING directly to IDLE when
	// a transport is successfully created, but the connection fails
	// before the SubConn can send the notification for READY. We treat
	// this as a successful connection and transition to IDLE.
	if (b.state == connectivity.Ready && newState.ConnectivityState != connectivity.Ready) || (oldState == connectivity.Connecting && newState.ConnectivityState == connectivity.Idle) {

Review comment (refactor):
Given that the only state from which a subchannel can transition to TF is CONNECTING, is there a reason to check `oldState` here?

Also, would it be better to move this to inside of the `select` arms for TF? We would have to have this two places if we do that, but that would also prevent adding more special cases here at the top of this method. What do you think?

Code after:
	})
}

func (b *pickfirstBalancer) updateSubConnState(sd *scData, newState balancer.SubConnState) {
	b.mu.Lock()
	defer b.mu.Unlock()
	oldState := sd.state
	sd.state = newState.ConnectivityState
	// Previously relevant SubConns can still callback with state updates.
	// To prevent pickers from returning these obsolete SubConns, this logic
	// is included to check if the current list of active SubConns includes this
	// SubConn.
	if activeSD, found := b.subConns.Get(sd.addr); !found || activeSD != sd {
		return
	}
	if newState.ConnectivityState == connectivity.Shutdown {
		return
	}

	// Record a connection attempt when exiting CONNECTING.
	if newState.ConnectivityState == connectivity.TransientFailure {
		sd.connectionFailedInFirstPass = true
		connectionAttemptsFailedMetric.Record(b.metricsRecorder, 1, b.target)
	}

	if newState.ConnectivityState == connectivity.Ready {
		connectionAttemptsSucceededMetric.Record(b.metricsRecorder, 1, b.target)
		b.shutdownRemainingLocked(sd)
		if !b.addressList.seekTo(sd.addr) {
			// This should not fail as we should have only one SubConn after
			// entering READY. The SubConn should be present in the addressList.
			b.logger.Errorf("Address %q not found address list in  %v", sd.addr, b.addressList.addresses)
			return
		}
		b.state = connectivity.Ready
		b.cc.UpdateState(balancer.State{
			ConnectivityState: connectivity.Ready,
			Picker:            &picker{result: balancer.PickResult{SubConn: sd.subConn}},
		})
		return
	}

	// If the LB policy is READY, and it receives a subchannel state change,
	// it means that the READY subchannel has failed.
	// A SubConn can also transition from CONNECTING directly to IDLE when
	// a transport is successfully created, but the connection fails
	// before the SubConn can send the notification for READY. We treat
	// this as a successful connection and transition to IDLE.
	if (b.state == connectivity.Ready && newState.ConnectivityState != connectivity.Ready) || (oldState == connectivity.Connecting && newState.ConnectivityState == connectivity.Idle) {
		// Once a transport fails, the balancer enters IDLE and starts from
		// the first address when the picker is used.