1
0
mirror of https://github.com/redis/go-redis.git synced 2025-04-17 20:17:02 +03:00

API vhange

This commit is contained in:
ofekshenawa 2025-03-20 13:09:16 +02:00
parent 3785924788
commit 2408d41ea6
3 changed files with 42 additions and 46 deletions

View File

@ -2814,7 +2814,7 @@ var _ = Describe("Commands", func() {
It("should HGETDEL", Label("hash", "HGETDEL"), func() {
SkipBeforeRedisVersion(7.9, "requires Redis 8.x")
// Setup: create a hash with three fields.
err := client.HSet(ctx, "myhash", "f1", "val1", "f2", "val2", "f3", "val3").Err()
Expect(err).NotTo(HaveOccurred())
@ -2837,8 +2837,6 @@ var _ = Describe("Commands", func() {
// HGETDEL on a key that does not exist.
res, err := client.HGetDel(ctx, "nonexistent", "f1", "f2").Result()
Expect(err).To(BeNil())
// Depending on your implementation, missing fields may return nil or empty strings.
// Adjust the expectation accordingly.
Expect(res).To(Equal([]string{"", ""}))
})
@ -2847,38 +2845,46 @@ var _ = Describe("Commands", func() {
// -----------------------------
It("should HGETEX with EX option", Label("hash", "HGETEX"), func() {
SkipBeforeRedisVersion(7.9, "requires Redis 8.x")
// Setup: create a hash.
err := client.HSet(ctx, "myhash", "f1", "val1", "f2", "val2").Err()
Expect(err).NotTo(HaveOccurred())
// Call HGETEX with EX option and 60 seconds TTL.
res, err := client.HGetEXWithArgs(ctx, "myhash", redis.HGetEXExpirationEX, 60, "f1", "f2").Result()
opt := redis.HGetEXOptions{
ExpirationType: redis.HGetEXExpirationEX,
ExpirationVal: 60,
}
res, err := client.HGetEXWithArgs(ctx, "myhash", &opt, "f1", "f2").Result()
Expect(err).NotTo(HaveOccurred())
Expect(res).To(Equal([]string{"val1", "val2"}))
// Optionally, verify TTL if your implementation exposes it.
})
It("should HGETEX with PERSIST option", Label("hash", "HGETEX"), func() {
SkipBeforeRedisVersion(8, "requires Redis 8.x")
// Setup: create a hash.
SkipBeforeRedisVersion(7.9, "requires Redis 8.x")
err := client.HSet(ctx, "myhash", "f1", "val1", "f2", "val2").Err()
Expect(err).NotTo(HaveOccurred())
// Call HGETEX with PERSIST (no TTL value needed).
res, err := client.HGetEXWithArgs(ctx, "myhash", redis.HGetEXExpirationPERSIST, 0, "f1", "f2").Result()
opt := redis.HGetEXOptions{ExpirationType: redis.HGetEXExpirationPERSIST}
res, err := client.HGetEXWithArgs(ctx, "myhash", &opt, "f1", "f2").Result()
Expect(err).NotTo(HaveOccurred())
Expect(res).To(Equal([]string{"val1", "val2"}))
})
It("should HGETEX with EXAT option", Label("hash", "HGETEX"), func() {
SkipBeforeRedisVersion(8, "requires Redis 8.x")
// Setup: create a hash.
SkipBeforeRedisVersion(7.9, "requires Redis 8.x")
err := client.HSet(ctx, "myhash", "f1", "val1", "f2", "val2").Err()
Expect(err).NotTo(HaveOccurred())
// Set expiration at a specific Unix timestamp (60 seconds from now).
expireAt := time.Now().Add(60 * time.Second).Unix()
res, err := client.HGetEXWithArgs(ctx, "myhash", redis.HGetEXExpirationEXAT, expireAt, "f1", "f2").Result()
opt := redis.HGetEXOptions{
ExpirationType: redis.HGetEXExpirationEXAT,
ExpirationVal: expireAt,
}
res, err := client.HGetEXWithArgs(ctx, "myhash", &opt, "f1", "f2").Result()
Expect(err).NotTo(HaveOccurred())
Expect(res).To(Equal([]string{"val1", "val2"}))
})
@ -2887,75 +2893,62 @@ var _ = Describe("Commands", func() {
// HSETEX with FNX/FXX options
// -----------------------------
It("should HSETEX with FNX condition", Label("hash", "HSETEX"), func() {
SkipBeforeRedisVersion(8, "requires Redis 8.x")
// Ensure the key is removed.
client.Del(ctx, "myhash")
SkipBeforeRedisVersion(7.9, "requires Redis 8.x")
// FNX: set field only if it does not exist.
opt := redis.HSetXOptions{
opt := redis.HSetEXOptions{
Condition: redis.HSetEXFNX,
ExpirationType: redis.HSetEXExpirationEX,
ExpirationVal: 60,
}
res, err := client.HSetEXWithArgs(ctx, "myhash", &opt, "f1", "val1").Result()
Expect(err).NotTo(HaveOccurred())
// Expect the field to be set.
Expect(res).To(Equal(int64(1)))
opt = redis.HSetXOptions{
opt = redis.HSetEXOptions{
Condition: redis.HSetEXFNX,
ExpirationType: redis.HSetEXExpirationEX,
ExpirationVal: 60,
}
// Attempt to set the same field again with FNX.
res, err = client.HSetEXWithArgs(ctx, "myhash", &opt, "f1", "val2").Result()
Expect(err).NotTo(HaveOccurred())
// Since the field already exists, no update occurs.
Expect(res).To(Equal(int64(0)))
})
It("should HSETEX with FXX condition", Label("hash", "HSETEX"), func() {
SkipBeforeRedisVersion(7.9, "requires Redis 8.x")
// Setup: ensure field f2 exists.
client.Del(ctx, "myhash")
err := client.HSet(ctx, "myhash", "f2", "val1").Err()
Expect(err).NotTo(HaveOccurred())
opt := redis.HSetXOptions{
opt := redis.HSetEXOptions{
Condition: redis.HSetEXFXX,
ExpirationType: redis.HSetEXExpirationEX,
ExpirationVal: 60,
}
// FXX: update field only if it exists.
res, err := client.HSetEXWithArgs(ctx, "myhash", &opt, "f2", "val2").Result()
Expect(err).NotTo(HaveOccurred())
Expect(res).To(Equal(int64(1)))
opt = redis.HSetXOptions{
opt = redis.HSetEXOptions{
Condition: redis.HSetEXFXX,
ExpirationType: redis.HSetEXExpirationEX,
ExpirationVal: 60,
}
// FXX on a non-existing field (f3) should not set the field.
res, err = client.HSetEXWithArgs(ctx, "myhash", &opt, "f3", "val3").Result()
Expect(err).NotTo(HaveOccurred())
Expect(res).To(Equal(int64(0)))
})
It("should HSETEX with multiple field operations", Label("hash", "HSETEX"), func() {
SkipBeforeRedisVersion(8, "requires Redis 8.x")
// Remove key if it exists.
client.Del(ctx, "myhash")
opt := redis.HSetXOptions{
SkipBeforeRedisVersion(7.9, "requires Redis 8.x")
opt := redis.HSetEXOptions{
ExpirationType: redis.HSetEXExpirationEX,
ExpirationVal: 60,
}
// Set multiple fields at once (no condition).
res, err := client.HSetEXWithArgs(ctx, "myhash", &opt, "f1", "val1", "f2", "val2").Result()
Expect(err).NotTo(HaveOccurred())
// Assume 1 indicates all fields were set.
Expect(res).To(Equal(int64(1)))
// Verify that both fields are set.
values, err := client.HMGet(ctx, "myhash", "f1", "f2").Result()
Expect(err).NotTo(HaveOccurred())
Expect(values).To(Equal([]interface{}{"val1", "val2"}))

View File

@ -1,7 +1,5 @@
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=

View File

@ -12,8 +12,7 @@ type HashCmdable interface {
HGetAll(ctx context.Context, key string) *MapStringStringCmd
HGetDel(ctx context.Context, key string, fields ...string) *StringSliceCmd
HGetEX(ctx context.Context, key string, fields ...string) *StringSliceCmd
HGetEXWithArgs(ctx context.Context, key string, expirationType HGetEXExpirationType, expirationVal int64, fields ...string) *StringSliceCmd
HIncrBy(ctx context.Context, key, field string, incr int64) *IntCmd
HGetEXWithArgs(ctx context.Context, key string, options *HGetEXOptions, fields ...string) *StringSliceCmd
HIncrByFloat(ctx context.Context, key, field string, incr float64) *FloatCmd
HKeys(ctx context.Context, key string) *StringSliceCmd
HLen(ctx context.Context, key string) *IntCmd
@ -21,7 +20,7 @@ type HashCmdable interface {
HSet(ctx context.Context, key string, values ...interface{}) *IntCmd
HMSet(ctx context.Context, key string, values ...interface{}) *BoolCmd
HSetEX(ctx context.Context, key string, fieldsAndValues ...string) *IntCmd
HSetEXWithArgs(ctx context.Context, key string, options *HSetXOptions, fieldsAndValues ...string) *IntCmd
HSetEXWithArgs(ctx context.Context, key string, options *HSetEXOptions, fieldsAndValues ...string) *IntCmd
HSetNX(ctx context.Context, key, field string, value interface{}) *BoolCmd
HScan(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd
HScanNoValues(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd
@ -491,12 +490,18 @@ const (
HGetEXExpirationPERSIST HGetEXExpirationType = "PERSIST"
)
func (c cmdable) HGetEXWithArgs(ctx context.Context, key string, expirationType HGetEXExpirationType, expirationVal int64, fields ...string) *StringSliceCmd {
args := []interface{}{"HGETEX", key}
type HGetEXOptions struct {
ExpirationType HGetEXExpirationType
ExpirationVal int64
}
args = append(args, string(expirationType))
if expirationType != HGetEXExpirationPERSIST {
args = append(args, expirationVal)
func (c cmdable) HGetEXWithArgs(ctx context.Context, key string, options *HGetEXOptions, fields ...string) *StringSliceCmd {
args := []interface{}{"HGETEX", key}
if options.ExpirationType != "" {
args = append(args, string(options.ExpirationType))
if options.ExpirationType != HGetEXExpirationPERSIST {
args = append(args, options.ExpirationVal)
}
}
args = append(args, "FIELDS", len(fields))
@ -526,7 +531,7 @@ const (
HSetEXExpirationKEEPTTL HSetEXExpirationType = "KEEPTTL"
)
type HSetXOptions struct {
type HSetEXOptions struct {
Condition HSetEXCondition
ExpirationType HSetEXExpirationType
ExpirationVal int64
@ -543,7 +548,7 @@ func (c cmdable) HSetEX(ctx context.Context, key string, fieldsAndValues ...stri
return cmd
}
func (c cmdable) HSetEXWithArgs(ctx context.Context, key string, options *HSetXOptions, fieldsAndValues ...string) *IntCmd {
func (c cmdable) HSetEXWithArgs(ctx context.Context, key string, options *HSetEXOptions, fieldsAndValues ...string) *IntCmd {
args := []interface{}{"HSETEX", key}
if options.Condition != "" {
args = append(args, string(options.Condition))