mirror of
https://github.com/EchoVault/SugarDB.git
synced 2025-09-29 13:22:10 +08:00
Added ZRemRangeByLex and ZRemRangeByRank to embedded API.
This commit is contained in:
3
Makefile
3
Makefile
@@ -14,7 +14,8 @@ build:
|
|||||||
env CGO_ENABLED=1 CC=x86_64-linux-musl-gcc GOOS=linux GOARCH=amd64 DEST=bin/linux/x86_64 make build-server
|
env CGO_ENABLED=1 CC=x86_64-linux-musl-gcc GOOS=linux GOARCH=amd64 DEST=bin/linux/x86_64 make build-server
|
||||||
|
|
||||||
run:
|
run:
|
||||||
make build && docker-compose up --build
|
make build && \
|
||||||
|
docker-compose up --build
|
||||||
|
|
||||||
test-unit:
|
test-unit:
|
||||||
env RACE=false OUT=internal/modules/admin/testdata make build-modules-test && \
|
env RACE=false OUT=internal/modules/admin/testdata make build-modules-test && \
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -17,6 +17,7 @@ package echovault
|
|||||||
import (
|
import (
|
||||||
"github.com/echovault/echovault/internal"
|
"github.com/echovault/echovault/internal"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetOptions modifies the behaviour for the Set command
|
// SetOptions modifies the behaviour for the Set command
|
||||||
@@ -124,12 +125,12 @@ func (server *EchoVault) Set(key, value string, options SetOptions) (string, err
|
|||||||
//
|
//
|
||||||
// `kvPairs` - map[string]string - a map representing all the keys and values to be set.
|
// `kvPairs` - map[string]string - a map representing all the keys and values to be set.
|
||||||
//
|
//
|
||||||
// Returns: "OK" if the set is successful.
|
// Returns: true if the set is successful.
|
||||||
//
|
//
|
||||||
// Errors:
|
// Errors:
|
||||||
//
|
//
|
||||||
// "key <key> does already exists" - when the NX flag is set to true and the key already exists.
|
// "key <key> already exists" - when the NX flag is set to true and the key already exists.
|
||||||
func (server *EchoVault) MSet(kvPairs map[string]string) (string, error) {
|
func (server *EchoVault) MSet(kvPairs map[string]string) (bool, error) {
|
||||||
cmd := []string{"MSET"}
|
cmd := []string{"MSET"}
|
||||||
|
|
||||||
for k, v := range kvPairs {
|
for k, v := range kvPairs {
|
||||||
@@ -138,10 +139,15 @@ func (server *EchoVault) MSet(kvPairs map[string]string) (string, error) {
|
|||||||
|
|
||||||
b, err := server.handleCommand(server.context, internal.EncodeCommand(cmd), nil, false, true)
|
b, err := server.handleCommand(server.context, internal.EncodeCommand(cmd), nil, false, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return internal.ParseStringResponse(b)
|
s, err := internal.ParseStringResponse(b)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.EqualFold(s, "ok"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get retrieves the value at the provided key.
|
// Get retrieves the value at the provided key.
|
||||||
@@ -279,7 +285,7 @@ func (server *EchoVault) PTTL(key string) (int, error) {
|
|||||||
// `options` - ExpireOptions
|
// `options` - ExpireOptions
|
||||||
//
|
//
|
||||||
// Returns: true if the key's expiry was successfully updated.
|
// Returns: true if the key's expiry was successfully updated.
|
||||||
func (server *EchoVault) Expire(key string, seconds int, options ExpireOptions) (int, error) {
|
func (server *EchoVault) Expire(key string, seconds int, options ExpireOptions) (bool, error) {
|
||||||
cmd := []string{"EXPIRE", key, strconv.Itoa(seconds)}
|
cmd := []string{"EXPIRE", key, strconv.Itoa(seconds)}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
@@ -295,10 +301,10 @@ func (server *EchoVault) Expire(key string, seconds int, options ExpireOptions)
|
|||||||
|
|
||||||
b, err := server.handleCommand(server.context, internal.EncodeCommand(cmd), nil, false, true)
|
b, err := server.handleCommand(server.context, internal.EncodeCommand(cmd), nil, false, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return internal.ParseIntegerResponse(b)
|
return internal.ParseBooleanResponse(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PExpire set the given key's expiry in milliseconds from now.
|
// PExpire set the given key's expiry in milliseconds from now.
|
||||||
@@ -313,7 +319,7 @@ func (server *EchoVault) Expire(key string, seconds int, options ExpireOptions)
|
|||||||
// `options` - PExpireOptions
|
// `options` - PExpireOptions
|
||||||
//
|
//
|
||||||
// Returns: true if the key's expiry was successfully updated.
|
// Returns: true if the key's expiry was successfully updated.
|
||||||
func (server *EchoVault) PExpire(key string, milliseconds int, options PExpireOptions) (int, error) {
|
func (server *EchoVault) PExpire(key string, milliseconds int, options PExpireOptions) (bool, error) {
|
||||||
cmd := []string{"PEXPIRE", key, strconv.Itoa(milliseconds)}
|
cmd := []string{"PEXPIRE", key, strconv.Itoa(milliseconds)}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
@@ -329,10 +335,10 @@ func (server *EchoVault) PExpire(key string, milliseconds int, options PExpireOp
|
|||||||
|
|
||||||
b, err := server.handleCommand(server.context, internal.EncodeCommand(cmd), nil, false, true)
|
b, err := server.handleCommand(server.context, internal.EncodeCommand(cmd), nil, false, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return internal.ParseIntegerResponse(b)
|
return internal.ParseBooleanResponse(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExpireAt set the given key's expiry in unix epoch seconds.
|
// ExpireAt set the given key's expiry in unix epoch seconds.
|
||||||
|
@@ -80,7 +80,7 @@ func TestEchoVault_EXPIRE(t *testing.T) {
|
|||||||
time int
|
time int
|
||||||
expireOpts ExpireOptions
|
expireOpts ExpireOptions
|
||||||
pexpireOpts PExpireOptions
|
pexpireOpts PExpireOptions
|
||||||
want int
|
want bool
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
@@ -92,7 +92,7 @@ func TestEchoVault_EXPIRE(t *testing.T) {
|
|||||||
presetValues: map[string]internal.KeyData{
|
presetValues: map[string]internal.KeyData{
|
||||||
"key1": {Value: "value1", ExpireAt: time.Time{}},
|
"key1": {Value: "value1", ExpireAt: time.Time{}},
|
||||||
},
|
},
|
||||||
want: 1,
|
want: true,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -104,7 +104,7 @@ func TestEchoVault_EXPIRE(t *testing.T) {
|
|||||||
presetValues: map[string]internal.KeyData{
|
presetValues: map[string]internal.KeyData{
|
||||||
"key2": {Value: "value2", ExpireAt: time.Time{}},
|
"key2": {Value: "value2", ExpireAt: time.Time{}},
|
||||||
},
|
},
|
||||||
want: 1,
|
want: true,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -116,11 +116,11 @@ func TestEchoVault_EXPIRE(t *testing.T) {
|
|||||||
presetValues: map[string]internal.KeyData{
|
presetValues: map[string]internal.KeyData{
|
||||||
"key3": {Value: "value3", ExpireAt: time.Time{}},
|
"key3": {Value: "value3", ExpireAt: time.Time{}},
|
||||||
},
|
},
|
||||||
want: 1,
|
want: true,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Return 0 when NX flag is provided and key already has an expiry time",
|
name: "Return false when NX flag is provided and key already has an expiry time",
|
||||||
cmd: "EXPIRE",
|
cmd: "EXPIRE",
|
||||||
key: "key4",
|
key: "key4",
|
||||||
time: 1000,
|
time: 1000,
|
||||||
@@ -128,7 +128,7 @@ func TestEchoVault_EXPIRE(t *testing.T) {
|
|||||||
presetValues: map[string]internal.KeyData{
|
presetValues: map[string]internal.KeyData{
|
||||||
"key4": {Value: "value4", ExpireAt: mockClock.Now().Add(1000 * time.Second)},
|
"key4": {Value: "value4", ExpireAt: mockClock.Now().Add(1000 * time.Second)},
|
||||||
},
|
},
|
||||||
want: 0,
|
want: false,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -140,11 +140,11 @@ func TestEchoVault_EXPIRE(t *testing.T) {
|
|||||||
presetValues: map[string]internal.KeyData{
|
presetValues: map[string]internal.KeyData{
|
||||||
"key5": {Value: "value5", ExpireAt: mockClock.Now().Add(30 * time.Second)},
|
"key5": {Value: "value5", ExpireAt: mockClock.Now().Add(30 * time.Second)},
|
||||||
},
|
},
|
||||||
want: 1,
|
want: true,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Return 0 when key does not have an expiry and the XX flag is provided",
|
name: "Return false when key does not have an expiry and the XX flag is provided",
|
||||||
cmd: "EXPIRE",
|
cmd: "EXPIRE",
|
||||||
time: 1000,
|
time: 1000,
|
||||||
expireOpts: ExpireOptions{XX: true},
|
expireOpts: ExpireOptions{XX: true},
|
||||||
@@ -152,7 +152,7 @@ func TestEchoVault_EXPIRE(t *testing.T) {
|
|||||||
presetValues: map[string]internal.KeyData{
|
presetValues: map[string]internal.KeyData{
|
||||||
"key6": {Value: "value6", ExpireAt: time.Time{}},
|
"key6": {Value: "value6", ExpireAt: time.Time{}},
|
||||||
},
|
},
|
||||||
want: 0,
|
want: false,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -164,11 +164,11 @@ func TestEchoVault_EXPIRE(t *testing.T) {
|
|||||||
presetValues: map[string]internal.KeyData{
|
presetValues: map[string]internal.KeyData{
|
||||||
"key7": {Value: "value7", ExpireAt: mockClock.Now().Add(30 * time.Second)},
|
"key7": {Value: "value7", ExpireAt: mockClock.Now().Add(30 * time.Second)},
|
||||||
},
|
},
|
||||||
want: 1,
|
want: true,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Return 0 when GT flag is passed and current expiry time is greater than provided time",
|
name: "Return false when GT flag is passed and current expiry time is greater than provided time",
|
||||||
cmd: "EXPIRE",
|
cmd: "EXPIRE",
|
||||||
key: "key8",
|
key: "key8",
|
||||||
time: 1000,
|
time: 1000,
|
||||||
@@ -176,11 +176,11 @@ func TestEchoVault_EXPIRE(t *testing.T) {
|
|||||||
presetValues: map[string]internal.KeyData{
|
presetValues: map[string]internal.KeyData{
|
||||||
"key8": {Value: "value8", ExpireAt: mockClock.Now().Add(3000 * time.Second)},
|
"key8": {Value: "value8", ExpireAt: mockClock.Now().Add(3000 * time.Second)},
|
||||||
},
|
},
|
||||||
want: 0,
|
want: false,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Return 0 when GT flag is passed and key does not have an expiry time",
|
name: "Return false when GT flag is passed and key does not have an expiry time",
|
||||||
cmd: "EXPIRE",
|
cmd: "EXPIRE",
|
||||||
key: "key9",
|
key: "key9",
|
||||||
time: 1000,
|
time: 1000,
|
||||||
@@ -188,7 +188,7 @@ func TestEchoVault_EXPIRE(t *testing.T) {
|
|||||||
presetValues: map[string]internal.KeyData{
|
presetValues: map[string]internal.KeyData{
|
||||||
"key9": {Value: "value9", ExpireAt: time.Time{}},
|
"key9": {Value: "value9", ExpireAt: time.Time{}},
|
||||||
},
|
},
|
||||||
want: 0,
|
want: false,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -200,11 +200,11 @@ func TestEchoVault_EXPIRE(t *testing.T) {
|
|||||||
presetValues: map[string]internal.KeyData{
|
presetValues: map[string]internal.KeyData{
|
||||||
"key10": {Value: "value10", ExpireAt: mockClock.Now().Add(3000 * time.Second)},
|
"key10": {Value: "value10", ExpireAt: mockClock.Now().Add(3000 * time.Second)},
|
||||||
},
|
},
|
||||||
want: 1,
|
want: true,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Return 0 when LT flag is passed and current expiry time is less than provided time",
|
name: "Return false when LT flag is passed and current expiry time is less than provided time",
|
||||||
cmd: "EXPIRE",
|
cmd: "EXPIRE",
|
||||||
key: "key11",
|
key: "key11",
|
||||||
time: 50000,
|
time: 50000,
|
||||||
@@ -212,7 +212,7 @@ func TestEchoVault_EXPIRE(t *testing.T) {
|
|||||||
presetValues: map[string]internal.KeyData{
|
presetValues: map[string]internal.KeyData{
|
||||||
"key11": {Value: "value11", ExpireAt: mockClock.Now().Add(30 * time.Second)},
|
"key11": {Value: "value11", ExpireAt: mockClock.Now().Add(30 * time.Second)},
|
||||||
},
|
},
|
||||||
want: 0,
|
want: false,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -223,7 +223,7 @@ func TestEchoVault_EXPIRE(t *testing.T) {
|
|||||||
presetKeyData(server, context.Background(), k, d)
|
presetKeyData(server, context.Background(), k, d)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var got int
|
var got bool
|
||||||
var err error
|
var err error
|
||||||
if strings.EqualFold(tt.cmd, "PEXPIRE") {
|
if strings.EqualFold(tt.cmd, "PEXPIRE") {
|
||||||
got, err = server.PExpire(tt.key, tt.time, tt.pexpireOpts)
|
got, err = server.PExpire(tt.key, tt.time, tt.pexpireOpts)
|
||||||
@@ -752,13 +752,13 @@ func TestEchoVault_MSET(t *testing.T) {
|
|||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
kvPairs map[string]string
|
kvPairs map[string]string
|
||||||
want string
|
want bool
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Set multiple keys",
|
name: "Set multiple keys",
|
||||||
kvPairs: map[string]string{"key1": "value1", "key2": "10", "key3": "3.142"},
|
kvPairs: map[string]string{"key1": "value1", "key2": "10", "key3": "3.142"},
|
||||||
want: "OK",
|
want: true,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@@ -87,6 +87,8 @@ type ZMPopOptions struct {
|
|||||||
//
|
//
|
||||||
// ByLex returns the elements within the lexicographical ranges specified.
|
// ByLex returns the elements within the lexicographical ranges specified.
|
||||||
//
|
//
|
||||||
|
// Rev reverses the result from the previous filters.
|
||||||
|
//
|
||||||
// Offset specifies the offset to from which to start the ZRange process.
|
// Offset specifies the offset to from which to start the ZRange process.
|
||||||
//
|
//
|
||||||
// Count specifies the number of elements to return.
|
// Count specifies the number of elements to return.
|
||||||
@@ -94,6 +96,7 @@ type ZRangeOptions struct {
|
|||||||
WithScores bool
|
WithScores bool
|
||||||
ByScore bool
|
ByScore bool
|
||||||
ByLex bool
|
ByLex bool
|
||||||
|
Rev bool
|
||||||
Offset uint
|
Offset uint
|
||||||
Count uint
|
Count uint
|
||||||
}
|
}
|
||||||
@@ -864,6 +867,62 @@ func (server *EchoVault) ZRemRangeByScore(key string, min float64, max float64)
|
|||||||
return internal.ParseIntegerResponse(b)
|
return internal.ParseIntegerResponse(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ZRemRangeByLex Removes the elements that are lexicographically between min and max.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
//
|
||||||
|
// `key` - string - The keys to the sorted set.
|
||||||
|
//
|
||||||
|
// `min` - string - The minimum lexicographic boundary.
|
||||||
|
//
|
||||||
|
// `max` - string - The maximum lexicographic boundary.
|
||||||
|
//
|
||||||
|
// Returns: The number of elements that were successfully removed.
|
||||||
|
//
|
||||||
|
// Errors:
|
||||||
|
//
|
||||||
|
// "value at <key> is not a sorted set" - when a key exists but is not a sorted set.
|
||||||
|
func (server *EchoVault) ZRemRangeByLex(key, min, max string) (int, error) {
|
||||||
|
b, err := server.handleCommand(
|
||||||
|
server.context, internal.EncodeCommand([]string{"ZREMRANGEBYLEX", key, min, max}),
|
||||||
|
nil,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return internal.ParseIntegerResponse(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZRemRangeByRank Removes the elements that are ranked between min and max.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
//
|
||||||
|
// `key` - string - The keys to the sorted set.
|
||||||
|
//
|
||||||
|
// `min` - int - The minimum rank boundary.
|
||||||
|
//
|
||||||
|
// `max` - int - The maximum rank boundary.
|
||||||
|
//
|
||||||
|
// Returns: The number of elements that were successfully removed.
|
||||||
|
//
|
||||||
|
// Errors:
|
||||||
|
//
|
||||||
|
// "value at <key> is not a sorted set" - when a key exists but is not a sorted set.
|
||||||
|
func (server *EchoVault) ZRemRangeByRank(key string, min, max int) (int, error) {
|
||||||
|
b, err := server.handleCommand(
|
||||||
|
server.context, internal.EncodeCommand([]string{"ZREMRANGEBYRANK", key, strconv.Itoa(min), strconv.Itoa(max)}),
|
||||||
|
nil,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return internal.ParseIntegerResponse(b)
|
||||||
|
}
|
||||||
|
|
||||||
// ZRange Returns the range of elements in the sorted set.
|
// ZRange Returns the range of elements in the sorted set.
|
||||||
//
|
//
|
||||||
// Parameters:
|
// Parameters:
|
||||||
@@ -889,6 +948,8 @@ func (server *EchoVault) ZRange(key, start, stop string, options ZRangeOptions)
|
|||||||
cmd = append(cmd, "BYSCORE")
|
cmd = append(cmd, "BYSCORE")
|
||||||
case options.ByLex:
|
case options.ByLex:
|
||||||
cmd = append(cmd, "BYLEX")
|
cmd = append(cmd, "BYLEX")
|
||||||
|
case options.Rev:
|
||||||
|
cmd = append(cmd, "REV")
|
||||||
default:
|
default:
|
||||||
cmd = append(cmd, "BYSCORE")
|
cmd = append(cmd, "BYSCORE")
|
||||||
}
|
}
|
||||||
@@ -941,6 +1002,8 @@ func (server *EchoVault) ZRangeStore(destination, source, start, stop string, op
|
|||||||
cmd = append(cmd, "BYSCORE")
|
cmd = append(cmd, "BYSCORE")
|
||||||
case options.ByLex:
|
case options.ByLex:
|
||||||
cmd = append(cmd, "BYLEX")
|
cmd = append(cmd, "BYLEX")
|
||||||
|
case options.Rev:
|
||||||
|
cmd = append(cmd, "REV")
|
||||||
default:
|
default:
|
||||||
cmd = append(cmd, "BYSCORE")
|
cmd = append(cmd, "BYSCORE")
|
||||||
}
|
}
|
||||||
|
@@ -333,8 +333,6 @@ func Test_AdminCommand(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Test MODULE LOAD command", func(t *testing.T) {
|
t.Run("Test MODULE LOAD command", func(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
port, err := internal.GetFreePort()
|
port, err := internal.GetFreePort()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
@@ -503,8 +501,6 @@ func Test_AdminCommand(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Test MODULE UNLOAD command", func(t *testing.T) {
|
t.Run("Test MODULE UNLOAD command", func(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
port, err := internal.GetFreePort()
|
port, err := internal.GetFreePort()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
@@ -527,6 +523,7 @@ func Test_AdminCommand(t *testing.T) {
|
|||||||
conn, err := net.Dial("tcp", fmt.Sprintf("localhost:%d", port))
|
conn, err := net.Dial("tcp", fmt.Sprintf("localhost:%d", port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
respConn := resp.NewConn(conn)
|
respConn := resp.NewConn(conn)
|
||||||
@@ -692,8 +689,6 @@ func Test_AdminCommand(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Test MODULE LIST command", func(t *testing.T) {
|
t.Run("Test MODULE LIST command", func(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
port, err := internal.GetFreePort()
|
port, err := internal.GetFreePort()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
@@ -716,6 +711,7 @@ func Test_AdminCommand(t *testing.T) {
|
|||||||
conn, err := net.Dial("tcp", fmt.Sprintf("localhost:%d", port))
|
conn, err := net.Dial("tcp", fmt.Sprintf("localhost:%d", port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
respConn := resp.NewConn(conn)
|
respConn := resp.NewConn(conn)
|
||||||
|
@@ -359,7 +359,7 @@ func handleExpire(params internal.HandlerFuncParams) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if _, err = params.KeyLock(params.Context, key); err != nil {
|
if _, err = params.KeyLock(params.Context, key); err != nil {
|
||||||
return nil, err
|
return []byte(":0\r\n"), err
|
||||||
}
|
}
|
||||||
defer params.KeyUnlock(params.Context, key)
|
defer params.KeyUnlock(params.Context, key)
|
||||||
|
|
||||||
@@ -496,7 +496,7 @@ PXAT - Expire at the exat time in unix milliseconds (positive integer).`,
|
|||||||
Command: "mset",
|
Command: "mset",
|
||||||
Module: constants.GenericModule,
|
Module: constants.GenericModule,
|
||||||
Categories: []string{constants.WriteCategory, constants.SlowCategory},
|
Categories: []string{constants.WriteCategory, constants.SlowCategory},
|
||||||
Description: "(MSET key value [key value ...]) Automatically generic or modify multiple key/value pairs.",
|
Description: "(MSET key value [key value ...]) Automatically set or modify multiple key/value pairs.",
|
||||||
Sync: true,
|
Sync: true,
|
||||||
KeyExtractionFunc: msetKeyFunc,
|
KeyExtractionFunc: msetKeyFunc,
|
||||||
HandlerFunc: handleMSet,
|
HandlerFunc: handleMSet,
|
||||||
|
@@ -1769,7 +1769,7 @@ The elements are ordered from lowest score to highest score`,
|
|||||||
Categories: []string{constants.SortedSetCategory, constants.ReadCategory, constants.SlowCategory},
|
Categories: []string{constants.SortedSetCategory, constants.ReadCategory, constants.SlowCategory},
|
||||||
Description: `(ZLEXCOUNT key min max) Returns the number of elements in within the sorted set within the
|
Description: `(ZLEXCOUNT key min max) Returns the number of elements in within the sorted set within the
|
||||||
lexicographical range between min and max. Returns 0, if the keys does not exist or if all the members do not have
|
lexicographical range between min and max. Returns 0, if the keys does not exist or if all the members do not have
|
||||||
the same score. If the value held at key is not a sorted set, an error is returned`,
|
the same score. If the value held at key is not a sorted set, an error is returned.`,
|
||||||
Sync: false,
|
Sync: false,
|
||||||
KeyExtractionFunc: zlexcountKeyFunc,
|
KeyExtractionFunc: zlexcountKeyFunc,
|
||||||
HandlerFunc: handleZLEXCOUNT,
|
HandlerFunc: handleZLEXCOUNT,
|
||||||
@@ -1779,7 +1779,7 @@ the same score. If the value held at key is not a sorted set, an error is return
|
|||||||
Module: constants.SortedSetModule,
|
Module: constants.SortedSetModule,
|
||||||
Categories: []string{constants.SortedSetCategory, constants.ReadCategory, constants.SlowCategory},
|
Categories: []string{constants.SortedSetCategory, constants.ReadCategory, constants.SlowCategory},
|
||||||
Description: `(ZRANGE key start stop [BYSCORE | BYLEX] [REV] [LIMIT offset count]
|
Description: `(ZRANGE key start stop [BYSCORE | BYLEX] [REV] [LIMIT offset count]
|
||||||
[WITHSCORES]) Returns the range of elements in the sorted set`,
|
[WITHSCORES]) Returns the range of elements in the sorted set.`,
|
||||||
Sync: false,
|
Sync: false,
|
||||||
KeyExtractionFunc: zrangeKeyCount,
|
KeyExtractionFunc: zrangeKeyCount,
|
||||||
HandlerFunc: handleZRANGE,
|
HandlerFunc: handleZRANGE,
|
||||||
@@ -1789,7 +1789,7 @@ the same score. If the value held at key is not a sorted set, an error is return
|
|||||||
Module: constants.SortedSetModule,
|
Module: constants.SortedSetModule,
|
||||||
Categories: []string{constants.SortedSetCategory, constants.WriteCategory, constants.SlowCategory},
|
Categories: []string{constants.SortedSetCategory, constants.WriteCategory, constants.SlowCategory},
|
||||||
Description: `ZRANGESTORE destination source start stop [BYSCORE | BYLEX] [REV] [LIMIT offset count]
|
Description: `ZRANGESTORE destination source start stop [BYSCORE | BYLEX] [REV] [LIMIT offset count]
|
||||||
[WITHSCORES] Retrieve the range of elements in the sorted set and store it in destination`,
|
[WITHSCORES] Retrieve the range of elements in the sorted set and store it in destination.`,
|
||||||
Sync: true,
|
Sync: true,
|
||||||
KeyExtractionFunc: zrangeStoreKeyFunc,
|
KeyExtractionFunc: zrangeStoreKeyFunc,
|
||||||
HandlerFunc: handleZRANGESTORE,
|
HandlerFunc: handleZRANGESTORE,
|
||||||
|
Reference in New Issue
Block a user