github.com/ydb-platform/ydb-go-sdk/v3@v3.89.2/balancers/config.go (about)

     1  package balancers
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  
     7  	balancerConfig "github.com/ydb-platform/ydb-go-sdk/v3/internal/balancer/config"
     8  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors"
     9  )
    10  
    11  type balancerType string
    12  
    13  const (
    14  	typeRoundRobin   = balancerType("round_robin")
    15  	typeRandomChoice = balancerType("random_choice")
    16  	typeSingle       = balancerType("single")
    17  	typeDisable      = balancerType("disable")
    18  )
    19  
    20  type preferType string
    21  
    22  const (
    23  	preferTypeNearestDC = preferType("nearest_dc")
    24  	preferTypeLocations = preferType("locations")
    25  
    26  	// Deprecated
    27  	// Will be removed after March 2025.
    28  	// Read about versioning policy: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#deprecated
    29  	preferTypeLocalDC = preferType("local_dc")
    30  )
    31  
    32  type balancersConfig struct {
    33  	Type      balancerType `json:"type"`
    34  	Prefer    preferType   `json:"prefer,omitempty"`
    35  	Fallback  bool         `json:"fallback,omitempty"`
    36  	Locations []string     `json:"locations,omitempty"`
    37  }
    38  
    39  type fromConfigOptionsHolder struct {
    40  	fallbackBalancer *balancerConfig.Config
    41  	errorHandler     func(error)
    42  }
    43  
    44  type fromConfigOption func(h *fromConfigOptionsHolder)
    45  
    46  func WithParseErrorFallbackBalancer(b *balancerConfig.Config) fromConfigOption {
    47  	return func(h *fromConfigOptionsHolder) {
    48  		h.fallbackBalancer = b
    49  	}
    50  }
    51  
    52  func WithParseErrorHandler(errorHandler func(error)) fromConfigOption {
    53  	return func(h *fromConfigOptionsHolder) {
    54  		h.errorHandler = errorHandler
    55  	}
    56  }
    57  
    58  func createByType(t balancerType) (*balancerConfig.Config, error) {
    59  	switch t {
    60  	case typeDisable:
    61  		return SingleConn(), nil
    62  	case typeSingle:
    63  		return SingleConn(), nil
    64  	case typeRandomChoice:
    65  		return RandomChoice(), nil
    66  	case typeRoundRobin:
    67  		return RoundRobin(), nil
    68  	default:
    69  		return nil, xerrors.WithStackTrace(fmt.Errorf("unknown type of balancer: %s", t))
    70  	}
    71  }
    72  
    73  func CreateFromConfig(s string) (*balancerConfig.Config, error) {
    74  	// try to parse s as identifier of balancer
    75  	if c, err := createByType(balancerType(s)); err == nil {
    76  		return c, nil
    77  	}
    78  
    79  	var (
    80  		b   *balancerConfig.Config
    81  		err error
    82  		c   balancersConfig
    83  	)
    84  
    85  	// try to parse s as json
    86  	if err = json.Unmarshal([]byte(s), &c); err != nil {
    87  		return nil, xerrors.WithStackTrace(err)
    88  	}
    89  
    90  	b, err = createByType(c.Type)
    91  	if err != nil {
    92  		return nil, xerrors.WithStackTrace(err)
    93  	}
    94  
    95  	switch c.Prefer {
    96  	case preferTypeLocalDC:
    97  		if c.Fallback {
    98  			return PreferNearestDCWithFallBack(b), nil
    99  		}
   100  
   101  		return PreferNearestDC(b), nil
   102  	case preferTypeNearestDC:
   103  		if c.Fallback {
   104  			return PreferNearestDCWithFallBack(b), nil
   105  		}
   106  
   107  		return PreferNearestDC(b), nil
   108  	case preferTypeLocations:
   109  		if len(c.Locations) == 0 {
   110  			return nil, xerrors.WithStackTrace(fmt.Errorf("empty locations list in balancer '%s' config", c.Type))
   111  		}
   112  		if c.Fallback {
   113  			return PreferLocationsWithFallback(b, c.Locations...), nil
   114  		}
   115  
   116  		return PreferLocations(b, c.Locations...), nil
   117  	default:
   118  		return b, nil
   119  	}
   120  }
   121  
   122  func FromConfig(config string, opts ...fromConfigOption) *balancerConfig.Config {
   123  	var (
   124  		h = fromConfigOptionsHolder{
   125  			fallbackBalancer: Default(),
   126  		}
   127  		b   *balancerConfig.Config
   128  		err error
   129  	)
   130  	for _, opt := range opts {
   131  		if opt != nil {
   132  			opt(&h)
   133  		}
   134  	}
   135  
   136  	b, err = CreateFromConfig(config)
   137  	if err != nil {
   138  		if h.errorHandler != nil {
   139  			h.errorHandler(err)
   140  		}
   141  
   142  		return h.fallbackBalancer
   143  	}
   144  
   145  	return b
   146  }