github.com/ydb-platform/ydb-go-sdk/v3@v3.89.2/internal/scheme/client.go (about) 1 package scheme 2 3 import ( 4 "context" 5 "errors" 6 7 "github.com/ydb-platform/ydb-go-genproto/Ydb_Scheme_V1" 8 "github.com/ydb-platform/ydb-go-genproto/protos/Ydb_Scheme" 9 "google.golang.org/grpc" 10 11 "github.com/ydb-platform/ydb-go-sdk/v3/internal/operation" 12 "github.com/ydb-platform/ydb-go-sdk/v3/internal/scheme/config" 13 "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack" 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 "github.com/ydb-platform/ydb-go-sdk/v3/trace" 18 ) 19 20 //nolint:gofumpt 21 //nolint:nolintlint 22 var errNilClient = xerrors.Wrap(errors.New("scheme client is not initialized")) 23 24 type Client struct { 25 config *config.Config 26 service Ydb_Scheme_V1.SchemeServiceClient 27 } 28 29 func (c *Client) Database() string { 30 return c.config.Database() 31 } 32 33 func (c *Client) Close(_ context.Context) error { 34 if c == nil { 35 return xerrors.WithStackTrace(errNilClient) 36 } 37 38 return nil 39 } 40 41 func New(ctx context.Context, cc grpc.ClientConnInterface, config *config.Config) *Client { 42 return &Client{ 43 config: config, 44 service: Ydb_Scheme_V1.NewSchemeServiceClient(cc), 45 } 46 } 47 48 func (c *Client) MakeDirectory(ctx context.Context, path string) (finalErr error) { 49 onDone := trace.SchemeOnMakeDirectory(c.config.Trace(), &ctx, 50 stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/scheme.(*Client).MakeDirectory"), 51 path, 52 ) 53 defer func() { 54 onDone(finalErr) 55 }() 56 call := func(ctx context.Context) error { 57 return xerrors.WithStackTrace(c.makeDirectory(ctx, path)) 58 } 59 if !c.config.AutoRetry() { 60 return call(ctx) 61 } 62 63 return retry.Retry(ctx, call, 64 retry.WithStackTrace(), 65 retry.WithIdempotent(true), 66 retry.WithTrace(c.config.TraceRetry()), 67 retry.WithBudget(c.config.RetryBudget()), 68 ) 69 } 70 71 func (c *Client) makeDirectory(ctx context.Context, path string) (err error) { 72 _, err = c.service.MakeDirectory( 73 ctx, 74 &Ydb_Scheme.MakeDirectoryRequest{ 75 Path: path, 76 OperationParams: operation.Params( 77 ctx, 78 c.config.OperationTimeout(), 79 c.config.OperationCancelAfter(), 80 operation.ModeSync, 81 ), 82 }, 83 ) 84 85 return xerrors.WithStackTrace(err) 86 } 87 88 func (c *Client) RemoveDirectory(ctx context.Context, path string) (finalErr error) { 89 onDone := trace.SchemeOnRemoveDirectory(c.config.Trace(), &ctx, 90 stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/scheme.(*Client).RemoveDirectory"), 91 path, 92 ) 93 defer func() { 94 onDone(finalErr) 95 }() 96 call := func(ctx context.Context) error { 97 return xerrors.WithStackTrace(c.removeDirectory(ctx, path)) 98 } 99 if !c.config.AutoRetry() { 100 return call(ctx) 101 } 102 103 return retry.Retry(ctx, call, 104 retry.WithStackTrace(), 105 retry.WithIdempotent(true), 106 retry.WithTrace(c.config.TraceRetry()), 107 retry.WithBudget(c.config.RetryBudget()), 108 ) 109 } 110 111 func (c *Client) removeDirectory(ctx context.Context, path string) (err error) { 112 _, err = c.service.RemoveDirectory( 113 ctx, 114 &Ydb_Scheme.RemoveDirectoryRequest{ 115 Path: path, 116 OperationParams: operation.Params( 117 ctx, 118 c.config.OperationTimeout(), 119 c.config.OperationCancelAfter(), 120 operation.ModeSync, 121 ), 122 }, 123 ) 124 125 return xerrors.WithStackTrace(err) 126 } 127 128 func (c *Client) ListDirectory(ctx context.Context, path string) (d scheme.Directory, finalErr error) { 129 onDone := trace.SchemeOnListDirectory(c.config.Trace(), &ctx, 130 stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/scheme.(*Client).ListDirectory"), 131 ) 132 defer func() { 133 onDone(finalErr) 134 }() 135 call := func(ctx context.Context) (err error) { 136 d, err = c.listDirectory(ctx, path) 137 138 return xerrors.WithStackTrace(err) 139 } 140 if !c.config.AutoRetry() { 141 err := call(ctx) 142 143 return d, xerrors.WithStackTrace(err) 144 } 145 err := retry.Retry(ctx, call, 146 retry.WithIdempotent(true), 147 retry.WithStackTrace(), 148 retry.WithTrace(c.config.TraceRetry()), 149 retry.WithBudget(c.config.RetryBudget()), 150 ) 151 152 return d, xerrors.WithStackTrace(err) 153 } 154 155 func (c *Client) listDirectory(ctx context.Context, path string) (scheme.Directory, error) { 156 var ( 157 d scheme.Directory 158 err error 159 response *Ydb_Scheme.ListDirectoryResponse 160 result Ydb_Scheme.ListDirectoryResult 161 ) 162 response, err = c.service.ListDirectory( 163 ctx, 164 &Ydb_Scheme.ListDirectoryRequest{ 165 Path: path, 166 OperationParams: operation.Params( 167 ctx, 168 c.config.OperationTimeout(), 169 c.config.OperationCancelAfter(), 170 operation.ModeSync, 171 ), 172 }, 173 ) 174 if err != nil { 175 return d, xerrors.WithStackTrace(err) 176 } 177 err = response.GetOperation().GetResult().UnmarshalTo(&result) 178 if err != nil { 179 return d, xerrors.WithStackTrace(err) 180 } 181 d.From(result.GetSelf()) 182 d.Children = make([]scheme.Entry, len(result.GetChildren())) 183 putEntry(d.Children, result.GetChildren()) 184 185 return d, nil 186 } 187 188 func (c *Client) DescribePath(ctx context.Context, path string) (e scheme.Entry, finalErr error) { 189 onDone := trace.SchemeOnDescribePath(c.config.Trace(), &ctx, 190 stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/scheme.(*Client).DescribePath"), 191 path, 192 ) 193 defer func() { 194 onDone(e.Type.String(), finalErr) 195 }() 196 call := func(ctx context.Context) (err error) { 197 e, err = c.describePath(ctx, path) 198 if err != nil { 199 return xerrors.WithStackTrace(err) 200 } 201 202 return nil 203 } 204 if !c.config.AutoRetry() { 205 err := call(ctx) 206 207 return e, err 208 } 209 err := retry.Retry(ctx, call, 210 retry.WithIdempotent(true), 211 retry.WithStackTrace(), 212 retry.WithTrace(c.config.TraceRetry()), 213 retry.WithBudget(c.config.RetryBudget()), 214 ) 215 216 return e, xerrors.WithStackTrace(err) 217 } 218 219 func (c *Client) describePath(ctx context.Context, path string) (e scheme.Entry, err error) { 220 var ( 221 response *Ydb_Scheme.DescribePathResponse 222 result Ydb_Scheme.DescribePathResult 223 ) 224 response, err = c.service.DescribePath( 225 ctx, 226 &Ydb_Scheme.DescribePathRequest{ 227 Path: path, 228 OperationParams: operation.Params( 229 ctx, 230 c.config.OperationTimeout(), 231 c.config.OperationCancelAfter(), 232 operation.ModeSync, 233 ), 234 }, 235 ) 236 if err != nil { 237 return e, xerrors.WithStackTrace(err) 238 } 239 err = response.GetOperation().GetResult().UnmarshalTo(&result) 240 if err != nil { 241 return e, xerrors.WithStackTrace(err) 242 } 243 e.From(result.GetSelf()) 244 245 return e, nil 246 } 247 248 func (c *Client) ModifyPermissions( 249 ctx context.Context, path string, opts ...scheme.PermissionsOption, 250 ) (finalErr error) { 251 onDone := trace.SchemeOnModifyPermissions(c.config.Trace(), &ctx, 252 stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/scheme.(*Client).ModifyPermissions"), 253 path, 254 ) 255 defer func() { 256 onDone(finalErr) 257 }() 258 var desc permissionsDesc 259 for _, opt := range opts { 260 if opt != nil { 261 opt(&desc) 262 } 263 } 264 call := func(ctx context.Context) error { 265 return xerrors.WithStackTrace(c.modifyPermissions(ctx, path, desc)) 266 } 267 if !c.config.AutoRetry() { 268 return call(ctx) 269 } 270 271 return retry.Retry(ctx, call, 272 retry.WithStackTrace(), 273 retry.WithIdempotent(true), 274 retry.WithTrace(c.config.TraceRetry()), 275 retry.WithBudget(c.config.RetryBudget()), 276 ) 277 } 278 279 func (c *Client) modifyPermissions(ctx context.Context, path string, desc permissionsDesc) (err error) { 280 _, err = c.service.ModifyPermissions( 281 ctx, 282 &Ydb_Scheme.ModifyPermissionsRequest{ 283 Path: path, 284 Actions: desc.actions, 285 ClearPermissions: desc.clear, 286 OperationParams: operation.Params( 287 ctx, 288 c.config.OperationTimeout(), 289 c.config.OperationCancelAfter(), 290 operation.ModeSync, 291 ), 292 }, 293 ) 294 if err != nil { 295 return xerrors.WithStackTrace(err) 296 } 297 298 return nil 299 } 300 301 func putEntry(dst []scheme.Entry, src []*Ydb_Scheme.Entry) { 302 for i, e := range src { 303 (dst[i]).From(e) 304 } 305 }