clientV3: fix behavior of WithPrefix and WithFromKey functions
The use of WithPrefix() and WithFromKey() together is not supported. The client doesn't respect this behavior currently. Fixes #10431
This commit is contained in:
@ -218,6 +218,10 @@ func (op Op) isWrite() bool {
|
|||||||
|
|
||||||
// OpGet returns "get" operation based on given key and operation options.
|
// OpGet returns "get" operation based on given key and operation options.
|
||||||
func OpGet(key string, opts ...OpOption) Op {
|
func OpGet(key string, opts ...OpOption) Op {
|
||||||
|
// WithPrefix and WithFromKey are not supported together
|
||||||
|
if isWithPrefix(opts) && isWithFromKey(opts) {
|
||||||
|
panic("`WithPrefix` and `WithFromKey` cannot be set at the same time, choose one")
|
||||||
|
}
|
||||||
ret := Op{t: tRange, key: []byte(key)}
|
ret := Op{t: tRange, key: []byte(key)}
|
||||||
ret.applyOpts(opts)
|
ret.applyOpts(opts)
|
||||||
return ret
|
return ret
|
||||||
@ -225,6 +229,10 @@ func OpGet(key string, opts ...OpOption) Op {
|
|||||||
|
|
||||||
// OpDelete returns "delete" operation based on given key and operation options.
|
// OpDelete returns "delete" operation based on given key and operation options.
|
||||||
func OpDelete(key string, opts ...OpOption) Op {
|
func OpDelete(key string, opts ...OpOption) Op {
|
||||||
|
// WithPrefix and WithFromKey are not supported together
|
||||||
|
if isWithPrefix(opts) && isWithFromKey(opts) {
|
||||||
|
panic("`WithPrefix` and `WithFromKey` cannot be set at the same time, choose one")
|
||||||
|
}
|
||||||
ret := Op{t: tDeleteRange, key: []byte(key)}
|
ret := Op{t: tDeleteRange, key: []byte(key)}
|
||||||
ret.applyOpts(opts)
|
ret.applyOpts(opts)
|
||||||
switch {
|
switch {
|
||||||
@ -544,3 +552,9 @@ func toLeaseTimeToLiveRequest(id LeaseID, opts ...LeaseOption) *pb.LeaseTimeToLi
|
|||||||
ret.applyOpts(opts)
|
ret.applyOpts(opts)
|
||||||
return &pb.LeaseTimeToLiveRequest{ID: int64(id), Keys: ret.attachedKeys}
|
return &pb.LeaseTimeToLiveRequest{ID: int64(id), Keys: ret.attachedKeys}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isWithPrefix returns true if WithPrefix is being called in the op
|
||||||
|
func isWithPrefix(opts []OpOption) bool { return isOpFuncCalled("WithPrefix", opts) }
|
||||||
|
|
||||||
|
// isWithFromKey returns true if WithFromKey is being called in the op
|
||||||
|
func isWithFromKey(opts []OpOption) bool { return isOpFuncCalled("WithFromKey", opts) }
|
||||||
|
@ -16,6 +16,9 @@ package clientv3
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -29,3 +32,18 @@ func jitterUp(duration time.Duration, jitter float64) time.Duration {
|
|||||||
multiplier := jitter * (rand.Float64()*2 - 1)
|
multiplier := jitter * (rand.Float64()*2 - 1)
|
||||||
return time.Duration(float64(duration) * (1 + multiplier))
|
return time.Duration(float64(duration) * (1 + multiplier))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if the provided function is being called in the op options.
|
||||||
|
func isOpFuncCalled(op string, opts []OpOption) bool {
|
||||||
|
for _, opt := range opts {
|
||||||
|
v := reflect.ValueOf(opt)
|
||||||
|
if v.Kind() == reflect.Func {
|
||||||
|
if opFunc := runtime.FuncForPC(v.Pointer()); opFunc != nil {
|
||||||
|
if strings.Contains(opFunc.Name(), op) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user