mirror of
https://github.com/EchoVault/SugarDB.git
synced 2025-09-27 12:22:16 +08:00
841 lines
27 KiB
Go
841 lines
27 KiB
Go
// Copyright 2024 Kelvin Clement Mwinuka
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package generic
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/echovault/echovault/internal"
|
|
"github.com/echovault/echovault/internal/constants"
|
|
)
|
|
|
|
type KeyObject struct {
|
|
value interface{}
|
|
locked bool
|
|
}
|
|
|
|
func handleSet(params internal.HandlerFuncParams) ([]byte, error) {
|
|
keys, err := setKeyFunc(params.Command)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
key := keys.WriteKeys[0]
|
|
keyExists := params.KeysExist(keys.WriteKeys)[key]
|
|
value := params.Command[2]
|
|
res := []byte(constants.OkResponse)
|
|
clock := params.GetClock()
|
|
|
|
options, err := getSetCommandOptions(clock, params.Command[3:], SetOptions{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// If Get is provided, the response should be the current stored value.
|
|
// If there's no current value, then the response should be nil.
|
|
if options.get {
|
|
if !keyExists {
|
|
res = []byte("$-1\r\n")
|
|
} else {
|
|
res = []byte(fmt.Sprintf("+%v\r\n", params.GetValues(params.Context, []string{key})[key]))
|
|
}
|
|
}
|
|
|
|
if "xx" == strings.ToLower(options.exists) {
|
|
// If XX is specified, make sure the key exists.
|
|
if !keyExists {
|
|
return nil, fmt.Errorf("key %s does not exist", key)
|
|
}
|
|
} else if "nx" == strings.ToLower(options.exists) {
|
|
// If NX is specified, make sure that the key does not currently exist.
|
|
if keyExists {
|
|
return nil, fmt.Errorf("key %s already exists", key)
|
|
}
|
|
}
|
|
|
|
if err = params.SetValues(params.Context, map[string]interface{}{
|
|
key: internal.AdaptType(value),
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// If expiresAt is set, set the key's expiry time as well
|
|
if options.expireAt != nil {
|
|
params.SetExpiry(params.Context, key, options.expireAt.(time.Time), false)
|
|
}
|
|
|
|
return res, nil
|
|
}
|
|
|
|
func handleMSet(params internal.HandlerFuncParams) ([]byte, error) {
|
|
_, err := msetKeyFunc(params.Command)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
entries := make(map[string]interface{})
|
|
|
|
// Extract all the key/value pairs
|
|
for i, key := range params.Command[1:] {
|
|
if i%2 == 0 {
|
|
entries[key] = internal.AdaptType(params.Command[1:][i+1])
|
|
}
|
|
}
|
|
|
|
// Set all the values
|
|
if err = params.SetValues(params.Context, entries); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return []byte(constants.OkResponse), nil
|
|
}
|
|
|
|
func handleGet(params internal.HandlerFuncParams) ([]byte, error) {
|
|
keys, err := getKeyFunc(params.Command)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
key := keys.ReadKeys[0]
|
|
keyExists := params.KeysExist([]string{key})[key]
|
|
|
|
if !keyExists {
|
|
return []byte("$-1\r\n"), nil
|
|
}
|
|
|
|
value := params.GetValues(params.Context, []string{key})[key]
|
|
|
|
return []byte(fmt.Sprintf("+%v\r\n", value)), nil
|
|
}
|
|
|
|
func handleMGet(params internal.HandlerFuncParams) ([]byte, error) {
|
|
keys, err := mgetKeyFunc(params.Command)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
values := make(map[string]string)
|
|
for key, value := range params.GetValues(params.Context, keys.ReadKeys) {
|
|
if value == nil {
|
|
values[key] = ""
|
|
continue
|
|
}
|
|
values[key] = fmt.Sprintf("%v", value)
|
|
}
|
|
|
|
bytes := []byte(fmt.Sprintf("*%d\r\n", len(params.Command[1:])))
|
|
|
|
for _, key := range params.Command[1:] {
|
|
if values[key] == "" {
|
|
bytes = append(bytes, []byte("$-1\r\n")...)
|
|
continue
|
|
}
|
|
bytes = append(bytes, []byte(fmt.Sprintf("$%d\r\n%s\r\n", len(values[key]), values[key]))...)
|
|
}
|
|
|
|
return bytes, nil
|
|
}
|
|
|
|
func handleDel(params internal.HandlerFuncParams) ([]byte, error) {
|
|
keys, err := delKeyFunc(params.Command)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
count := 0
|
|
for key, exists := range params.KeysExist(keys.WriteKeys) {
|
|
if !exists {
|
|
continue
|
|
}
|
|
err = params.DeleteKey(key)
|
|
if err != nil {
|
|
log.Printf("could not delete key %s due to error: %+v\n", key, err)
|
|
continue
|
|
}
|
|
count += 1
|
|
}
|
|
return []byte(fmt.Sprintf(":%d\r\n", count)), nil
|
|
}
|
|
|
|
func handlePersist(params internal.HandlerFuncParams) ([]byte, error) {
|
|
keys, err := persistKeyFunc(params.Command)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
key := keys.WriteKeys[0]
|
|
keyExists := params.KeysExist(keys.WriteKeys)[key]
|
|
|
|
if !keyExists {
|
|
return []byte(":0\r\n"), nil
|
|
}
|
|
|
|
expireAt := params.GetExpiry(key)
|
|
if expireAt == (time.Time{}) {
|
|
return []byte(":0\r\n"), nil
|
|
}
|
|
|
|
params.SetExpiry(params.Context, key, time.Time{}, false)
|
|
|
|
return []byte(":1\r\n"), nil
|
|
}
|
|
|
|
func handleExpireTime(params internal.HandlerFuncParams) ([]byte, error) {
|
|
keys, err := expireTimeKeyFunc(params.Command)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
key := keys.ReadKeys[0]
|
|
keyExists := params.KeysExist(keys.ReadKeys)[key]
|
|
|
|
if !keyExists {
|
|
return []byte(":-2\r\n"), nil
|
|
}
|
|
|
|
expireAt := params.GetExpiry(key)
|
|
|
|
if expireAt == (time.Time{}) {
|
|
return []byte(":-1\r\n"), nil
|
|
}
|
|
|
|
t := expireAt.Unix()
|
|
if strings.ToLower(params.Command[0]) == "pexpiretime" {
|
|
t = expireAt.UnixMilli()
|
|
}
|
|
|
|
return []byte(fmt.Sprintf(":%d\r\n", t)), nil
|
|
}
|
|
|
|
func handleTTL(params internal.HandlerFuncParams) ([]byte, error) {
|
|
keys, err := ttlKeyFunc(params.Command)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
key := keys.ReadKeys[0]
|
|
keyExists := params.KeysExist(keys.ReadKeys)[key]
|
|
|
|
clock := params.GetClock()
|
|
|
|
if !keyExists {
|
|
return []byte(":-2\r\n"), nil
|
|
}
|
|
|
|
expireAt := params.GetExpiry(key)
|
|
|
|
if expireAt == (time.Time{}) {
|
|
return []byte(":-1\r\n"), nil
|
|
}
|
|
|
|
t := expireAt.Unix() - clock.Now().Unix()
|
|
if strings.ToLower(params.Command[0]) == "pttl" {
|
|
t = expireAt.UnixMilli() - clock.Now().UnixMilli()
|
|
}
|
|
|
|
if t <= 0 {
|
|
return []byte(":0\r\n"), nil
|
|
}
|
|
|
|
return []byte(fmt.Sprintf(":%d\r\n", t)), nil
|
|
}
|
|
|
|
func handleExpire(params internal.HandlerFuncParams) ([]byte, error) {
|
|
keys, err := expireKeyFunc(params.Command)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
key := keys.WriteKeys[0]
|
|
keyExists := params.KeysExist(keys.WriteKeys)[key]
|
|
|
|
// Extract time
|
|
n, err := strconv.ParseInt(params.Command[2], 10, 64)
|
|
if err != nil {
|
|
return nil, errors.New("expire time must be integer")
|
|
}
|
|
expireAt := params.GetClock().Now().Add(time.Duration(n) * time.Second)
|
|
if strings.ToLower(params.Command[0]) == "pexpire" {
|
|
expireAt = params.GetClock().Now().Add(time.Duration(n) * time.Millisecond)
|
|
}
|
|
|
|
if !keyExists {
|
|
return []byte(":0\r\n"), nil
|
|
}
|
|
|
|
if len(params.Command) == 3 {
|
|
params.SetExpiry(params.Context, key, expireAt, true)
|
|
return []byte(":1\r\n"), nil
|
|
}
|
|
|
|
currentExpireAt := params.GetExpiry(key)
|
|
|
|
switch strings.ToLower(params.Command[3]) {
|
|
case "nx":
|
|
if currentExpireAt != (time.Time{}) {
|
|
return []byte(":0\r\n"), nil
|
|
}
|
|
params.SetExpiry(params.Context, key, expireAt, false)
|
|
case "xx":
|
|
if currentExpireAt == (time.Time{}) {
|
|
return []byte(":0\r\n"), nil
|
|
}
|
|
params.SetExpiry(params.Context, key, expireAt, false)
|
|
case "gt":
|
|
if currentExpireAt == (time.Time{}) {
|
|
return []byte(":0\r\n"), nil
|
|
}
|
|
if expireAt.Before(currentExpireAt) {
|
|
return []byte(":0\r\n"), nil
|
|
}
|
|
params.SetExpiry(params.Context, key, expireAt, false)
|
|
case "lt":
|
|
if currentExpireAt != (time.Time{}) {
|
|
if currentExpireAt.Before(expireAt) {
|
|
return []byte(":0\r\n"), nil
|
|
}
|
|
params.SetExpiry(params.Context, key, expireAt, false)
|
|
}
|
|
params.SetExpiry(params.Context, key, expireAt, false)
|
|
default:
|
|
return nil, fmt.Errorf("unknown option %s", strings.ToUpper(params.Command[3]))
|
|
}
|
|
|
|
return []byte(":1\r\n"), nil
|
|
}
|
|
|
|
func handleExpireAt(params internal.HandlerFuncParams) ([]byte, error) {
|
|
keys, err := expireKeyFunc(params.Command)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
key := keys.WriteKeys[0]
|
|
keyExists := params.KeysExist(keys.WriteKeys)[key]
|
|
|
|
// Extract time
|
|
n, err := strconv.ParseInt(params.Command[2], 10, 64)
|
|
if err != nil {
|
|
return nil, errors.New("expire time must be integer")
|
|
}
|
|
expireAt := time.Unix(n, 0)
|
|
if strings.ToLower(params.Command[0]) == "pexpireat" {
|
|
expireAt = time.UnixMilli(n)
|
|
}
|
|
|
|
if !keyExists {
|
|
return []byte(":0\r\n"), nil
|
|
}
|
|
|
|
if len(params.Command) == 3 {
|
|
params.SetExpiry(params.Context, key, expireAt, true)
|
|
return []byte(":1\r\n"), nil
|
|
}
|
|
|
|
currentExpireAt := params.GetExpiry(key)
|
|
|
|
switch strings.ToLower(params.Command[3]) {
|
|
case "nx":
|
|
if currentExpireAt != (time.Time{}) {
|
|
return []byte(":0\r\n"), nil
|
|
}
|
|
params.SetExpiry(params.Context, key, expireAt, false)
|
|
case "xx":
|
|
if currentExpireAt == (time.Time{}) {
|
|
return []byte(":0\r\n"), nil
|
|
}
|
|
params.SetExpiry(params.Context, key, expireAt, false)
|
|
case "gt":
|
|
if currentExpireAt == (time.Time{}) {
|
|
return []byte(":0\r\n"), nil
|
|
}
|
|
if expireAt.Before(currentExpireAt) {
|
|
return []byte(":0\r\n"), nil
|
|
}
|
|
params.SetExpiry(params.Context, key, expireAt, false)
|
|
case "lt":
|
|
if currentExpireAt != (time.Time{}) {
|
|
if currentExpireAt.Before(expireAt) {
|
|
return []byte(":0\r\n"), nil
|
|
}
|
|
params.SetExpiry(params.Context, key, expireAt, false)
|
|
}
|
|
params.SetExpiry(params.Context, key, expireAt, false)
|
|
default:
|
|
return nil, fmt.Errorf("unknown option %s", strings.ToUpper(params.Command[3]))
|
|
}
|
|
|
|
return []byte(":1\r\n"), nil
|
|
}
|
|
|
|
func handleIncr(params internal.HandlerFuncParams) ([]byte, error) {
|
|
// Extract key from command
|
|
keys, err := incrKeyFunc(params.Command)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
key := keys.WriteKeys[0]
|
|
values := params.GetValues(params.Context, []string{key}) // Get the current values for the specified keys
|
|
currentValue, ok := values[key] // Check if the key exists
|
|
|
|
var newValue int64
|
|
var currentValueInt int64
|
|
|
|
// Check if the key exists and its current value
|
|
if !ok || currentValue == nil {
|
|
// If key does not exist, initialize it with 1
|
|
newValue = 1
|
|
} else {
|
|
// Use type switch to handle different types of currentValue
|
|
switch v := currentValue.(type) {
|
|
case string:
|
|
var err error
|
|
currentValueInt, err = strconv.ParseInt(v, 10, 64) // Parse the string to int64
|
|
if err != nil {
|
|
return nil, errors.New("value is not an integer or out of range")
|
|
}
|
|
case int:
|
|
currentValueInt = int64(v) // Convert int to int64
|
|
case int64:
|
|
currentValueInt = v // Use int64 value directly
|
|
default:
|
|
fmt.Printf("unexpected type for currentValue: %T\n", currentValue)
|
|
return nil, errors.New("unexpected type for currentValue") // Handle unexpected types
|
|
}
|
|
newValue = currentValueInt + 1 // Increment the value
|
|
}
|
|
|
|
// Set the new incremented value
|
|
if err := params.SetValues(params.Context, map[string]interface{}{key: fmt.Sprintf("%d", newValue)}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Prepare response with the actual new value
|
|
return []byte(fmt.Sprintf(":%d\r\n", newValue)), nil
|
|
}
|
|
|
|
func handleDecr(params internal.HandlerFuncParams) ([]byte, error) {
|
|
// Extract key from command
|
|
keys, err := decrKeyFunc(params.Command)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
key := keys.WriteKeys[0]
|
|
values := params.GetValues(params.Context, []string{key}) // Get the current values for the specified keys
|
|
currentValue, ok := values[key] // Check if the key exists
|
|
|
|
var newValue int64
|
|
var currentValueInt int64
|
|
|
|
// Check if the key exists and its current value
|
|
if !ok || currentValue == nil {
|
|
// If key does not exist, initialize it with 0
|
|
newValue = -1
|
|
} else {
|
|
// Use type switch to handle different types of currentValue
|
|
switch v := currentValue.(type) {
|
|
case string:
|
|
var err error
|
|
currentValueInt, err = strconv.ParseInt(v, 10, 64) // Parse the string to int64
|
|
if err != nil {
|
|
return nil, errors.New("value is not an integer or out of range")
|
|
}
|
|
case int:
|
|
currentValueInt = int64(v) // Convert int to int64
|
|
case int64:
|
|
currentValueInt = v // Use int64 value directly
|
|
default:
|
|
fmt.Printf("unexpected type for currentValue: %T\n", currentValue)
|
|
return nil, errors.New("unexpected type for currentValue") // Handle unexpected types
|
|
}
|
|
newValue = currentValueInt - 1 // Decrement the value
|
|
}
|
|
|
|
// Set the new incremented value
|
|
if err := params.SetValues(params.Context, map[string]interface{}{key: fmt.Sprintf("%d", newValue)}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Prepare response with the actual new value
|
|
return []byte(fmt.Sprintf(":%d\r\n", newValue)), nil
|
|
}
|
|
|
|
func handleIncrBy(params internal.HandlerFuncParams) ([]byte, error) {
|
|
// Extract key from command
|
|
keys, err := incrByKeyFunc(params.Command)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Parse increment value
|
|
incrValue, err := strconv.ParseInt(params.Command[2], 10, 64)
|
|
if err != nil {
|
|
return nil, errors.New("increment value is not an integer or out of range")
|
|
}
|
|
|
|
key := keys.WriteKeys[0]
|
|
values := params.GetValues(params.Context, []string{key}) // Get the current values for the specified keys
|
|
currentValue, ok := values[key] // Check if the key exists
|
|
|
|
var newValue int64
|
|
var currentValueInt int64
|
|
|
|
// Check if the key exists and its current value
|
|
if !ok || currentValue == nil {
|
|
// If key does not exist, initialize it with the increment value
|
|
newValue = incrValue
|
|
} else {
|
|
// Use type switch to handle different types of currentValue
|
|
switch v := currentValue.(type) {
|
|
case string:
|
|
currentValueInt, err = strconv.ParseInt(v, 10, 64) // Parse the string to int64
|
|
if err != nil {
|
|
return nil, errors.New("value is not an integer or out of range")
|
|
}
|
|
case int:
|
|
currentValueInt = int64(v) // Convert int to int64
|
|
case int64:
|
|
currentValueInt = v // Use int64 value directly
|
|
default:
|
|
fmt.Printf("unexpected type for currentValue: %T\n", currentValue)
|
|
return nil, errors.New("unexpected type for currentValue") // Handle unexpected types
|
|
}
|
|
newValue = currentValueInt + incrValue // Increment the value by the specified amount
|
|
}
|
|
|
|
// Set the new incremented value
|
|
if err := params.SetValues(params.Context, map[string]interface{}{key: fmt.Sprintf("%d", newValue)}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Prepare response with the actual new value
|
|
return []byte(fmt.Sprintf(":%d\r\n", newValue)), nil
|
|
}
|
|
|
|
func handleDecrBy(params internal.HandlerFuncParams) ([]byte, error) {
|
|
// Extract key from command
|
|
keys, err := decrByKeyFunc(params.Command)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Parse decrement value
|
|
decrValue, err := strconv.ParseInt(params.Command[2], 10, 64)
|
|
if err != nil {
|
|
return nil, errors.New("decrement value is not an integer or out of range")
|
|
}
|
|
|
|
key := keys.WriteKeys[0]
|
|
values := params.GetValues(params.Context, []string{key}) // Get the current values for the specified keys
|
|
currentValue, ok := values[key] // Check if the key exists
|
|
|
|
var newValue int64
|
|
var currentValueInt int64
|
|
|
|
// Check if the key exists and its current value
|
|
if !ok || currentValue == nil {
|
|
// If key does not exist, initialize it with the decrement value
|
|
newValue = decrValue * -1
|
|
} else {
|
|
// Use type switch to handle different types of currentValue
|
|
switch v := currentValue.(type) {
|
|
case string:
|
|
currentValueInt, err = strconv.ParseInt(v, 10, 64) // Parse the string to int64
|
|
if err != nil {
|
|
return nil, errors.New("value is not an integer or out of range")
|
|
}
|
|
case int:
|
|
currentValueInt = int64(v) // Convert int to int64
|
|
case int64:
|
|
currentValueInt = v // Use int64 value directly
|
|
default:
|
|
fmt.Printf("unexpected type for currentValue: %T\n", currentValue)
|
|
return nil, errors.New("unexpected type for currentValue") // Handle unexpected types
|
|
}
|
|
newValue = currentValueInt - decrValue // decrement the value by the specified amount
|
|
}
|
|
|
|
// Set the new incremented value
|
|
if err := params.SetValues(params.Context, map[string]interface{}{key: fmt.Sprintf("%d", newValue)}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Prepare response with the actual new value
|
|
return []byte(fmt.Sprintf(":%d\r\n", newValue)), nil
|
|
}
|
|
|
|
func handleRename(params internal.HandlerFuncParams) ([]byte, error) {
|
|
if len(params.Command) != 3 {
|
|
return nil, errors.New(constants.WrongArgsResponse)
|
|
}
|
|
|
|
oldKey := params.Command[1]
|
|
newKey := params.Command[2]
|
|
|
|
// Get the current value for the old key
|
|
values := params.GetValues(params.Context, []string{oldKey})
|
|
oldValue, ok := values[oldKey]
|
|
|
|
if !ok || oldValue == nil {
|
|
return nil, errors.New("no such key")
|
|
}
|
|
|
|
// Set the new key with the old value
|
|
if err := params.SetValues(params.Context, map[string]interface{}{newKey: oldValue}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Delete the old key
|
|
if err := params.DeleteKey(oldKey); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return []byte("+OK\r\n"), nil
|
|
}
|
|
|
|
func Commands() []internal.Command {
|
|
return []internal.Command{
|
|
{
|
|
Command: "set",
|
|
Module: constants.GenericModule,
|
|
Categories: []string{constants.WriteCategory, constants.SlowCategory},
|
|
Description: `
|
|
(SET key value [NX | XX] [GET] [EX seconds | PX milliseconds | EXAT unix-time-seconds | PXAT unix-time-milliseconds])
|
|
Set the value of a key, considering the value's type.
|
|
NX - Only set if the key does not exist.
|
|
XX - Only set if the key exists.
|
|
GET - Return the old value stored at key, or nil if the value does not exist.
|
|
EX - Expire the key after the specified number of seconds (positive integer).
|
|
PX - Expire the key after the specified number of milliseconds (positive integer).
|
|
EXAT - Expire at the exact time in unix seconds (positive integer).
|
|
PXAT - Expire at the exat time in unix milliseconds (positive integer).`,
|
|
Sync: true,
|
|
KeyExtractionFunc: setKeyFunc,
|
|
HandlerFunc: handleSet,
|
|
},
|
|
{
|
|
Command: "mset",
|
|
Module: constants.GenericModule,
|
|
Categories: []string{constants.WriteCategory, constants.SlowCategory},
|
|
Description: "(MSET key value [key value ...]) Automatically set or modify multiple key/value pairs.",
|
|
Sync: true,
|
|
KeyExtractionFunc: msetKeyFunc,
|
|
HandlerFunc: handleMSet,
|
|
},
|
|
{
|
|
Command: "get",
|
|
Module: constants.GenericModule,
|
|
Categories: []string{constants.ReadCategory, constants.FastCategory},
|
|
Description: "(GET key) Get the value at the specified key.",
|
|
Sync: false,
|
|
KeyExtractionFunc: getKeyFunc,
|
|
HandlerFunc: handleGet,
|
|
},
|
|
{
|
|
Command: "mget",
|
|
Module: constants.GenericModule,
|
|
Categories: []string{constants.ReadCategory, constants.FastCategory},
|
|
Description: "(MGET key [key ...]) Get multiple values from the specified keys.",
|
|
Sync: false,
|
|
KeyExtractionFunc: mgetKeyFunc,
|
|
HandlerFunc: handleMGet,
|
|
},
|
|
{
|
|
Command: "del",
|
|
Module: constants.GenericModule,
|
|
Categories: []string{constants.KeyspaceCategory, constants.WriteCategory, constants.FastCategory},
|
|
Description: "(DEL key [key ...]) Removes one or more keys from the store.",
|
|
Sync: true,
|
|
KeyExtractionFunc: delKeyFunc,
|
|
HandlerFunc: handleDel,
|
|
},
|
|
{
|
|
Command: "persist",
|
|
Module: constants.GenericModule,
|
|
Categories: []string{constants.KeyspaceCategory, constants.WriteCategory, constants.FastCategory},
|
|
Description: `(PERSIST key) Removes the TTl associated with a key,
|
|
turning it from a volatile key to a persistent key.`,
|
|
Sync: true,
|
|
KeyExtractionFunc: persistKeyFunc,
|
|
HandlerFunc: handlePersist,
|
|
},
|
|
{
|
|
Command: "expiretime",
|
|
Module: constants.GenericModule,
|
|
Categories: []string{constants.KeyspaceCategory, constants.ReadCategory, constants.FastCategory},
|
|
Description: `(EXPIRETIME key) Returns the absolute unix time in seconds when the key will expire.
|
|
Return -1 if the key exists but has no associated expiry time.
|
|
Returns -2 if the key does not exist.`,
|
|
Sync: false,
|
|
KeyExtractionFunc: expireTimeKeyFunc,
|
|
HandlerFunc: handleExpireTime,
|
|
},
|
|
{
|
|
Command: "pexpiretime",
|
|
Module: constants.GenericModule,
|
|
Categories: []string{constants.KeyspaceCategory, constants.ReadCategory, constants.FastCategory},
|
|
Description: `(PEXPIRETIME key) Returns the absolute unix time in milliseconds when the key will expire.
|
|
Return -1 if the key exists but has no associated expiry time.
|
|
Returns -2 if the key does not exist.`,
|
|
Sync: false,
|
|
KeyExtractionFunc: expireTimeKeyFunc,
|
|
HandlerFunc: handleExpireTime,
|
|
},
|
|
{
|
|
Command: "ttl",
|
|
Module: constants.GenericModule,
|
|
Categories: []string{constants.KeyspaceCategory, constants.ReadCategory, constants.FastCategory},
|
|
Description: `(TTL key) Returns the remaining time to live for a key that has an expiry time in seconds.
|
|
If the key exists but does not have an associated expiry time, -1 is returned.
|
|
If the key does not exist, -2 is returned.`,
|
|
Sync: false,
|
|
KeyExtractionFunc: ttlKeyFunc,
|
|
HandlerFunc: handleTTL,
|
|
},
|
|
{
|
|
Command: "pttl",
|
|
Module: constants.GenericModule,
|
|
Categories: []string{constants.KeyspaceCategory, constants.ReadCategory, constants.FastCategory},
|
|
Description: `(PTTL key) Returns the remaining time to live for a key that has an expiry time in milliseconds.
|
|
If the key exists but does not have an associated expiry time, -1 is returned.
|
|
If the key does not exist, -2 is returned.`,
|
|
Sync: false,
|
|
KeyExtractionFunc: ttlKeyFunc,
|
|
HandlerFunc: handleTTL,
|
|
},
|
|
{
|
|
Command: "expire",
|
|
Module: constants.GenericModule,
|
|
Categories: []string{constants.KeyspaceCategory, constants.WriteCategory, constants.FastCategory},
|
|
Description: `(EXPIRE key seconds [NX | XX | GT | LT])
|
|
Expire the key in the specified number of seconds. This commands turns a key into a volatile one.
|
|
NX - Only set the expiry time if the key has no associated expiry.
|
|
XX - Only set the expiry time if the key already has an expiry time.
|
|
GT - Only set the expiry time if the new expiry time is greater than the current one.
|
|
LT - Only set the expiry time if the new expiry time is less than the current one.`,
|
|
Sync: true,
|
|
KeyExtractionFunc: expireKeyFunc,
|
|
HandlerFunc: handleExpire,
|
|
},
|
|
{
|
|
Command: "pexpire",
|
|
Module: constants.GenericModule,
|
|
Categories: []string{constants.KeyspaceCategory, constants.WriteCategory, constants.FastCategory},
|
|
Description: `(PEXPIRE key milliseconds [NX | XX | GT | LT])
|
|
Expire the key in the specified number of milliseconds. This commands turns a key into a volatile one.
|
|
NX - Only set the expiry time if the key has no associated expiry.
|
|
XX - Only set the expiry time if the key already has an expiry time.
|
|
GT - Only set the expiry time if the new expiry time is greater than the current one.
|
|
LT - Only set the expiry time if the new expiry time is less than the current one.`,
|
|
Sync: true,
|
|
KeyExtractionFunc: expireKeyFunc,
|
|
HandlerFunc: handleExpire,
|
|
},
|
|
{
|
|
Command: "expireat",
|
|
Module: constants.GenericModule,
|
|
Categories: []string{constants.KeyspaceCategory, constants.WriteCategory, constants.FastCategory},
|
|
Description: `(EXPIREAT key unix-time-seconds [NX | XX | GT | LT])
|
|
Expire the key in at the exact unix time in seconds.
|
|
This commands turns a key into a volatile one.
|
|
NX - Only set the expiry time if the key has no associated expiry.
|
|
XX - Only set the expiry time if the key already has an expiry time.
|
|
GT - Only set the expiry time if the new expiry time is greater than the current one.
|
|
LT - Only set the expiry time if the new expiry time is less than the current one.`,
|
|
Sync: true,
|
|
KeyExtractionFunc: expireAtKeyFunc,
|
|
HandlerFunc: handleExpireAt,
|
|
},
|
|
{
|
|
Command: "pexpireat",
|
|
Module: constants.GenericModule,
|
|
Categories: []string{constants.KeyspaceCategory, constants.WriteCategory, constants.FastCategory},
|
|
Description: `(PEXPIREAT key unix-time-milliseconds [NX | XX | GT | LT])
|
|
Expire the key in at the exact unix time in milliseconds.
|
|
This commands turns a key into a volatile one.
|
|
NX - Only set the expiry time if the key has no associated expiry.
|
|
XX - Only set the expiry time if the key already has an expiry time.
|
|
GT - Only set the expiry time if the new expiry time is greater than the current one.
|
|
LT - Only set the expiry time if the new expiry time is less than the current one.`,
|
|
Sync: true,
|
|
KeyExtractionFunc: expireAtKeyFunc,
|
|
HandlerFunc: handleExpireAt,
|
|
},
|
|
{
|
|
Command: "incr",
|
|
Module: constants.GenericModule,
|
|
Categories: []string{constants.KeyspaceCategory, constants.WriteCategory, constants.FastCategory},
|
|
Description: `(INCR key)
|
|
Increments the number stored at key by one. If the key does not exist, it is set to 0 before performing the operation.
|
|
An error is returned if the key contains a value of the wrong type or contains a string that cannot be represented as integer.
|
|
This operation is limited to 64 bit signed integers.`,
|
|
Sync: true,
|
|
KeyExtractionFunc: incrKeyFunc,
|
|
HandlerFunc: handleIncr,
|
|
},
|
|
{
|
|
Command: "decr",
|
|
Module: constants.GenericModule,
|
|
Categories: []string{constants.KeyspaceCategory, constants.WriteCategory, constants.FastCategory},
|
|
Description: `(DECR key)
|
|
Decrements the number stored at key by one.
|
|
If the key does not exist, it is set to 0 before performing the operation.
|
|
An error is returned if the key contains a value of the wrong type or contains a string that cannot be represented as integer.
|
|
This operation is limited to 64 bit signed integers.`,
|
|
Sync: true,
|
|
KeyExtractionFunc: decrKeyFunc,
|
|
HandlerFunc: handleDecr,
|
|
},
|
|
{
|
|
Command: "incrby",
|
|
Module: constants.GenericModule,
|
|
Categories: []string{constants.KeyspaceCategory, constants.WriteCategory, constants.FastCategory},
|
|
Description: `(INCRBY key increment)
|
|
Increments the number stored at key by increment. If the key does not exist, it is set to 0 before performing the operation.
|
|
An error is returned if the key contains a value of the wrong type or contains a string that can not be represented as integer.`,
|
|
Sync: true,
|
|
KeyExtractionFunc: incrByKeyFunc,
|
|
HandlerFunc: handleIncrBy,
|
|
},
|
|
{
|
|
Command: "decrby",
|
|
Module: constants.GenericModule,
|
|
Categories: []string{constants.KeyspaceCategory, constants.WriteCategory, constants.FastCategory},
|
|
Description: `(DECRBY key decrement)
|
|
The DECRBY command reduces the value stored at the specified key by the specified decrement.
|
|
If the key does not exist, it is initialized with a value of 0 before performing the operation.
|
|
If the key's value is not of the correct type or cannot be represented as an integer, an error is returned.`,
|
|
Sync: true,
|
|
KeyExtractionFunc: decrByKeyFunc,
|
|
HandlerFunc: handleDecrBy,
|
|
},
|
|
{
|
|
Command: "rename",
|
|
Module: constants.GenericModule,
|
|
Categories: []string{constants.KeyspaceCategory, constants.WriteCategory, constants.FastCategory},
|
|
Description: `(RENAME key newkey)
|
|
Renames key to newkey. If newkey already exists, it is overwritten. If key does not exist, an error is returned.`,
|
|
Sync: true,
|
|
KeyExtractionFunc: renameKeyFunc,
|
|
HandlerFunc: handleRename,
|
|
},
|
|
}
|
|
}
|