mirror of
https://github.com/redis/go-redis.git
synced 2025-07-18 00:20:57 +03:00
Merge branch 'master' into ndyakov/CAE-1088-resp3-notification-handlers
This commit is contained in:
1
.github/actions/run-tests/action.yml
vendored
1
.github/actions/run-tests/action.yml
vendored
@ -25,6 +25,7 @@ runs:
|
|||||||
|
|
||||||
# Mapping of redis version to redis testing containers
|
# Mapping of redis version to redis testing containers
|
||||||
declare -A redis_version_mapping=(
|
declare -A redis_version_mapping=(
|
||||||
|
["8.2.x"]="8.2-M01-pre"
|
||||||
["8.0.x"]="8.0.2"
|
["8.0.x"]="8.0.2"
|
||||||
["7.4.x"]="rs-7.4.0-v5"
|
["7.4.x"]="rs-7.4.0-v5"
|
||||||
["7.2.x"]="rs-7.2.0-v17"
|
["7.2.x"]="rs-7.2.0-v17"
|
||||||
|
3
.github/workflows/build.yml
vendored
3
.github/workflows/build.yml
vendored
@ -18,6 +18,7 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
redis-version:
|
redis-version:
|
||||||
|
- "8.2.x" # Redis CE 8.2
|
||||||
- "8.0.x" # Redis CE 8.0
|
- "8.0.x" # Redis CE 8.0
|
||||||
- "7.4.x" # Redis stack 7.4
|
- "7.4.x" # Redis stack 7.4
|
||||||
go-version:
|
go-version:
|
||||||
@ -43,6 +44,7 @@ jobs:
|
|||||||
|
|
||||||
# Mapping of redis version to redis testing containers
|
# Mapping of redis version to redis testing containers
|
||||||
declare -A redis_version_mapping=(
|
declare -A redis_version_mapping=(
|
||||||
|
["8.2.x"]="8.2-M01-pre"
|
||||||
["8.0.x"]="8.0.2"
|
["8.0.x"]="8.0.2"
|
||||||
["7.4.x"]="rs-7.4.0-v5"
|
["7.4.x"]="rs-7.4.0-v5"
|
||||||
)
|
)
|
||||||
@ -72,6 +74,7 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
redis-version:
|
redis-version:
|
||||||
|
- "8.2.x" # Redis CE 8.2
|
||||||
- "8.0.x" # Redis CE 8.0
|
- "8.0.x" # Redis CE 8.0
|
||||||
- "7.4.x" # Redis stack 7.4
|
- "7.4.x" # Redis stack 7.4
|
||||||
- "7.2.x" # Redis stack 7.2
|
- "7.2.x" # Redis stack 7.2
|
||||||
|
@ -12,6 +12,10 @@ type BitMapCmdable interface {
|
|||||||
BitOpAnd(ctx context.Context, destKey string, keys ...string) *IntCmd
|
BitOpAnd(ctx context.Context, destKey string, keys ...string) *IntCmd
|
||||||
BitOpOr(ctx context.Context, destKey string, keys ...string) *IntCmd
|
BitOpOr(ctx context.Context, destKey string, keys ...string) *IntCmd
|
||||||
BitOpXor(ctx context.Context, destKey string, keys ...string) *IntCmd
|
BitOpXor(ctx context.Context, destKey string, keys ...string) *IntCmd
|
||||||
|
BitOpDiff(ctx context.Context, destKey string, keys ...string) *IntCmd
|
||||||
|
BitOpDiff1(ctx context.Context, destKey string, keys ...string) *IntCmd
|
||||||
|
BitOpAndOr(ctx context.Context, destKey string, keys ...string) *IntCmd
|
||||||
|
BitOpOne(ctx context.Context, destKey string, keys ...string) *IntCmd
|
||||||
BitOpNot(ctx context.Context, destKey string, key string) *IntCmd
|
BitOpNot(ctx context.Context, destKey string, key string) *IntCmd
|
||||||
BitPos(ctx context.Context, key string, bit int64, pos ...int64) *IntCmd
|
BitPos(ctx context.Context, key string, bit int64, pos ...int64) *IntCmd
|
||||||
BitPosSpan(ctx context.Context, key string, bit int8, start, end int64, span string) *IntCmd
|
BitPosSpan(ctx context.Context, key string, bit int8, start, end int64, span string) *IntCmd
|
||||||
@ -78,22 +82,50 @@ func (c cmdable) bitOp(ctx context.Context, op, destKey string, keys ...string)
|
|||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BitOpAnd creates a new bitmap in which users are members of all given bitmaps
|
||||||
func (c cmdable) BitOpAnd(ctx context.Context, destKey string, keys ...string) *IntCmd {
|
func (c cmdable) BitOpAnd(ctx context.Context, destKey string, keys ...string) *IntCmd {
|
||||||
return c.bitOp(ctx, "and", destKey, keys...)
|
return c.bitOp(ctx, "and", destKey, keys...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BitOpOr creates a new bitmap in which users are member of at least one given bitmap
|
||||||
func (c cmdable) BitOpOr(ctx context.Context, destKey string, keys ...string) *IntCmd {
|
func (c cmdable) BitOpOr(ctx context.Context, destKey string, keys ...string) *IntCmd {
|
||||||
return c.bitOp(ctx, "or", destKey, keys...)
|
return c.bitOp(ctx, "or", destKey, keys...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BitOpXor creates a new bitmap in which users are the result of XORing all given bitmaps
|
||||||
func (c cmdable) BitOpXor(ctx context.Context, destKey string, keys ...string) *IntCmd {
|
func (c cmdable) BitOpXor(ctx context.Context, destKey string, keys ...string) *IntCmd {
|
||||||
return c.bitOp(ctx, "xor", destKey, keys...)
|
return c.bitOp(ctx, "xor", destKey, keys...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BitOpNot creates a new bitmap in which users are not members of a given bitmap
|
||||||
func (c cmdable) BitOpNot(ctx context.Context, destKey string, key string) *IntCmd {
|
func (c cmdable) BitOpNot(ctx context.Context, destKey string, key string) *IntCmd {
|
||||||
return c.bitOp(ctx, "not", destKey, key)
|
return c.bitOp(ctx, "not", destKey, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BitOpDiff creates a new bitmap in which users are members of bitmap X but not of any of bitmaps Y1, Y2, …
|
||||||
|
// Introduced with Redis 8.2
|
||||||
|
func (c cmdable) BitOpDiff(ctx context.Context, destKey string, keys ...string) *IntCmd {
|
||||||
|
return c.bitOp(ctx, "diff", destKey, keys...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BitOpDiff1 creates a new bitmap in which users are members of one or more of bitmaps Y1, Y2, … but not members of bitmap X
|
||||||
|
// Introduced with Redis 8.2
|
||||||
|
func (c cmdable) BitOpDiff1(ctx context.Context, destKey string, keys ...string) *IntCmd {
|
||||||
|
return c.bitOp(ctx, "diff1", destKey, keys...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BitOpAndOr creates a new bitmap in which users are members of bitmap X and also members of one or more of bitmaps Y1, Y2, …
|
||||||
|
// Introduced with Redis 8.2
|
||||||
|
func (c cmdable) BitOpAndOr(ctx context.Context, destKey string, keys ...string) *IntCmd {
|
||||||
|
return c.bitOp(ctx, "andor", destKey, keys...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BitOpOne creates a new bitmap in which users are members of exactly one of the given bitmaps
|
||||||
|
// Introduced with Redis 8.2
|
||||||
|
func (c cmdable) BitOpOne(ctx context.Context, destKey string, keys ...string) *IntCmd {
|
||||||
|
return c.bitOp(ctx, "one", destKey, keys...)
|
||||||
|
}
|
||||||
|
|
||||||
// BitPos is an API before Redis version 7.0, cmd: bitpos key bit start end
|
// BitPos is an API before Redis version 7.0, cmd: bitpos key bit start end
|
||||||
// if you need the `byte | bit` parameter, please use `BitPosSpan`.
|
// if you need the `byte | bit` parameter, please use `BitPosSpan`.
|
||||||
func (c cmdable) BitPos(ctx context.Context, key string, bit int64, pos ...int64) *IntCmd {
|
func (c cmdable) BitPos(ctx context.Context, key string, bit int64, pos ...int64) *IntCmd {
|
||||||
|
@ -5197,6 +5197,9 @@ type ClientInfo struct {
|
|||||||
OutputListLength int // oll, output list length (replies are queued in this list when the buffer is full)
|
OutputListLength int // oll, output list length (replies are queued in this list when the buffer is full)
|
||||||
OutputMemory int // omem, output buffer memory usage
|
OutputMemory int // omem, output buffer memory usage
|
||||||
TotalMemory int // tot-mem, total memory consumed by this client in its various buffers
|
TotalMemory int // tot-mem, total memory consumed by this client in its various buffers
|
||||||
|
TotalNetIn int // tot-net-in, total network input
|
||||||
|
TotalNetOut int // tot-net-out, total network output
|
||||||
|
TotalCmds int // tot-cmds, total number of commands processed
|
||||||
IoThread int // io-thread id
|
IoThread int // io-thread id
|
||||||
Events string // file descriptor events (see below)
|
Events string // file descriptor events (see below)
|
||||||
LastCmd string // cmd, last command played
|
LastCmd string // cmd, last command played
|
||||||
@ -5362,6 +5365,12 @@ func parseClientInfo(txt string) (info *ClientInfo, err error) {
|
|||||||
info.OutputMemory, err = strconv.Atoi(val)
|
info.OutputMemory, err = strconv.Atoi(val)
|
||||||
case "tot-mem":
|
case "tot-mem":
|
||||||
info.TotalMemory, err = strconv.Atoi(val)
|
info.TotalMemory, err = strconv.Atoi(val)
|
||||||
|
case "tot-net-in":
|
||||||
|
info.TotalNetIn, err = strconv.Atoi(val)
|
||||||
|
case "tot-net-out":
|
||||||
|
info.TotalNetOut, err = strconv.Atoi(val)
|
||||||
|
case "tot-cmds":
|
||||||
|
info.TotalCmds, err = strconv.Atoi(val)
|
||||||
case "events":
|
case "events":
|
||||||
info.Events = val
|
info.Events = val
|
||||||
case "cmd":
|
case "cmd":
|
||||||
|
@ -1469,6 +1469,82 @@ var _ = Describe("Commands", func() {
|
|||||||
Expect(get.Val()).To(Equal("\xf0"))
|
Expect(get.Val()).To(Equal("\xf0"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("should BitOpDiff", Label("NonRedisEnterprise"), func() {
|
||||||
|
SkipBeforeRedisVersion(8.2, "BITOP DIFF is available since Redis 8.2")
|
||||||
|
set := client.Set(ctx, "key1", "\xff", 0)
|
||||||
|
Expect(set.Err()).NotTo(HaveOccurred())
|
||||||
|
Expect(set.Val()).To(Equal("OK"))
|
||||||
|
|
||||||
|
set = client.Set(ctx, "key2", "\x0f", 0)
|
||||||
|
Expect(set.Err()).NotTo(HaveOccurred())
|
||||||
|
Expect(set.Val()).To(Equal("OK"))
|
||||||
|
|
||||||
|
bitOpDiff := client.BitOpDiff(ctx, "dest", "key1", "key2")
|
||||||
|
Expect(bitOpDiff.Err()).NotTo(HaveOccurred())
|
||||||
|
Expect(bitOpDiff.Val()).To(Equal(int64(1)))
|
||||||
|
|
||||||
|
get := client.Get(ctx, "dest")
|
||||||
|
Expect(get.Err()).NotTo(HaveOccurred())
|
||||||
|
Expect(get.Val()).To(Equal("\xf0"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should BitOpDiff1", Label("NonRedisEnterprise"), func() {
|
||||||
|
SkipBeforeRedisVersion(8.2, "BITOP DIFF is available since Redis 8.2")
|
||||||
|
set := client.Set(ctx, "key1", "\xff", 0)
|
||||||
|
Expect(set.Err()).NotTo(HaveOccurred())
|
||||||
|
Expect(set.Val()).To(Equal("OK"))
|
||||||
|
|
||||||
|
set = client.Set(ctx, "key2", "\x0f", 0)
|
||||||
|
Expect(set.Err()).NotTo(HaveOccurred())
|
||||||
|
Expect(set.Val()).To(Equal("OK"))
|
||||||
|
|
||||||
|
bitOpDiff1 := client.BitOpDiff1(ctx, "dest", "key1", "key2")
|
||||||
|
Expect(bitOpDiff1.Err()).NotTo(HaveOccurred())
|
||||||
|
Expect(bitOpDiff1.Val()).To(Equal(int64(1)))
|
||||||
|
|
||||||
|
get := client.Get(ctx, "dest")
|
||||||
|
Expect(get.Err()).NotTo(HaveOccurred())
|
||||||
|
Expect(get.Val()).To(Equal("\x00"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should BitOpAndOr", Label("NonRedisEnterprise"), func() {
|
||||||
|
SkipBeforeRedisVersion(8.2, "BITOP ANDOR is available since Redis 8.2")
|
||||||
|
set := client.Set(ctx, "key1", "\xff", 0)
|
||||||
|
Expect(set.Err()).NotTo(HaveOccurred())
|
||||||
|
Expect(set.Val()).To(Equal("OK"))
|
||||||
|
|
||||||
|
set = client.Set(ctx, "key2", "\x0f", 0)
|
||||||
|
Expect(set.Err()).NotTo(HaveOccurred())
|
||||||
|
Expect(set.Val()).To(Equal("OK"))
|
||||||
|
|
||||||
|
bitOpAndOr := client.BitOpAndOr(ctx, "dest", "key1", "key2")
|
||||||
|
Expect(bitOpAndOr.Err()).NotTo(HaveOccurred())
|
||||||
|
Expect(bitOpAndOr.Val()).To(Equal(int64(1)))
|
||||||
|
|
||||||
|
get := client.Get(ctx, "dest")
|
||||||
|
Expect(get.Err()).NotTo(HaveOccurred())
|
||||||
|
Expect(get.Val()).To(Equal("\x0f"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should BitOpOne", Label("NonRedisEnterprise"), func() {
|
||||||
|
SkipBeforeRedisVersion(8.2, "BITOP ONE is available since Redis 8.2")
|
||||||
|
set := client.Set(ctx, "key1", "\xff", 0)
|
||||||
|
Expect(set.Err()).NotTo(HaveOccurred())
|
||||||
|
Expect(set.Val()).To(Equal("OK"))
|
||||||
|
|
||||||
|
set = client.Set(ctx, "key2", "\x0f", 0)
|
||||||
|
Expect(set.Err()).NotTo(HaveOccurred())
|
||||||
|
Expect(set.Val()).To(Equal("OK"))
|
||||||
|
|
||||||
|
bitOpOne := client.BitOpOne(ctx, "dest", "key1", "key2")
|
||||||
|
Expect(bitOpOne.Err()).NotTo(HaveOccurred())
|
||||||
|
Expect(bitOpOne.Val()).To(Equal(int64(1)))
|
||||||
|
|
||||||
|
get := client.Get(ctx, "dest")
|
||||||
|
Expect(get.Err()).NotTo(HaveOccurred())
|
||||||
|
Expect(get.Val()).To(Equal("\xf0"))
|
||||||
|
})
|
||||||
|
|
||||||
It("should BitOpNot", Label("NonRedisEnterprise"), func() {
|
It("should BitOpNot", Label("NonRedisEnterprise"), func() {
|
||||||
set := client.Set(ctx, "key1", "\x00", 0)
|
set := client.Set(ctx, "key1", "\x00", 0)
|
||||||
Expect(set.Err()).NotTo(HaveOccurred())
|
Expect(set.Err()).NotTo(HaveOccurred())
|
||||||
|
16
ring.go
16
ring.go
@ -798,6 +798,8 @@ func (c *Ring) generalProcessPipeline(
|
|||||||
}
|
}
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
errs := make(chan error, len(cmdsMap))
|
||||||
|
|
||||||
for hash, cmds := range cmdsMap {
|
for hash, cmds := range cmdsMap {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(hash string, cmds []Cmder) {
|
go func(hash string, cmds []Cmder) {
|
||||||
@ -810,16 +812,24 @@ func (c *Ring) generalProcessPipeline(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hook := shard.Client.processPipelineHook
|
||||||
if tx {
|
if tx {
|
||||||
cmds = wrapMultiExec(ctx, cmds)
|
cmds = wrapMultiExec(ctx, cmds)
|
||||||
_ = shard.Client.processTxPipelineHook(ctx, cmds)
|
hook = shard.Client.processTxPipelineHook
|
||||||
} else {
|
}
|
||||||
_ = shard.Client.processPipelineHook(ctx, cmds)
|
|
||||||
|
if err = hook(ctx, cmds); err != nil {
|
||||||
|
errs <- err
|
||||||
}
|
}
|
||||||
}(hash, cmds)
|
}(hash, cmds)
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
close(errs)
|
||||||
|
|
||||||
|
if err := <-errs; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return cmdsFirstErr(cmds)
|
return cmdsFirstErr(cmds)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
15
ring_test.go
15
ring_test.go
@ -277,6 +277,21 @@ var _ = Describe("Redis Ring", func() {
|
|||||||
Expect(ringShard1.Info(ctx).Val()).ToNot(ContainSubstring("keys="))
|
Expect(ringShard1.Info(ctx).Val()).ToNot(ContainSubstring("keys="))
|
||||||
Expect(ringShard2.Info(ctx).Val()).To(ContainSubstring("keys=100"))
|
Expect(ringShard2.Info(ctx).Val()).To(ContainSubstring("keys=100"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("return dial timeout error", func() {
|
||||||
|
opt := redisRingOptions()
|
||||||
|
opt.DialTimeout = 250 * time.Millisecond
|
||||||
|
opt.Addrs = map[string]string{"ringShardNotExist": ":1997"}
|
||||||
|
ring = redis.NewRing(opt)
|
||||||
|
|
||||||
|
_, err := ring.Pipelined(ctx, func(pipe redis.Pipeliner) error {
|
||||||
|
pipe.HSet(ctx, "key", "value")
|
||||||
|
pipe.Expire(ctx, "key", time.Minute)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
Expect(err).To(HaveOccurred())
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("new client callback", func() {
|
Describe("new client callback", func() {
|
||||||
|
Reference in New Issue
Block a user