func (cr *cacheRecord) refreshIfRequired(name string, resolve func(string) ([]net.IP, error), maxAge time.Duration) {
	cr.mu.Lock()

	// If no need to refresh or update in progress
	if cr.updateInProgress || time.Since(cr.lastUpdatedAt) < maxAge {
		cr.mu.Unlock()
		return
	}

	// Cache record is old and no update in progress, issue a request to update.
	cr.updateInProgress = true
	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		defer wg.Done()
		// Note that we call backend's resolve outside of the mutex locks and take the lock again
		// to update the cache record once we have the results from the backend.
		ips, err := resolve(name)
		cr.mu.Lock()
		defer cr.mu.Unlock()
		cr.err = err
		if err != nil {
			// Reset cache record time so it's updated inline next time.
			cr.lastUpdatedAt = time.Time{}
			cr.updateInProgress = false
			return
		}
		// Reset error state
		cr.err = nil
		var ip4, ip6 net.IP
		for _, ip := range ips {
			switch ipVersion(ip) {
			case 4:
				ip4 = ip
			case 6:
				ip6 = ip
			}
		}
		cr.ip4 = ip4
		cr.ip6 = ip6
		cr.lastUpdatedAt = time.Now()
		cr.updateInProgress = false
	}()

	// Wait if this is first update
	if cr.lastUpdatedAt.IsZero() {
		cr.mu.Unlock()
		wg.Wait()
	} else {
		cr.mu.Unlock()
	}
	return
}
// refreshIfRequired does most of the work. Overall goal is to minimize the lock period of the cache record. To that
// end, if the cache record needs updating, we do that with the mutex unlocked.
//
// If cache record is already being updated or fresh enough it returns immediately.
// if cache record needs updating, we kick off refresh in a new goroutine. If this is not the first update, we immediately
// return whatever is in the cache. However, if it's the first update, we wait for the refresh to finish, before returning.
//
// TODO: See if this whole magic will be simpler to reason-about if we use channels.
refreshIfRequired does most of the work. Overall goal is to minimize the lock period of the cache record. To that
end, if the cache record needs updating, we do that with the mutex unlocked.

If cache record is already being updated or fresh enough it returns immediately.
if cache record needs updating, we kick off refresh in a new goroutine. If this is not the first update, we immediately
return whatever is in the cache. However, if it's the first update, we wait for the refresh to finish, before returning.

See if this whole magic will be simpler to reason-about if we use channels.
// refreshIfRequired does most of the work . Overall goal is to minimize the lock period of the cache record . To that // end if the cache record needs updating we do that with the mutex unlocked . // // If cache record is already being updated or fresh enough it returns immediately . // if cache record needs updating we kick off refresh in a new goroutine . If this is not the first update we immediately // return whatever is in the cache . However if it ' s the first update we wait for the refresh to finish before returning . // // TODO : See if this whole magic will be simpler to reason - about if we use channels .
func (cr *cacheRecord) refreshIfRequired(name string, resolve func(string) ([]net.IP, error), maxAge time.Duration) {
	cr.mu.Lock()
	if cr.updateInProgress || time.Since(cr.lastUpdatedAt) < maxAge {
		cr.mu.Unlock()
		return
	}
	cr.updateInProgress = true
	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		defer wg.Done()
		ips, err := resolve(name)
		cr.mu.Lock()
		defer cr.mu.Unlock()
		cr.err = err
		if err != nil {
			cr.lastUpdatedAt = time.Time{}
			cr.updateInProgress = false
			return
		}
		cr.err = nil
		var ip4, ip6 net.IP
		for _, ip := range ips {
			switch ipVersion(ip) {
			case 4:
				ip4 = ip
			case 6:
				ip6 = ip
			}
		}
		cr.ip4 = ip4
		cr.ip6 = ip6
		cr.lastUpdatedAt = time.Now()
		cr.updateInProgress = false
	}()
	if cr.lastUpdatedAt.IsZero() {
		cr.mu.Unlock()
		wg.Wait()
	} else {
		cr.mu.Unlock()
	}
	return
}
func ( cr * cacheRecord ) refreshIfRequired ( name string , resolve func ( string ) ( [ ] net . IP , error ) , maxAge time . Duration ) { cr . mu . Lock ( ) if cr . updateInProgress || time . Since ( cr . lastUpdatedAt ) < maxAge { cr . mu . Unlock ( ) return } cr . updateInProgress = true var wg sync . WaitGroup wg . Add ( 1 ) go func ( ) { defer wg . Done ( ) ips , err := resolve ( name ) cr . mu . Lock ( ) defer cr . mu . Unlock ( ) cr . err = err if err != nil { cr . lastUpdatedAt = time . Time { } cr . updateInProgress = false return } cr . err = nil var ip4 , ip6 net . IP for _ , ip := range ips { switch ipVersion ( ip ) { case 4 : ip4 = ip case 6 : ip6 = ip } } cr . ip4 = ip4 cr . ip6 = ip6 cr . lastUpdatedAt = time . Now ( ) cr . updateInProgress = false } ( ) if cr . lastUpdatedAt . IsZero ( ) { cr . mu . Unlock ( ) wg . Wait ( ) } else { cr . mu . Unlock ( ) } return }
refreshIfRequired does most of the work.
refreshIfRequired does most of the work .
// If no need to refresh or update in progress // Cache record is old and no update in progress, issue a request to update. // Note that we call backend's resolve outside of the mutex locks and take the lock again // to update the cache record once we have the results from the backend. // Reset cache record time so it's updated inline next time. // Reset error state // Wait if this is first update