mirror of
https://github.com/nalgeon/redka.git
synced 2025-09-27 04:16:00 +08:00
113 lines
2.1 KiB
Go
113 lines
2.1 KiB
Go
package command
|
|
|
|
import (
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/nalgeon/redka"
|
|
"github.com/tidwall/redcon"
|
|
)
|
|
|
|
// Set sets the string value of a key, ignoring its type.
|
|
// The key is created if it doesn't exist.
|
|
// SET key value [NX | XX] [EX seconds | PX milliseconds ]
|
|
// https://redis.io/commands/set
|
|
type Set struct {
|
|
baseCmd
|
|
key string
|
|
value []byte
|
|
ifNX bool
|
|
ifXX bool
|
|
ttl time.Duration
|
|
}
|
|
|
|
func parseSet(b baseCmd) (*Set, error) {
|
|
parseExists := func(cmd *Set, value string) error {
|
|
switch value {
|
|
case "nx":
|
|
cmd.ifNX = true
|
|
case "xx":
|
|
cmd.ifXX = true
|
|
default:
|
|
return ErrSyntax
|
|
}
|
|
return nil
|
|
}
|
|
|
|
parseExpires := func(cmd *Set, unit string, value string) error {
|
|
valueInt, err := strconv.Atoi(value)
|
|
if err != nil {
|
|
return ErrInvalidInt
|
|
}
|
|
|
|
switch string(unit) {
|
|
case "ex":
|
|
cmd.ttl = time.Duration(valueInt) * time.Second
|
|
case "px":
|
|
cmd.ttl = time.Duration(valueInt) * time.Millisecond
|
|
default:
|
|
return ErrSyntax
|
|
}
|
|
|
|
if cmd.ttl <= 0 {
|
|
return ErrInvalidExpireTime(cmd.name)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
cmd := &Set{baseCmd: b}
|
|
if len(cmd.args) < 2 || len(cmd.args) > 5 {
|
|
return cmd, ErrInvalidArgNum(cmd.name)
|
|
}
|
|
|
|
cmd.key = string(cmd.args[0])
|
|
cmd.value = cmd.args[1]
|
|
|
|
if len(cmd.args) == 3 || len(cmd.args) == 5 {
|
|
err := parseExists(cmd, string(cmd.args[2]))
|
|
if err != nil {
|
|
return cmd, err
|
|
}
|
|
}
|
|
|
|
if len(cmd.args) == 4 {
|
|
err := parseExpires(cmd, string(cmd.args[2]), string(cmd.args[3]))
|
|
if err != nil {
|
|
return cmd, err
|
|
}
|
|
}
|
|
|
|
if len(cmd.args) == 5 {
|
|
err := parseExpires(cmd, string(cmd.args[3]), string(cmd.args[4]))
|
|
if err != nil {
|
|
return cmd, err
|
|
}
|
|
}
|
|
|
|
return cmd, nil
|
|
}
|
|
|
|
func (cmd *Set) Run(w redcon.Conn, red redka.Redka) (any, error) {
|
|
var ok bool
|
|
var err error
|
|
if cmd.ifXX {
|
|
ok, err = red.Str().SetExists(cmd.key, cmd.value, cmd.ttl)
|
|
} else if cmd.ifNX {
|
|
ok, err = red.Str().SetNotExists(cmd.key, cmd.value, cmd.ttl)
|
|
} else {
|
|
err = red.Str().SetExpires(cmd.key, cmd.value, cmd.ttl)
|
|
ok = err == nil
|
|
}
|
|
|
|
if err != nil {
|
|
w.WriteError(err.Error())
|
|
return nil, err
|
|
}
|
|
if !ok {
|
|
w.WriteNull()
|
|
return false, nil
|
|
}
|
|
w.WriteString("OK")
|
|
return true, nil
|
|
}
|