@@ -7,9 +7,10 @@ import (
77 "time"
88
99 "github.com/google/uuid"
10- "github.com/mitchellh/mapstructure"
1110 "github.com/tarantool/go-tarantool/v2"
1211 "github.com/tarantool/go-tarantool/v2/pool"
12+ "github.com/vmihailenco/msgpack/v5"
13+ "github.com/vmihailenco/msgpack/v5/msgpcode"
1314)
1415
1516type ReplicasetInfo struct {
@@ -51,41 +52,71 @@ func (rs *Replicaset) bucketStatAsync(ctx context.Context, bucketID uint64) *tar
5152 return rs .CallAsync (ctx , ReplicasetCallOpts {PoolMode : pool .RO }, bucketStatFnc , []interface {}{bucketID })
5253}
5354
54- func bucketStatWait (future * tarantool.Future ) (BucketStatInfo , error ) {
55- var bsInfo BucketStatInfo
55+ type vshardStorageBucketStatResponseProto struct {
56+ ok bool
57+ info BucketStatInfo
58+ err StorageCallVShardError
59+ }
5660
57- respData , err := future .Get ()
61+ func (r * vshardStorageBucketStatResponseProto ) DecodeMsgpack (d * msgpack.Decoder ) error {
62+ // bucket_stat returns pair: stat, err
63+ // https://github.com/tarantool/vshard/blob/e1c806e1d3d2ce8a4e6b4d498c09051bf34ab92a/vshard/storage/init.lua#L1413
64+
65+ respArrayLen , err := d .DecodeArrayLen ()
5866 if err != nil {
59- return bsInfo , err
67+ return err
6068 }
6169
62- if len ( respData ) == 0 {
63- return bsInfo , fmt .Errorf ("protocol violation bucketStatWait: empty response" )
70+ if respArrayLen == 0 {
71+ return fmt .Errorf ("protocol violation bucketStatWait: empty response" )
6472 }
6573
66- if respData [0 ] == nil {
67- if len (respData ) != 2 {
68- return bsInfo , fmt .Errorf ("protocol violation bucketStatWait: invalid response length %d when respData[0] is nil" , len (respData ))
74+ code , err := d .PeekCode ()
75+ if err != nil {
76+ return err
77+ }
78+
79+ if code == msgpcode .Nil {
80+ err = d .DecodeNil ()
81+ if err != nil {
82+ return err
83+ }
84+
85+ if respArrayLen != 2 {
86+ return fmt .Errorf ("protocol violation bucketStatWait: length is %d on vshard error case" , respArrayLen )
6987 }
7088
71- var bsError bucketStatError
72- err = mapstructure .Decode (respData [1 ], & bsError )
89+ err = d .Decode (& r .err )
7390 if err != nil {
74- // We could not decode respData[1] as bsError, so return respData[1] as is, add info why we could not decode.
75- return bsInfo , fmt .Errorf ("bucketStatWait error: %v (can't decode into bsError: %v)" , respData [1 ], err )
91+ return fmt .Errorf ("failed to decode storage vshard error: %w" , err )
7692 }
7793
78- return bsInfo , bsError
94+ return nil
7995 }
8096
81- // A problem with key-code 1
82- // todo: fix after https://github.com/tarantool/go-tarantool/issues/368
83- err = mapstructure .Decode (respData [0 ], & bsInfo )
97+ err = d .Decode (& r .info )
8498 if err != nil {
85- return bsInfo , fmt .Errorf ("can't decode bsInfo: %w" , err )
99+ return fmt .Errorf ("failed to decode bucket stat info: %w" , err )
100+ }
101+
102+ r .ok = true
103+
104+ return nil
105+ }
106+
107+ func bucketStatWait (future * tarantool.Future ) (BucketStatInfo , error ) {
108+ var bucketStatResponse vshardStorageBucketStatResponseProto
109+
110+ err := future .GetTyped (& bucketStatResponse )
111+ if err != nil {
112+ return BucketStatInfo {}, err
113+ }
114+
115+ if ! bucketStatResponse .ok {
116+ return BucketStatInfo {}, bucketStatResponse .err
86117 }
87118
88- return bsInfo , nil
119+ return bucketStatResponse . info , nil
89120}
90121
91122// ReplicaCall perform function on remote storage
0 commit comments