Skip to main content

cmd_getex.go

cmd_getex.go - Overview

This file defines the GETEX command, which retrieves the value of a key and optionally sets its expiration.

Detailed Documentation

cGETEX

var cGETEX = &CommandMeta{
Name: "GETEX",
Syntax: "GETEX key [EX seconds] [PX milliseconds] [EXAT timestamp-seconds] [PXAT timestamp-milliseconds] [PERSIST]",
HelpShort: "GETEX gets the value of key and optionally set its expiration.",
HelpLong: `
GETEX gets the value of key and optionally set its expiration. The behavior of the command
is similar to the GET command with the addition of the ability to set an expiration on the key.

The command returns (nil) if the key does not exist. The command supports the following options:

- EX seconds: Set the expiration to seconds from now.
- PX milliseconds: Set the expiration to milliseconds from now.
- EXAT timestamp: Set the expiration to a Unix timestamp.
- PXAT timestamp: Set the expiration to a Unix timestamp in milliseconds.
- PERSIST: Remove the expiration from the key.
`,
Examples: `
localhost:7379> SET k v
OK OK
localhost:7379> GETEX k EX 1000
OK v
localhost:7379> TTL k
OK 996
localhost:7379> GETEX k PX 200000
OK v
localhost:7379> GETEX k EXAT 1772377267
OK v
localhost:7379> GETEX k PXAT 1772377267000
OK v
localhost:7379> GETEX k PERSIST
OK v
localhost:7379> GET k
(nil)
`,
Eval: evalGETEX,
Execute: executeGETEX,
}
  • Purpose: Defines the metadata for the GETEX command, including its name, syntax, help text, examples, and associated functions for evaluation and execution.
  • Fields:
    • Name: The name of the command ("GETEX").
    • Syntax: The command's syntax.
    • HelpShort: A short description of the command.
    • HelpLong: A longer, more detailed description of the command.
    • Examples: Example usage of the command.
    • Eval: The function to evaluate the command (evalGETEX).
    • Execute: The function to execute the command (executeGETEX).

evalGETEX

func evalGETEX(c *Cmd, s *dstore.Store) (*CmdRes, error) {
if len(c.C.Args) < 1 {
return cmdResNil, errors.ErrWrongArgumentCount("GETEX")
}

var key = c.C.Args[0]
params := map[types.Param]string{}
for i := 1; i < len(c.C.Args); i++ {
arg := types.Param(strings.ToUpper(c.C.Args[i]))
switch arg {
case types.EX, types.PX, types.EXAT, types.PXAT:
params[arg] = c.C.Args[i+1]
i++
case types.PERSIST:
params[arg] = "true"
}
}

// Raise errors if incompatible parameters are provided
// in one command
if params[types.EX] != "" && params[types.PX] != "" {
return cmdResNil, errors.ErrInvalidSyntax("GETEX")
} else if params[types.EX] != "" && params[types.EXAT] != "" {
return cmdResNil, errors.ErrInvalidSyntax("GETEX")
} else if params[types.EX] != "" && params[types.PXAT] != "" {
return cmdResNil, errors.ErrInvalidSyntax("GETEX")
} else if params[types.PX] != "" && params[types.EXAT] != "" {
return cmdResNil, errors.ErrInvalidSyntax("GETEX")
} else if params[types.PX] != "" && params[types.PXAT] != "" {
return cmdResNil, errors.ErrInvalidSyntax("GETEX")
} else if params[types.EXAT] != "" && params[types.PXAT] != "" {
return cmdResNil, errors.ErrInvalidSyntax("GETEX")
} else if params[types.PERSIST] != "" && (params[types.EX] != "" || params[types.PX] != "" || params[types.EXAT] != "" || params[types.PXAT] != "") {
return cmdResNil, errors.ErrInvalidSyntax("GETEX")
}
var err error
var exDurationSec, exDurationMs int64

// Default to -1 to indicate that the value is not set
// and the key will not expire
exDurationMs = -1

if params[types.EX] != "" {
exDurationSec, err = strconv.ParseInt(params[types.EX], 10, 64)
if err != nil {
return cmdResNil, errors.ErrInvalidValue("GETEX", "EX")
}
if exDurationSec <= 0 || exDurationSec >= MaxEXDurationSec {
return cmdResNil, errors.ErrInvalidValue("GETEX", "EX")
}
exDurationMs = exDurationSec * 1000
}

if params[types.PX] != "" {
exDurationMs, err = strconv.ParseInt(params[types.PX], 10, 64)
if err != nil {
return cmdResNil, errors.ErrInvalidValue("GETEX", "PX")
}
if exDurationMs <= 0 || exDurationMs >= MaxEXDurationSec {
return cmdResNil, errors.ErrInvalidValue("GETEX", "PX")
}
}

if params[types.EXAT] != "" {
tv, err := strconv.ParseInt(params[types.EXAT], 10, 64)
if err != nil {
return cmdResNil, errors.ErrInvalidValue("GETEX", "EXAT")
}
exDurationSec = tv - utils.GetCurrentTime().Unix()
if exDurationSec <= 0 || exDurationSec >= MaxEXDurationSec {
return cmdResNil, errors.ErrInvalidValue("GETEX", "EXAT")
}
exDurationMs = exDurationSec * 1000
}

if params[types.PXAT] != "" {
tv, err := strconv.ParseInt(params[types.PXAT], 10, 64)
if err != nil {
return cmdResNil, errors.ErrInvalidValue("GETEX", "PXAT")
}
exDurationMs = tv - utils.GetCurrentTime().UnixMilli()
if exDurationMs <= 0 || exDurationMs >= (MaxEXDurationSec*1000) {
return cmdResNil, errors.ErrInvalidValue("GETEX", "PXAT")
}
}

existingObj := s.Get(key)
if existingObj == nil {
return cmdResNil, nil
}

resp, err := evalGET(&Cmd{
C: &wire.Command{
Cmd: "GET",
Args: []string{key},
}}, s)
if err != nil {
return resp, err
}

if params[types.PERSIST] != "" {
dstore.DelExpiry(existingObj, s)
} else if exDurationMs != -1 {
s.SetExpiry(existingObj, exDurationMs)
}

return resp, nil
}
  • Purpose: Evaluates the GETEX command, parses its arguments, retrieves the value associated with the key, and optionally sets or removes the key's expiration.
  • Parameters:
    • c (Cmd): The command to evaluate.
    • s (dstore.Store): The data store.
  • Returns:
    • *CmdRes: The result of the command.
    • error: An error, if any.

executeGETEX

func executeGETEX(c *Cmd, sm *shardmanager.ShardManager) (*CmdRes, error) {
if len(c.C.Args) == 0 {
return cmdResNil, errors.ErrWrongArgumentCount("GETEX")
}

shard := sm.GetShardForKey(c.C.Args[0])
return evalGETEX(c, shard.Thread.Store())
}
  • Purpose: Executes the GETEX command by retrieving the appropriate shard based on the key and then calling evalGETEX to evaluate the command within that shard's store.
  • Parameters:
    • c (Cmd): The command to execute.
    • sm (shardmanager.ShardManager): The shard manager.
  • Returns:
    • *CmdRes: The result of the command.
    • error: An error, if any.

Getting Started Relevance