...

Source file src/golang.conradwood.net/go-easyops/client/fancy_addresslist_custom.go

Documentation: golang.conradwood.net/go-easyops/client

     1  package client
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"golang.conradwood.net/apis/registry"
     7  	"golang.conradwood.net/go-easyops/cmdline"
     8  	"golang.conradwood.net/go-easyops/utils"
     9  	"google.golang.org/grpc/connectivity"
    10  	"sync"
    11  	"time"
    12  )
    13  
    14  const (
    15  	REFRESH = time.Duration(5) * time.Second
    16  )
    17  
    18  var (
    19  	debug_custom_resolver    = flag.Bool("ge_debug_custom_fancy_resolver", false, "debug the custom fancy resolver, if any are being used")
    20  	custom_fancyadrlist_lock sync.Mutex
    21  )
    22  
    23  type custom_fancy_addresslist struct {
    24  	fal      *FancyAddressList
    25  	resolver func(registryadr, servicename string) ([]*registry.Target, error)
    26  }
    27  
    28  /*
    29  this creates a fancy address list, which does not automatically maintain its list of targets. it also does not (and cannot) be used for loadbalancing, because it has no connection to a grpc LoadBalancer or Picker.
    30  sometimes maybe might need a custom resolver for a fancy address list.
    31  */
    32  func NewFancyAddressListWithResolver(servicename string, resolver func(registryadr, servicename string) ([]*registry.Target, error)) (*FancyAddressList, error) {
    33  	fal := &FancyAddressList{Name: servicename}
    34  	cfa := &custom_fancy_addresslist{fal: fal, resolver: resolver}
    35  	targets, err := resolver(cmdline.GetClientRegistryAddress(), servicename)
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  	for _, fa := range targets_to_fancyadr(targets) {
    40  		fal.Add(fa)
    41  	}
    42  	go cfa.custom_fal_updater(REFRESH)
    43  	return fal, nil
    44  }
    45  
    46  func (cfa *custom_fancy_addresslist) custom_fal_updater(refresh time.Duration) {
    47  	for {
    48  		time.Sleep(refresh)
    49  		targets, err := cfa.resolver(cmdline.GetClientRegistryAddress(), cfa.fal.Name)
    50  		if err != nil {
    51  			fmt.Printf("[go-easyops] custom fancyaddresslist resolver failed: %s\n", err)
    52  			continue
    53  		}
    54  		cfa.debugf("got %d targets from resolver\n", len(targets))
    55  		fas := targets_to_fancyadr(targets)
    56  		cfa.debugf("got %d fancyaddress from %d targets from resolver\n", len(fas), len(targets))
    57  		ac := utils.CompareArray(fas, cfa.fal.addresses, func(i, j int) bool {
    58  			return fas[i].Key() == cfa.fal.addresses[j].Key()
    59  		})
    60  		for _, fa_idx := range ac.ElementsIn1ButNot2() {
    61  			cfa.debugf("adding %s\n", fas[fa_idx])
    62  			cfa.fal.Add(fas[fa_idx])
    63  		}
    64  		for _, fa_idx := range ac.ElementsIn2ButNot1() {
    65  			cfa.debugf("removing %s\n", cfa.fal.addresses[fa_idx])
    66  			cfa.fal.remove(cfa.fal.addresses[fa_idx])
    67  		}
    68  	}
    69  }
    70  func (cfa *custom_fancy_addresslist) debugf(format string, args ...interface{}) {
    71  	if !*debug_custom_resolver {
    72  		return
    73  	}
    74  	s := fmt.Sprintf(format, args...)
    75  	fmt.Printf("[go-easyops] fancyaddresslist: %s", s)
    76  }
    77  func targets_to_fancyadr(targets []*registry.Target) []*FancyAddr {
    78  	var res []*FancyAddr
    79  	for _, t := range targets {
    80  		if !hasApi(t.ApiType, registry.Apitype_grpc) {
    81  			// ignore targets without apitype grpc
    82  			continue
    83  		}
    84  		fa := &FancyAddr{state: connectivity.Ready, // docs say use CONNECTING here, but that never calls the picker nor the stateupdate. how does that work?
    85  			addr:   fmt.Sprintf("%s:%d", t.IP, t.Port),
    86  			Target: t,
    87  		}
    88  		res = append(res, fa)
    89  	}
    90  
    91  	return res
    92  }
    93  

View as plain text