github.com/projecteru2/core@v0.0.0-20240321043226-06bcc1c23f58/client/resolver/eru/resolver.go (about)

     1  package eru
     2  
     3  import (
     4  	"context"
     5  	"strings"
     6  
     7  	"github.com/projecteru2/core/client/servicediscovery"
     8  	"github.com/projecteru2/core/log"
     9  	"github.com/projecteru2/core/types"
    10  
    11  	"google.golang.org/grpc/resolver"
    12  )
    13  
    14  // Resolver for target eru://{addr}
    15  type Resolver struct {
    16  	cc        resolver.ClientConn
    17  	cancel    context.CancelFunc
    18  	discovery servicediscovery.ServiceDiscovery
    19  }
    20  
    21  // New Resolver
    22  func New(cc resolver.ClientConn, endpoint string, authority string) *Resolver {
    23  	var username, password string
    24  	if authority != "" {
    25  		parts := strings.Split(authority, ":")
    26  		username, password = strings.TrimLeft(parts[0], "@"), parts[1]
    27  	}
    28  	authConfig := types.AuthConfig{Username: username, Password: password}
    29  	r := &Resolver{
    30  		cc:        cc,
    31  		discovery: servicediscovery.New(endpoint, authConfig),
    32  	}
    33  	cc.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: endpoint}}}) //nolint
    34  	go r.sync(context.TODO())
    35  	return r
    36  }
    37  
    38  // ResolveNow for interface
    39  func (r *Resolver) ResolveNow(_ resolver.ResolveNowOptions) {}
    40  
    41  // Close for interface
    42  func (r *Resolver) Close() {
    43  	r.cancel()
    44  }
    45  
    46  func (r *Resolver) sync(ctx context.Context) {
    47  	ctx, r.cancel = context.WithCancel(ctx)
    48  	defer r.cancel()
    49  	logger := log.WithFunc("resolver.sync")
    50  	logger.Debug(ctx, "start sync service discovery")
    51  
    52  	ch, err := r.discovery.Watch(ctx)
    53  	if err != nil {
    54  		logger.Error(ctx, err, "failed to watch service status")
    55  		return
    56  	}
    57  	for {
    58  		select {
    59  		case <-ctx.Done():
    60  			logger.Error(ctx, ctx.Err(), "watch interrupted")
    61  			return
    62  		case endpoints, ok := <-ch:
    63  			if !ok {
    64  				logger.Info(ctx, nil, "watch closed")
    65  				return
    66  			}
    67  
    68  			var addresses []resolver.Address
    69  			for _, ep := range endpoints {
    70  				addresses = append(addresses, resolver.Address{Addr: ep})
    71  			}
    72  			r.cc.UpdateState(resolver.State{Addresses: addresses}) //nolint
    73  		}
    74  	}
    75  
    76  }