diff --git a/.github/actions/run-tests/action.yml b/.github/actions/run-tests/action.yml index e9bb7e797..bba991972 100644 --- a/.github/actions/run-tests/action.yml +++ b/.github/actions/run-tests/action.yml @@ -25,6 +25,7 @@ runs: # Mapping of redis version to redis testing containers declare -A redis_version_mapping=( + ["8.2.x"]="8.2-M01-pre" ["8.0.x"]="8.0.2" ["7.4.x"]="rs-7.4.0-v5" ["7.2.x"]="rs-7.2.0-v17" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c8b3d1b68..dd097a9fa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,6 +18,7 @@ jobs: fail-fast: false matrix: redis-version: + - "8.2.x" # Redis CE 8.2 - "8.0.x" # Redis CE 8.0 - "7.4.x" # Redis stack 7.4 go-version: @@ -43,6 +44,7 @@ jobs: # Mapping of redis version to redis testing containers declare -A redis_version_mapping=( + ["8.2.x"]="8.2-M01-pre" ["8.0.x"]="8.0.2" ["7.4.x"]="rs-7.4.0-v5" ) @@ -72,6 +74,7 @@ jobs: fail-fast: false matrix: redis-version: + - "8.2.x" # Redis CE 8.2 - "8.0.x" # Redis CE 8.0 - "7.4.x" # Redis stack 7.4 - "7.2.x" # Redis stack 7.2 diff --git a/bitmap_commands.go b/bitmap_commands.go index a21558289..4dbc862a1 100644 --- a/bitmap_commands.go +++ b/bitmap_commands.go @@ -12,6 +12,10 @@ type BitMapCmdable interface { BitOpAnd(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 + 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 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 @@ -78,22 +82,50 @@ func (c cmdable) bitOp(ctx context.Context, op, destKey string, keys ...string) 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 { 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 { 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 { 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 { 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 // if you need the `byte | bit` parameter, please use `BitPosSpan`. func (c cmdable) BitPos(ctx context.Context, key string, bit int64, pos ...int64) *IntCmd { diff --git a/command.go b/command.go index 652e241be..9d9d2848c 100644 --- a/command.go +++ b/command.go @@ -5138,6 +5138,9 @@ type ClientInfo struct { OutputListLength int // oll, output list length (replies are queued in this list when the buffer is full) OutputMemory int // omem, output buffer memory usage 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 Events string // file descriptor events (see below) LastCmd string // cmd, last command played @@ -5303,6 +5306,12 @@ func parseClientInfo(txt string) (info *ClientInfo, err error) { info.OutputMemory, err = strconv.Atoi(val) case "tot-mem": 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": info.Events = val case "cmd": diff --git a/commands_test.go b/commands_test.go index 72b206943..19548e134 100644 --- a/commands_test.go +++ b/commands_test.go @@ -1469,6 +1469,82 @@ var _ = Describe("Commands", func() { 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() { set := client.Set(ctx, "key1", "\x00", 0) Expect(set.Err()).NotTo(HaveOccurred())