Repository: grpc/grpc-go
File: internal/xds/balancer/clusterresolver/resource_resolver_dns.go (Go)

Code before:
}

// The definition of stop() mentions that implementations must not invoke any
// methods on the topLevelResolver once the call to `stop()` returns. The
// underlying dns resolver does not send any updates to the resolver.ClientConn
// interface passed to it (implemented by dnsDiscoveryMechanism in this case)
// after its `Close()` returns. Therefore, we can guarantee that no methods of
// the topLevelResolver are invoked after we return from this method.
func (dr *dnsDiscoveryMechanism) stop() {
	if dr.dnsR != nil {
		dr.dnsR.Close()
	}
}

// dnsDiscoveryMechanism needs to implement resolver.ClientConn interface to receive
// updates from the real DNS resolver.

func (dr *dnsDiscoveryMechanism) UpdateState(state resolver.State) error {
	if dr.logger.V(2) {
		dr.logger.Infof("DNS discovery mechanism for resource %q reported an update: %s", dr.target, pretty.ToJSON(state))
	}

	dr.mu.Lock()
	var endpoints = state.Endpoints
	if len(endpoints) == 0 {
		endpoints = []resolver.Endpoint{{Addresses: state.Addresses}}
	}
	dr.endpoints = endpoints
	dr.updateReceived = true
	dr.mu.Unlock()

	dr.topLevelResolver.onUpdate(func() {})
	return nil
}

func (dr *dnsDiscoveryMechanism) ReportError(err error) {
	if dr.logger.V(2) {
		dr.logger.Infof("DNS discovery mechanism for resource %q reported error: %v", dr.target, err)
	}

	dr.mu.Lock()
	// If a previous good update was received, suppress the error and continue
	// using the previous update. If RPCs were succeeding prior to this, they
	// will continue to do so. Also suppress errors if we previously received an
	// error, since there will be no downstream effects of propagating this
	// error.
	if dr.updateReceived {
		dr.mu.Unlock()
		return
	}
	dr.endpoints = nil

Review comment (suggestion):
I think we should return a single endpoint with all addresses from here, whether the DNS resolver returns addresses or endpoints. That way, we can be sure that in the config builder part, we always just have a single endpoint when the cluster is LOGICAL_DNS.

Code after:
}

// The definition of stop() mentions that implementations must not invoke any
// methods on the topLevelResolver once the call to `stop()` returns. The
// underlying dns resolver does not send any updates to the resolver.ClientConn
// interface passed to it (implemented by dnsDiscoveryMechanism in this case)
// after its `Close()` returns. Therefore, we can guarantee that no methods of
// the topLevelResolver are invoked after we return from this method.
func (dr *dnsDiscoveryMechanism) stop() {
	if dr.dnsR != nil {
		dr.dnsR.Close()
	}
}

// dnsDiscoveryMechanism needs to implement resolver.ClientConn interface to receive
// updates from the real DNS resolver.

func (dr *dnsDiscoveryMechanism) UpdateState(state resolver.State) error {
	if dr.logger.V(2) {
		dr.logger.Infof("DNS discovery mechanism for resource %q reported an update: %s", dr.target, pretty.ToJSON(state))
	}

	dr.mu.Lock()
	dr.endpoints = state.Endpoints
	dr.updateReceived = true
	dr.mu.Unlock()

	dr.topLevelResolver.onUpdate(func() {})
	return nil
}

func (dr *dnsDiscoveryMechanism) ReportError(err error) {
	if dr.logger.V(2) {
		dr.logger.Infof("DNS discovery mechanism for resource %q reported error: %v", dr.target, err)
	}

	dr.mu.Lock()
	// If a previous good update was received, suppress the error and continue
	// using the previous update. If RPCs were succeeding prior to this, they
	// will continue to do so. Also suppress errors if we previously received an
	// error, since there will be no downstream effects of propagating this
	// error.
	if dr.updateReceived {
		dr.mu.Unlock()
		return
	}
	dr.endpoints = nil
	dr.updateReceived = true
	dr.mu.Unlock()

	dr.topLevelResolver.onUpdate(func() {})