Skip to content

Commit

Permalink
Go: Implement Exists, Expire related commands and TTL commands (valke…
Browse files Browse the repository at this point in the history
…y-io#2738)

* Implemented Exists, Expire and TTL commands

Signed-off-by: Niharika Bhavaraju <[email protected]>
  • Loading branch information
niharikabhavaraju authored Dec 13, 2024
1 parent b347ef8 commit ab31e48
Show file tree
Hide file tree
Showing 5 changed files with 1,112 additions and 7 deletions.
145 changes: 145 additions & 0 deletions go/api/base_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -957,3 +957,148 @@ func (client *baseClient) Del(keys []string) (Result[int64], error) {

return handleLongResponse(result)
}

func (client *baseClient) Exists(keys []string) (Result[int64], error) {
result, err := client.executeCommand(C.Exists, keys)
if err != nil {
return CreateNilInt64Result(), err
}

return handleLongResponse(result)
}

func (client *baseClient) Expire(key string, seconds int64) (Result[bool], error) {
result, err := client.executeCommand(C.Expire, []string{key, utils.IntToString(seconds)})
if err != nil {
return CreateNilBoolResult(), err
}

return handleBooleanResponse(result)
}

func (client *baseClient) ExpireWithOptions(key string, seconds int64, expireCondition ExpireCondition) (Result[bool], error) {
expireConditionStr, err := expireCondition.toString()
if err != nil {
return CreateNilBoolResult(), err
}
result, err := client.executeCommand(C.Expire, []string{key, utils.IntToString(seconds), expireConditionStr})
if err != nil {
return CreateNilBoolResult(), err
}
return handleBooleanResponse(result)
}

func (client *baseClient) ExpireAt(key string, unixTimestampInSeconds int64) (Result[bool], error) {
result, err := client.executeCommand(C.ExpireAt, []string{key, utils.IntToString(unixTimestampInSeconds)})
if err != nil {
return CreateNilBoolResult(), err
}

return handleBooleanResponse(result)
}

func (client *baseClient) ExpireAtWithOptions(
key string,
unixTimestampInSeconds int64,
expireCondition ExpireCondition,
) (Result[bool], error) {
expireConditionStr, err := expireCondition.toString()
if err != nil {
return CreateNilBoolResult(), err
}
result, err := client.executeCommand(
C.ExpireAt,
[]string{key, utils.IntToString(unixTimestampInSeconds), expireConditionStr},
)
if err != nil {
return CreateNilBoolResult(), err
}
return handleBooleanResponse(result)
}

func (client *baseClient) PExpire(key string, milliseconds int64) (Result[bool], error) {
result, err := client.executeCommand(C.PExpire, []string{key, utils.IntToString(milliseconds)})
if err != nil {
return CreateNilBoolResult(), err
}
return handleBooleanResponse(result)
}

func (client *baseClient) PExpireWithOptions(
key string,
milliseconds int64,
expireCondition ExpireCondition,
) (Result[bool], error) {
expireConditionStr, err := expireCondition.toString()
if err != nil {
return CreateNilBoolResult(), err
}
result, err := client.executeCommand(C.PExpire, []string{key, utils.IntToString(milliseconds), expireConditionStr})
if err != nil {
return CreateNilBoolResult(), err
}
return handleBooleanResponse(result)
}

func (client *baseClient) PExpireAt(key string, unixTimestampInMilliSeconds int64) (Result[bool], error) {
result, err := client.executeCommand(C.PExpireAt, []string{key, utils.IntToString(unixTimestampInMilliSeconds)})
if err != nil {
return CreateNilBoolResult(), err
}
return handleBooleanResponse(result)
}

func (client *baseClient) PExpireAtWithOptions(
key string,
unixTimestampInMilliSeconds int64,
expireCondition ExpireCondition,
) (Result[bool], error) {
expireConditionStr, err := expireCondition.toString()
if err != nil {
return CreateNilBoolResult(), err
}
result, err := client.executeCommand(
C.PExpireAt,
[]string{key, utils.IntToString(unixTimestampInMilliSeconds), expireConditionStr},
)
if err != nil {
return CreateNilBoolResult(), err
}
return handleBooleanResponse(result)
}

func (client *baseClient) ExpireTime(key string) (Result[int64], error) {
result, err := client.executeCommand(C.ExpireTime, []string{key})
if err != nil {
return CreateNilInt64Result(), err
}

return handleLongResponse(result)
}

func (client *baseClient) PExpireTime(key string) (Result[int64], error) {
result, err := client.executeCommand(C.PExpireTime, []string{key})
if err != nil {
return CreateNilInt64Result(), err
}

return handleLongResponse(result)
}

func (client *baseClient) TTL(key string) (Result[int64], error) {
result, err := client.executeCommand(C.TTL, []string{key})
if err != nil {
return CreateNilInt64Result(), err
}

return handleLongResponse(result)
}

func (client *baseClient) PTTL(key string) (Result[int64], error) {
result, err := client.executeCommand(C.PTTL, []string{key})
if err != nil {
return CreateNilInt64Result(), err
}

return handleLongResponse(result)
}
28 changes: 28 additions & 0 deletions go/api/command_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,34 @@ const (
OnlyIfDoesNotExist ConditionalSet = "NX"
)

type ExpireCondition string

const (
// HasExistingExpiry only sets the key if it already exists. Equivalent to "XX" in the valkey API.
HasExistingExpiry ExpireCondition = "XX"
// HasNoExpiry only sets the key if it does not already exist. Equivalent to "NX" in the valkey API.
HasNoExpiry ExpireCondition = "NX"
// NewExpiryGreaterThanCurrent only sets the key if its greater than current. Equivalent to "GT" in the valkey API.
NewExpiryGreaterThanCurrent ExpireCondition = "GT"
// NewExpiryLessThanCurrent only sets the key if its lesser than current. Equivalent to "LT" in the valkey API.
NewExpiryLessThanCurrent ExpireCondition = "LT"
)

func (expireCondition ExpireCondition) toString() (string, error) {
switch expireCondition {
case HasExistingExpiry:
return string(HasExistingExpiry), nil
case HasNoExpiry:
return string(HasNoExpiry), nil
case NewExpiryGreaterThanCurrent:
return string(NewExpiryGreaterThanCurrent), nil
case NewExpiryLessThanCurrent:
return string(NewExpiryLessThanCurrent), nil
default:
return "", &RequestError{"Invalid expire condition"}
}
}

// Expiry is used to configure the lifetime of a value.
type Expiry struct {
Type ExpiryType
Expand Down
18 changes: 12 additions & 6 deletions go/api/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,12 @@ type StringCommands interface {
// the entire operation fails.
//
// Note:
// When in cluster mode, all keys in keyValueMap must map to the same hash slot.
//
// See [valkey.io] for details.
// In cluster mode, if keys in `keyValueMap` map to different hash slots, the command
// will be split across these slots and executed separately for each. This means the command
// is atomic only at the slot level. If one or more slot-specific requests fail, the entire
// call will return the first encountered error, even though some requests may have succeeded
// while others did not. If this behavior impacts your application logic, consider splitting
// the request into sub-requests per slot to ensure atomicity.
//
// Parameters:
// keyValueMap - A key-value map consisting of keys and their respective values to set.
Expand Down Expand Up @@ -414,9 +417,12 @@ type StringCommands interface {
// Valkey 7.0 and above.
//
// Note:
// When in cluster mode, key1 and key2 must map to the same hash slot.
//
// See [valkey.io] for details.
// In cluster mode, if keys in `keyValueMap` map to different hash slots, the command
// will be split across these slots and executed separately for each. This means the command
// is atomic only at the slot level. If one or more slot-specific requests fail, the entire
// call will return the first encountered error, even though some requests may have succeeded
// while others did not. If this behavior impacts your application logic, consider splitting
// the request into sub-requests per slot to ensure atomicity.
//
// Parameters:
// key1 - The key that stores the first string.
Expand Down
Loading

0 comments on commit ab31e48

Please sign in to comment.