github.com/ydb-platform/ydb-go-sdk/v3@v3.57.0/internal/coordination/client.go (about) 1 package coordination 2 3 import ( 4 "context" 5 "errors" 6 7 "github.com/ydb-platform/ydb-go-genproto/Ydb_Coordination_V1" 8 "github.com/ydb-platform/ydb-go-genproto/protos/Ydb_Coordination" 9 "google.golang.org/grpc" 10 11 "github.com/ydb-platform/ydb-go-sdk/v3/coordination" 12 "github.com/ydb-platform/ydb-go-sdk/v3/internal/coordination/config" 13 "github.com/ydb-platform/ydb-go-sdk/v3/internal/operation" 14 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" 15 "github.com/ydb-platform/ydb-go-sdk/v3/retry" 16 "github.com/ydb-platform/ydb-go-sdk/v3/scheme" 17 ) 18 19 //nolint:gofumpt 20 //nolint:nolintlint 21 var ( 22 errNilClient = xerrors.Wrap(errors.New("coordination client is not initialized")) 23 ) 24 25 type Client struct { 26 config config.Config 27 service Ydb_Coordination_V1.CoordinationServiceClient 28 } 29 30 func New(ctx context.Context, cc grpc.ClientConnInterface, config config.Config) (*Client, error) { 31 return &Client{ 32 config: config, 33 service: Ydb_Coordination_V1.NewCoordinationServiceClient(cc), 34 }, nil 35 } 36 37 func (c *Client) CreateNode(ctx context.Context, path string, config coordination.NodeConfig) error { 38 if c == nil { 39 return xerrors.WithStackTrace(errNilClient) 40 } 41 call := func(ctx context.Context) error { 42 return xerrors.WithStackTrace(c.createNode(ctx, path, config)) 43 } 44 if !c.config.AutoRetry() { 45 return xerrors.WithStackTrace(call(ctx)) 46 } 47 48 return retry.Retry(ctx, 49 call, retry.WithStackTrace(), 50 retry.WithIdempotent(true), 51 retry.WithTrace(c.config.TraceRetry()), 52 ) 53 } 54 55 func (c *Client) createNode(ctx context.Context, path string, config coordination.NodeConfig) error { 56 _, err := c.service.CreateNode( 57 ctx, 58 &Ydb_Coordination.CreateNodeRequest{ 59 Path: path, 60 Config: &Ydb_Coordination.Config{ 61 Path: config.Path, 62 SelfCheckPeriodMillis: config.SelfCheckPeriodMillis, 63 SessionGracePeriodMillis: config.SessionGracePeriodMillis, 64 ReadConsistencyMode: config.ReadConsistencyMode.To(), 65 AttachConsistencyMode: config.AttachConsistencyMode.To(), 66 RateLimiterCountersMode: config.RatelimiterCountersMode.To(), 67 }, 68 OperationParams: operation.Params( 69 ctx, 70 c.config.OperationTimeout(), 71 c.config.OperationCancelAfter(), 72 operation.ModeSync, 73 ), 74 }, 75 ) 76 77 return xerrors.WithStackTrace(err) 78 } 79 80 func (c *Client) AlterNode(ctx context.Context, path string, config coordination.NodeConfig) error { 81 if c == nil { 82 return xerrors.WithStackTrace(errNilClient) 83 } 84 call := func(ctx context.Context) error { 85 return xerrors.WithStackTrace(c.alterNode(ctx, path, config)) 86 } 87 if !c.config.AutoRetry() { 88 return xerrors.WithStackTrace(call(ctx)) 89 } 90 91 return retry.Retry(ctx, 92 call, 93 retry.WithStackTrace(), 94 retry.WithIdempotent(true), 95 retry.WithTrace(c.config.TraceRetry()), 96 ) 97 } 98 99 func (c *Client) alterNode(ctx context.Context, path string, config coordination.NodeConfig) error { 100 _, err := c.service.AlterNode( 101 ctx, 102 &Ydb_Coordination.AlterNodeRequest{ 103 Path: path, 104 Config: &Ydb_Coordination.Config{ 105 Path: config.Path, 106 SelfCheckPeriodMillis: config.SelfCheckPeriodMillis, 107 SessionGracePeriodMillis: config.SessionGracePeriodMillis, 108 ReadConsistencyMode: config.ReadConsistencyMode.To(), 109 AttachConsistencyMode: config.AttachConsistencyMode.To(), 110 RateLimiterCountersMode: config.RatelimiterCountersMode.To(), 111 }, 112 OperationParams: operation.Params( 113 ctx, 114 c.config.OperationTimeout(), 115 c.config.OperationCancelAfter(), 116 operation.ModeSync, 117 ), 118 }, 119 ) 120 121 return xerrors.WithStackTrace(err) 122 } 123 124 func (c *Client) DropNode(ctx context.Context, path string) error { 125 if c == nil { 126 return xerrors.WithStackTrace(errNilClient) 127 } 128 call := func(ctx context.Context) error { 129 return xerrors.WithStackTrace(c.dropNode(ctx, path)) 130 } 131 if !c.config.AutoRetry() { 132 return xerrors.WithStackTrace(call(ctx)) 133 } 134 135 return retry.Retry(ctx, call, 136 retry.WithStackTrace(), 137 retry.WithIdempotent(true), 138 retry.WithTrace(c.config.TraceRetry()), 139 ) 140 } 141 142 func (c *Client) dropNode(ctx context.Context, path string) error { 143 _, err := c.service.DropNode( 144 ctx, 145 &Ydb_Coordination.DropNodeRequest{ 146 Path: path, 147 OperationParams: operation.Params( 148 ctx, 149 c.config.OperationTimeout(), 150 c.config.OperationCancelAfter(), 151 operation.ModeSync, 152 ), 153 }, 154 ) 155 156 return xerrors.WithStackTrace(err) 157 } 158 159 func (c *Client) DescribeNode( 160 ctx context.Context, 161 path string, 162 ) ( 163 entry *scheme.Entry, 164 config *coordination.NodeConfig, 165 _ error, 166 ) { 167 if c == nil { 168 return nil, nil, xerrors.WithStackTrace(errNilClient) 169 } 170 call := func(ctx context.Context) (err error) { 171 entry, config, err = c.describeNode(ctx, path) 172 173 return xerrors.WithStackTrace(err) 174 } 175 if !c.config.AutoRetry() { 176 err := call(ctx) 177 178 return entry, config, xerrors.WithStackTrace(err) 179 } 180 err := retry.Retry(ctx, call, 181 retry.WithStackTrace(), 182 retry.WithIdempotent(true), 183 retry.WithTrace(c.config.TraceRetry()), 184 ) 185 186 return entry, config, xerrors.WithStackTrace(err) 187 } 188 189 // DescribeNode describes a coordination node 190 func (c *Client) describeNode( 191 ctx context.Context, 192 path string, 193 ) ( 194 _ *scheme.Entry, 195 _ *coordination.NodeConfig, 196 err error, 197 ) { 198 var ( 199 response *Ydb_Coordination.DescribeNodeResponse 200 result Ydb_Coordination.DescribeNodeResult 201 ) 202 response, err = c.service.DescribeNode( 203 ctx, 204 &Ydb_Coordination.DescribeNodeRequest{ 205 Path: path, 206 OperationParams: operation.Params( 207 ctx, 208 c.config.OperationTimeout(), 209 c.config.OperationCancelAfter(), 210 operation.ModeSync, 211 ), 212 }, 213 ) 214 if err != nil { 215 return nil, nil, xerrors.WithStackTrace(err) 216 } 217 err = response.GetOperation().GetResult().UnmarshalTo(&result) 218 if err != nil { 219 return nil, nil, xerrors.WithStackTrace(err) 220 } 221 222 return scheme.InnerConvertEntry(result.GetSelf()), &coordination.NodeConfig{ 223 Path: result.GetConfig().GetPath(), 224 SelfCheckPeriodMillis: result.GetConfig().GetSelfCheckPeriodMillis(), 225 SessionGracePeriodMillis: result.GetConfig().GetSessionGracePeriodMillis(), 226 ReadConsistencyMode: consistencyMode(result.GetConfig().GetReadConsistencyMode()), 227 AttachConsistencyMode: consistencyMode(result.GetConfig().GetAttachConsistencyMode()), 228 RatelimiterCountersMode: ratelimiterCountersMode(result.GetConfig().GetRateLimiterCountersMode()), 229 }, nil 230 } 231 232 func (c *Client) Close(ctx context.Context) error { 233 if c == nil { 234 return xerrors.WithStackTrace(errNilClient) 235 } 236 237 return c.close(ctx) 238 } 239 240 func (c *Client) close(context.Context) error { 241 return nil 242 } 243 244 func consistencyMode(t Ydb_Coordination.ConsistencyMode) coordination.ConsistencyMode { 245 switch t { 246 case Ydb_Coordination.ConsistencyMode_CONSISTENCY_MODE_STRICT: 247 return coordination.ConsistencyModeStrict 248 case Ydb_Coordination.ConsistencyMode_CONSISTENCY_MODE_RELAXED: 249 return coordination.ConsistencyModeRelaxed 250 default: 251 return coordination.ConsistencyModeUnset 252 } 253 } 254 255 func ratelimiterCountersMode(t Ydb_Coordination.RateLimiterCountersMode) coordination.RatelimiterCountersMode { 256 switch t { 257 case Ydb_Coordination.RateLimiterCountersMode_RATE_LIMITER_COUNTERS_MODE_AGGREGATED: 258 return coordination.RatelimiterCountersModeAggregated 259 case Ydb_Coordination.RateLimiterCountersMode_RATE_LIMITER_COUNTERS_MODE_DETAILED: 260 return coordination.RatelimiterCountersModeDetailed 261 default: 262 return coordination.RatelimiterCountersModeUnset 263 } 264 }