Repository: grpc/grpc-go
File: internal/resolver/delegatingresolver/delegatingresolver.go (Go)

Code before:
		r.proxyAddrs = make([]resolver.Address, 0, len(state.Endpoints))
		for _, endpoint := range state.Endpoints {
			r.proxyAddrs = append(r.proxyAddrs, endpoint.Addresses...)
		}
	} else if state.Addresses != nil {
		r.proxyAddrs = state.Addresses
	} else {
		r.proxyAddrs = []resolver.Address{} // ensure proxyAddrs is non-nil to indicate an update has been received
	}
	err := r.updateClientConnStateLocked()
	// Another possible approach was to block until updates are received from
	// both resolvers. But this is not used because calling `New()` triggers
	// `Build()` for the first resolver, which calls `UpdateState()`. And the
	// second resolver hasn't sent an update yet, so it would cause `New()` to
	// block indefinitely.
	if err != nil {
		go func() {
			r.childMu.Lock()
			defer r.childMu.Unlock()
			if r.targetResolver != nil {
				r.targetResolver.ResolveNow(resolver.ResolveNowOptions{})
			}
		}()
	}
	return err
}

// updateTargetResolverState is the StateListener function provided to the
// target resolver via wrappingClientConn. It updates the resolver state and
// marks the target resolver as ready. If the update includes at least one TCP
// address and the proxy resolver has not yet been constructed, it initializes
// the proxy resolver. A combined state update is triggered once both resolvers
// are ready. If all addresses are non-TCP, it proceeds without waiting for the
// proxy resolver. If ClientConn.UpdateState returns a non-nil error,
// ResolveNow() is called on the proxy resolver.
func (r *delegatingResolver) updateTargetResolverState(state resolver.State) error {
	r.mu.Lock()
	defer r.mu.Unlock()

	if logger.V(2) {
		logger.Infof("Addresses received from target resolver: %v", state.Addresses)
	}
	r.targetResolverState = &state
	// If no addresses returned by resolver have network type as tcp , do not
	// wait for proxy update.
	if !isTCPAddressPresent(r.targetResolverState) {
		return r.cc.UpdateState(*r.targetResolverState)
	}

	if len(r.proxyAddrs) == 0 {
		go func() {

Review comment (suggestion):
I see this `StateListener` being mentioned in a couple of places. There is no such method on the `resolver.ClientConn` interface.

Code after:
			r.proxyAddrs = append(r.proxyAddrs, endpoint.Addresses...)
		}
	} else if state.Addresses != nil {
		r.proxyAddrs = state.Addresses
	} else {
		r.proxyAddrs = []resolver.Address{} // ensure proxyAddrs is non-nil to indicate an update has been received
	}
	err := r.updateClientConnStateLocked()
	// Another possible approach was to block until updates are received from
	// both resolvers. But this is not used because calling `New()` triggers
	// `Build()` for the first resolver, which calls `UpdateState()`. And the
	// second resolver hasn't sent an update yet, so it would cause `New()` to
	// block indefinitely.
	if err != nil {
		go func() {
			r.childMu.Lock()
			defer r.childMu.Unlock()
			if r.targetResolver != nil {
				r.targetResolver.ResolveNow(resolver.ResolveNowOptions{})
			}
		}()
	}
	return err
}

// updateTargetResolverState is the StateListener function provided to the
// target resolver via wrappingClientConn. It updates the resolver state and
// marks the target resolver as ready. If the update includes at least one TCP
// address and the proxy resolver has not yet been constructed, it initializes
// the proxy resolver. A combined state update is triggered once both resolvers
// are ready. If all addresses are non-TCP, it proceeds without waiting for the
// proxy resolver. If ClientConn.UpdateState returns a non-nil error,
// ResolveNow() is called on the proxy resolver.
func (r *delegatingResolver) updateTargetResolverState(state resolver.State) error {
	r.mu.Lock()
	defer r.mu.Unlock()

	if logger.V(2) {
		logger.Infof("Addresses received from target resolver: %v", state.Addresses)
	}
	r.targetResolverState = &state
	// If no addresses returned by resolver have network type as tcp , do not
	// wait for proxy update.
	if !isTCPAddressPresent(r.targetResolverState) {
		return r.cc.UpdateState(*r.targetResolverState)
	}

	// The proxy resolver may be rebuilt multiple times, specifically each time
	// the target resolver sends an update, even if the target resolver is built
	// successfully but building the proxy resolver fails.
	if len(r.proxyAddrs) == 0 {