Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: redis/go-redis
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v9.4.0
Choose a base ref
...
head repository: redis/go-redis
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v9.6.1
Choose a head ref
Loading
Showing with 1,471 additions and 726 deletions.
  1. +3 −0 .github/wordlist.txt
  2. +3 −3 .github/workflows/build.yml
  3. +1 −1 .github/workflows/golangci-lint.yml
  4. +1 −1 .github/workflows/release-drafter.yml
  5. +1 −1 .github/workflows/spellcheck.yml
  6. +6 −8 .github/workflows/test-redis-enterprise.yml
  7. +9 −0 CHANGELOG.md
  8. +6 −1 Makefile
  9. +26 −5 README.md
  10. +18 −6 bitmap_commands.go
  11. +98 −0 bitmap_commands_test.go
  12. +21 −1 command.go
  13. +1 −1 commands.go
  14. +294 −3 commands_test.go
  15. +3 −0 error.go
  16. +1 −1 example/del-keys-without-ttl/go.mod
  17. +2 −2 example/del-keys-without-ttl/go.sum
  18. +1 −1 example/hll/go.mod
  19. +2 −2 example/hll/go.sum
  20. +1 −1 example/lua-scripting/go.mod
  21. +2 −2 example/lua-scripting/go.sum
  22. +10 −10 example/otel/config/otel-collector.yaml
  23. +3 −3 example/otel/docker-compose.yml
  24. +25 −25 example/otel/go.mod
  25. +47 −447 example/otel/go.sum
  26. +44 −38 example/otel/uptrace.yml
  27. +1 −1 example/redis-bloom/go.mod
  28. +2 −2 example/redis-bloom/go.sum
  29. +1 −1 example/scan-struct/go.mod
  30. +2 −2 example/scan-struct/go.sum
  31. +26 −0 example/scan-struct/main.go
  32. +24 −2 example_test.go
  33. +9 −4 extra/rediscensus/go.mod
  34. +2 −4 extra/rediscensus/go.sum
  35. +9 −4 extra/rediscmd/go.mod
  36. +4 −4 extra/rediscmd/go.sum
  37. +1 −1 extra/redisotel/config.go
  38. +8 −8 extra/redisotel/go.mod
  39. +16 −18 extra/redisotel/go.sum
  40. +5 −5 extra/redisotel/redisotel_test.go
  41. +39 −22 extra/redisotel/tracing.go
  42. +3 −3 extra/redisprometheus/go.mod
  43. +4 −4 extra/redisprometheus/go.sum
  44. +7 −0 generic_commands.go
  45. +5 −0 go.mod
  46. +277 −1 hash_commands.go
  47. +22 −0 internal/pool/conn.go
  48. +1 −10 internal/pool/conn_check.go
  49. +2 −2 internal/pool/conn_check_dummy.go
  50. +31 −4 internal/pool/conn_check_test.go
  51. +16 −2 internal/pool/pool.go
  52. +37 −0 internal/util.go
  53. +74 −0 internal/util_test.go
  54. +16 −0 iterator_test.go
  55. +3 −3 json_test.go
  56. +61 −0 monitor_test.go
  57. +9 −3 options.go
  58. +53 −21 osscluster.go
  59. +26 −0 osscluster_test.go
  60. +0 −8 package.json
  61. +2 −2 pubsub.go
  62. +21 −14 redis.go
  63. +2 −2 redis_test.go
  64. +0 −3 scripts/release.sh
  65. +6 −0 sentinel.go
  66. +1 −1 sentinel_test.go
  67. +13 −1 stream_commands.go
  68. +1 −1 version.go
3 changes: 3 additions & 0 deletions .github/wordlist.txt
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ ACLs
autoload
autoloader
autoloading
analytics
Autoloading
backend
backends
@@ -13,6 +14,7 @@ customizable
Customizable
dataset
de
DisableIdentity
ElastiCache
extensibility
FPM
@@ -43,6 +45,7 @@ RocksDB
runtime
SHA
sharding
SETNAME
SSL
struct
stunnel
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -2,9 +2,9 @@ name: Go

on:
push:
branches: [master, v9]
branches: [master, v9, v9.6]
pull_request:
branches: [master, v9]
branches: [master, v9, v9.6]

permissions:
contents: read
@@ -20,7 +20,7 @@ jobs:

services:
redis:
image: redis/redis-stack-server:edge
image: redis/redis-stack-server:7.4.0-rc2
options: >-
--health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5
ports:
2 changes: 1 addition & 1 deletion .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
@@ -23,4 +23,4 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
uses: golangci/golangci-lint-action@v6
2 changes: 1 addition & 1 deletion .github/workflows/release-drafter.yml
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
steps:
# Drafts your next Release notes as Pull Requests are merged into "master"
- uses: release-drafter/release-drafter@v5
- uses: release-drafter/release-drafter@v6
with:
# (Optional) specify config name to use, relative to .github/. Default: release-drafter.yml
config-name: release-drafter-config.yml
2 changes: 1 addition & 1 deletion .github/workflows/spellcheck.yml
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- name: Check Spelling
uses: rojopolis/spellcheck-github-actions@0.35.0
uses: rojopolis/spellcheck-github-actions@0.38.0
with:
config_path: .github/spellcheck-settings.yml
task_name: Markdown
14 changes: 6 additions & 8 deletions .github/workflows/test-redis-enterprise.yml
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ jobs:
fail-fast: false
matrix:
go-version: [1.21.x]
re-build: ["7.2.4-92"]
re-build: ["7.4.2-54"]

steps:
- name: Checkout code
@@ -36,14 +36,12 @@ jobs:
- name: Build cluster
working-directory: redis-ee
env:
IMAGE: "redislabs/redis-internal:${{ matrix.re-build }}"
RE_USERNAME: ${{ secrets.RE_USERNAME }}
RE_PASS: ${{ secrets.RE_PASS }}
RE_CLUSTER_NAME: ${{ secrets.RE_CLUSTER_NAME }}
IMAGE: "redislabs/redis:${{ matrix.re-build }}"
RE_USERNAME: test@test.com
RE_PASS: 12345
RE_CLUSTER_NAME: re-test
RE_USE_OSS_CLUSTER: false
RE_DB_PORT: ${{ secrets.RE_DB_PORT }}
DOCKER_ACCESS_TOKEN: ${{ secrets.DOCKER_ACCESS_TOKEN }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
RE_DB_PORT: 6379
run: ./build.sh

- name: Test
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
## Unreleased

### Changed

* `go-redis` won't skip span creation if the parent spans is not recording. ([#2980](https://github.com/redis/go-redis/issues/2980))
Users can use the OpenTelemetry sampler to control the sampling behavior.
For instance, you can use the `ParentBased(NeverSample())` sampler from `go.opentelemetry.io/otel/sdk/trace` to keep
a similar behavior (drop orphan spans) of `go-redis` as before.

## [9.0.5](https://github.com/redis/go-redis/compare/v9.0.4...v9.0.5) (2023-05-29)


7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
GO_MOD_DIRS := $(shell find . -type f -name 'go.mod' -exec dirname {} \; | sort)

test: testdeps
$(eval GO_VERSION := $(shell go version | cut -d " " -f 3 | cut -d. -f2))
set -e; for dir in $(GO_MOD_DIRS); do \
if echo "$${dir}" | grep -q "./example" && [ "$(GO_VERSION)" = "19" ]; then \
echo "Skipping go test in $${dir} due to Go version 1.19 and dir contains ./example"; \
continue; \
fi; \
echo "go test in $${dir}"; \
(cd "$${dir}" && \
go mod tidy -compat=1.18 && \
@@ -26,7 +31,7 @@ build:

testdata/redis:
mkdir -p $@
wget -qO- https://download.redis.io/releases/redis-7.2.1.tar.gz | tar xvz --strip-components=1 -C $@
wget -qO- https://download.redis.io/releases/redis-7.4-rc2.tar.gz | tar xvz --strip-components=1 -C $@

testdata/redis/src/redis-server: testdata/redis
cd $< && make all
31 changes: 26 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -51,8 +51,8 @@ key value NoSQL database that uses RocksDB as storage engine and is compatible w

## Features

- Redis 3 commands except QUIT, MONITOR, and SYNC.
- Automatic connection pooling with
- Redis commands except QUIT and SYNC.
- Automatic connection pooling.
- [Pub/Sub](https://redis.uptrace.dev/guide/go-redis-pubsub.html).
- [Pipelines and transactions](https://redis.uptrace.dev/guide/go-redis-pipelines.html).
- [Scripting](https://redis.uptrace.dev/guide/lua-scripting.html).
@@ -143,9 +143,6 @@ to this specification.

```go
import (
"context"
"fmt"

"github.com/redis/go-redis/v9"
)

@@ -161,6 +158,30 @@ func ExampleClient() *redis.Client {

```


### Advanced Configuration

go-redis supports extending the client identification phase to allow projects to send their own custom client identification.

#### Default Client Identification

By default, go-redis automatically sends the client library name and version during the connection process. This feature is available in redis-server as of version 7.2. As a result, the command is "fire and forget", meaning it should fail silently, in the case that the redis server does not support this feature.

#### Disabling Identity Verification

When connection identity verification is not required or needs to be explicitly disabled, a `DisableIndentity` configuration option exists. In V10 of this library, `DisableIndentity` will become `DisableIdentity` in order to fix the associated typo.

To disable verification, set the `DisableIndentity` option to `true` in the Redis client options:

```go
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "",
DB: 0,
DisableIndentity: true, // Disable set-info on connect
})
```

## Contributing

Please see [out contributing guidelines](CONTRIBUTING.md) to help us improve this library!
24 changes: 18 additions & 6 deletions bitmap_commands.go
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ package redis

import (
"context"
"errors"
)

type BitMapCmdable interface {
@@ -15,6 +16,7 @@ type BitMapCmdable interface {
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
BitField(ctx context.Context, key string, values ...interface{}) *IntSliceCmd
BitFieldRO(ctx context.Context, key string, values ...interface{}) *IntSliceCmd
}

func (c cmdable) GetBit(ctx context.Context, key string, offset int64) *IntCmd {
@@ -37,16 +39,26 @@ func (c cmdable) SetBit(ctx context.Context, key string, offset int64, value int

type BitCount struct {
Start, End int64
Unit string // BYTE(default) | BIT
}

const BitCountIndexByte string = "BYTE"
const BitCountIndexBit string = "BIT"

func (c cmdable) BitCount(ctx context.Context, key string, bitCount *BitCount) *IntCmd {
args := []interface{}{"bitcount", key}
args := make([]any, 2, 5)
args[0] = "bitcount"
args[1] = key
if bitCount != nil {
args = append(
args,
bitCount.Start,
bitCount.End,
)
args = append(args, bitCount.Start, bitCount.End)
if bitCount.Unit != "" {
if bitCount.Unit != BitCountIndexByte && bitCount.Unit != BitCountIndexBit {
cmd := NewIntCmd(ctx)
cmd.SetErr(errors.New("redis: invalid bitcount index"))
return cmd
}
args = append(args, bitCount.Unit)
}
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
98 changes: 98 additions & 0 deletions bitmap_commands_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package redis_test

import (
. "github.com/bsm/ginkgo/v2"
. "github.com/bsm/gomega"
"github.com/redis/go-redis/v9"
)

type bitCountExpected struct {
Start int64
End int64
Expected int64
}

var _ = Describe("BitCountBite", func() {
var client *redis.Client
key := "bit_count_test"

BeforeEach(func() {
client = redis.NewClient(redisOptions())
Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred())
values := []int{0, 1, 0, 0, 1, 0, 1, 0, 1, 1}
for i, v := range values {
cmd := client.SetBit(ctx, key, int64(i), v)
Expect(cmd.Err()).NotTo(HaveOccurred())
}
})

AfterEach(func() {
Expect(client.Close()).NotTo(HaveOccurred())
})

It("bit count bite", func() {
var expected = []bitCountExpected{
{0, 0, 0},
{0, 1, 1},
{0, 2, 1},
{0, 3, 1},
{0, 4, 2},
{0, 5, 2},
{0, 6, 3},
{0, 7, 3},
{0, 8, 4},
{0, 9, 5},
}

for _, e := range expected {
cmd := client.BitCount(ctx, key, &redis.BitCount{Start: e.Start, End: e.End, Unit: redis.BitCountIndexBit})
Expect(cmd.Err()).NotTo(HaveOccurred())
Expect(cmd.Val()).To(Equal(e.Expected))
}
})
})

var _ = Describe("BitCountByte", func() {
var client *redis.Client
key := "bit_count_test"

BeforeEach(func() {
client = redis.NewClient(redisOptions())
Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred())
values := []int{0, 0, 0, 0, 0, 0, 0, 1, 1, 1}
for i, v := range values {
cmd := client.SetBit(ctx, key, int64(i), v)
Expect(cmd.Err()).NotTo(HaveOccurred())
}
})

AfterEach(func() {
Expect(client.Close()).NotTo(HaveOccurred())
})

It("bit count byte", func() {
var expected = []bitCountExpected{
{0, 0, 1},
{0, 1, 3},
}

for _, e := range expected {
cmd := client.BitCount(ctx, key, &redis.BitCount{Start: e.Start, End: e.End, Unit: redis.BitCountIndexByte})
Expect(cmd.Err()).NotTo(HaveOccurred())
Expect(cmd.Val()).To(Equal(e.Expected))
}
})

It("bit count byte with no unit specified", func() {
var expected = []bitCountExpected{
{0, 0, 1},
{0, 1, 3},
}

for _, e := range expected {
cmd := client.BitCount(ctx, key, &redis.BitCount{Start: e.Start, End: e.End})
Expect(cmd.Err()).NotTo(HaveOccurred())
Expect(cmd.Val()).To(Equal(e.Expected))
}
})
})
22 changes: 21 additions & 1 deletion command.go
Original file line number Diff line number Diff line change
@@ -573,6 +573,10 @@ func (cmd *StatusCmd) Result() (string, error) {
return cmd.val, cmd.err
}

func (cmd *StatusCmd) Bytes() ([]byte, error) {
return util.StringToBytes(cmd.val), cmd.err
}

func (cmd *StatusCmd) String() string {
return cmdString(cmd, cmd.val)
}
@@ -4997,6 +5001,7 @@ type ClientInfo struct {
PSub int // number of pattern matching subscriptions
SSub int // redis version 7.0.3, number of shard channel subscriptions
Multi int // number of commands in a MULTI/EXEC context
Watch int // redis version 7.4 RC1, number of keys this client is currently watching.
QueryBuf int // qbuf, query buffer length (0 means no query pending)
QueryBufFree int // qbuf-free, free space of the query buffer (0 means the buffer is full)
ArgvMem int // incomplete arguments for the next command (already extracted from query buffer)
@@ -5149,6 +5154,8 @@ func parseClientInfo(txt string) (info *ClientInfo, err error) {
info.SSub, err = strconv.Atoi(val)
case "multi":
info.Multi, err = strconv.Atoi(val)
case "watch":
info.Watch, err = strconv.Atoi(val)
case "qbuf":
info.QueryBuf, err = strconv.Atoi(val)
case "qbuf-free":
@@ -5310,6 +5317,16 @@ type LibraryInfo struct {
LibVer *string
}

// WithLibraryName returns a valid LibraryInfo with library name only.
func WithLibraryName(libName string) LibraryInfo {
return LibraryInfo{LibName: &libName}
}

// WithLibraryVersion returns a valid LibraryInfo with library version only.
func WithLibraryVersion(libVer string) LibraryInfo {
return LibraryInfo{LibVer: &libVer}
}

// -------------------------------------------

type InfoCmd struct {
@@ -5444,9 +5461,12 @@ func (cmd *MonitorCmd) readMonitor(rd *proto.Reader, cancel context.CancelFunc)
for {
cmd.mu.Lock()
st := cmd.status
pk, _ := rd.Peek(1)
cmd.mu.Unlock()
if pk, _ := rd.Peek(1); len(pk) != 0 && st == monitorStatusStart {
if len(pk) != 0 && st == monitorStatusStart {
cmd.mu.Lock()
line, err := rd.ReadString()
cmd.mu.Unlock()
if err != nil {
return err
}
Loading