@@ -6,93 +6,81 @@ import (
66 "path"
77 "strings"
88
9- "github.com/ydb-platform/ydb-go-genproto/protos/Ydb"
10-
11- "github.com/ydb-platform/ydb-go-sdk/v3"
129 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors"
13- "github.com/ydb-platform/ydb-go-sdk/v3/retry"
1410 "github.com/ydb-platform/ydb-go-sdk/v3/scheme"
1511 "github.com/ydb-platform/ydb-go-sdk/v3/table"
12+ "github.com/ydb-platform/ydb-go-sdk/v3/topic"
1613)
1714
1815const (
1916 sysTable = ".sys"
2017)
2118
22- type dbNamer interface {
19+ type dbName interface {
2320 Name () string
2421}
2522
26- type dbSchemer interface {
23+ type dbScheme interface {
2724 Scheme () scheme.Client
2825}
2926
30- type dbTabler interface {
27+ type dbTable interface {
3128 Table () table.Client
3229}
3330
31+ type dbTopic interface {
32+ Topic () topic.Client
33+ }
34+
3435type dbForMakeRecursive interface {
35- dbNamer
36- dbSchemer
36+ dbName
37+ dbScheme
3738}
3839
3940type dbFoRemoveRecursive interface {
40- dbNamer
41- dbSchemer
42- dbTabler
41+ dbName
42+ dbScheme
43+ dbTable
44+ dbTopic
4345}
4446
4547// MakeRecursive creates path inside database
4648// pathToCreate is a database root relative path
4749// MakeRecursive method equal bash command `mkdir -p ~/path/to/create`
4850// where `~` - is a root of database
4951func MakeRecursive (ctx context.Context , db dbForMakeRecursive , pathToCreate string ) error {
50- pathToCreate = path .Join (db .Name (), pathToCreate )
51- for i := len (db .Name ()) + 1 ; i < len (pathToCreate ); i ++ {
52- x := strings .IndexByte (pathToCreate [i :], '/' )
53- if x == - 1 {
54- x = len (pathToCreate [i :]) - 1
55- }
56- i += x
57- var (
58- err error
59- info scheme.Entry
60- sub = pathToCreate [:i + 1 ]
52+ if strings .HasPrefix (pathToCreate , sysTable + "/" ) {
53+ return xerrors .WithStackTrace (
54+ fmt .Errorf ("making directory %q inside system path %q not supported" , pathToCreate , sysTable ),
55+ )
56+ }
57+
58+ absPath := path .Join (db .Name (), pathToCreate )
59+
60+ err := db .Scheme ().MakeDirectory (ctx , absPath )
61+ if err != nil {
62+ return xerrors .WithStackTrace (
63+ fmt .Errorf ("cannot make directory %q: %w" , absPath , err ),
64+ )
65+ }
66+
67+ info , err := db .Scheme ().DescribePath (ctx , absPath )
68+ if err != nil {
69+ return xerrors .WithStackTrace (
70+ fmt .Errorf ("cannot describe path %q: %w" , absPath , err ),
71+ )
72+ }
73+
74+ switch info .Type {
75+ case
76+ scheme .EntryDatabase ,
77+ scheme .EntryDirectory :
78+ return nil
79+ default :
80+ return xerrors .WithStackTrace (
81+ fmt .Errorf ("entry %q exists but it is not a directory: %s" , absPath , info .Type ),
6182 )
62- err = retry .Retry (ctx , func (ctx context.Context ) (err error ) {
63- info , err = db .Scheme ().DescribePath (ctx , sub )
64- return err
65- }, retry .WithIdempotent (true ))
66- if ydb .IsOperationError (err , Ydb .StatusIds_SCHEME_ERROR ) {
67- err = retry .Retry (ctx , func (ctx context.Context ) (err error ) {
68- return db .Scheme ().MakeDirectory (ctx , sub )
69- }, retry .WithIdempotent (true ))
70- if err != nil {
71- return xerrors .WithStackTrace (err )
72- }
73- err = retry .Retry (ctx , func (ctx context.Context ) (err error ) {
74- info , err = db .Scheme ().DescribePath (ctx , sub )
75- return err
76- }, retry .WithIdempotent (true ))
77- if err != nil {
78- return xerrors .WithStackTrace (err )
79- }
80- }
81- if err != nil {
82- return xerrors .WithStackTrace (err )
83- }
84- switch info .Type {
85- case
86- scheme .EntryDatabase ,
87- scheme .EntryDirectory :
88- // OK
89- default :
90- return xerrors .WithStackTrace (fmt .Errorf ("entry %q exists but it is a %s" ,
91- sub , info .Type ,
92- ))
93- }
9483 }
95- return nil
9684}
9785
9886// RemoveRecursive remove selected directory or table names in database.
@@ -103,19 +91,32 @@ func MakeRecursive(ctx context.Context, db dbForMakeRecursive, pathToCreate stri
10391// where `~` - is a root of database
10492func RemoveRecursive (ctx context.Context , db dbFoRemoveRecursive , pathToRemove string ) error {
10593 fullSysTablePath := path .Join (db .Name (), sysTable )
106- var list func (int , string ) error
107- list = func (i int , p string ) error {
108- var dir scheme.Directory
109- var err error
110- err = retry .Retry (ctx , func (ctx context.Context ) (err error ) {
111- dir , err = db .Scheme ().ListDirectory (ctx , p )
112- return xerrors .WithStackTrace (err )
113- }, retry .WithIdempotent (true ))
114- if ydb .IsOperationErrorSchemeError (err ) {
94+ var rmPath func (int , string ) error
95+ rmPath = func (i int , p string ) error {
96+ if exists , err := IsDirectoryExists (ctx , db .Scheme (), p ); err != nil {
97+ return xerrors .WithStackTrace (
98+ fmt .Errorf ("check directory %q exists failed: %w" , p , err ),
99+ )
100+ } else if ! exists {
115101 return nil
116102 }
103+
104+ entry , err := db .Scheme ().DescribePath (ctx , p )
117105 if err != nil {
118- return xerrors .WithStackTrace (err )
106+ return xerrors .WithStackTrace (
107+ fmt .Errorf ("cannot describe path %q: %w" , p , err ),
108+ )
109+ }
110+
111+ if entry .Type != scheme .EntryDirectory {
112+ return nil
113+ }
114+
115+ dir , err := db .Scheme ().ListDirectory (ctx , p )
116+ if err != nil {
117+ return xerrors .WithStackTrace (
118+ fmt .Errorf ("listing directory %q failed: %w" , p , err ),
119+ )
119120 }
120121
121122 for _ , child := range dir .Children {
@@ -125,33 +126,45 @@ func RemoveRecursive(ctx context.Context, db dbFoRemoveRecursive, pathToRemove s
125126 }
126127 switch child .Type {
127128 case scheme .EntryDirectory :
128- if err = list (i + 1 , pt ); err != nil {
129- return xerrors .WithStackTrace (err )
130- }
131- err = db .Scheme ().RemoveDirectory (ctx , pt )
132- if err != nil {
133- return xerrors .WithStackTrace (err )
129+ if err = rmPath (i + 1 , pt ); err != nil {
130+ return xerrors .WithStackTrace (
131+ fmt .Errorf ("recursive removing directory %q failed: %w" , pt , err ),
132+ )
134133 }
135134
136135 case scheme .EntryTable :
137136 err = db .Table ().Do (ctx , func (ctx context.Context , session table.Session ) (err error ) {
138137 return session .DropTable (ctx , pt )
139138 }, table .WithIdempotent ())
140139 if err != nil {
141- return xerrors .WithStackTrace (err )
140+ return xerrors .WithStackTrace (
141+ fmt .Errorf ("removing table %q failed: %w" , pt , err ),
142+ )
142143 }
143144
144145 case scheme .EntryTopic :
145146 err = db .Topic ().Drop (ctx , pt )
146147 if err != nil {
147- return xerrors .WithStackTrace (err )
148+ return xerrors .WithStackTrace (
149+ fmt .Errorf ("removing topic %q failed: %w" , pt , err ),
150+ )
148151 }
149152
150153 default :
151- return xerrors .WithStackTrace (fmt .Errorf ("unknown entry type: %s" , child .Type .String ()))
154+ return xerrors .WithStackTrace (
155+ fmt .Errorf ("unknown entry type: %s" , child .Type .String ()),
156+ )
152157 }
153158 }
159+
160+ err = db .Scheme ().RemoveDirectory (ctx , p )
161+ if err != nil {
162+ return xerrors .WithStackTrace (
163+ fmt .Errorf ("removing directory %q failed: %w" , p , err ),
164+ )
165+ }
166+
154167 return nil
155168 }
156- return list (0 , path .Join (db .Name (), pathToRemove ))
169+ return rmPath (0 , path .Join (db .Name (), pathToRemove ))
157170}
0 commit comments