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 }