Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

release: 9.7.1 patch #3278

Merged
merged 15 commits into from
Feb 21, 2025
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ stunnel
SynDump
TCP
TLS
UnstableResp
uri
URI
url
Expand All @@ -62,3 +63,5 @@ RedisStack
RedisGears
RedisTimeseries
RediSearch
RawResult
RawVal
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,21 @@ rdb := redis.NewClient(&redis.Options{
#### Unstable RESP3 Structures for RediSearch Commands
When integrating Redis with application functionalities using RESP3, it's important to note that some response structures aren't final yet. This is especially true for more complex structures like search and query results. We recommend using RESP2 when using the search and query capabilities, but we plan to stabilize the RESP3-based API-s in the coming versions. You can find more guidance in the upcoming release notes.

To enable unstable RESP3, set the option in your client configuration:

```go
redis.NewClient(&redis.Options{
UnstableResp3: true,
})
```
**Note:** When UnstableResp3 mode is enabled, it's necessary to use RawResult() and RawVal() to retrieve a raw data.
Since, raw response is the only option for unstable search commands Val() and Result() calls wouldn't have any affect on them:

```go
res1, err := client.FTSearchWithArgs(ctx, "txt", "foo bar", &redis.FTSearchOptions{}).RawResult()
val1 := client.FTSearchWithArgs(ctx, "txt", "foo bar", &redis.FTSearchOptions{}).RawVal()
```

## Contributing

Please see [out contributing guidelines](CONTRIBUTING.md) to help us improve this library!
Expand Down
2 changes: 1 addition & 1 deletion commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ var _ = Describe("Commands", func() {

killed := client.ClientKillByFilter(ctx, "MAXAGE", "1")
Expect(killed.Err()).NotTo(HaveOccurred())
Expect(killed.Val()).To(SatisfyAny(Equal(int64(2)), Equal(int64(3))))
Expect(killed.Val()).To(BeNumerically(">=", 2))

select {
case <-done:
Expand Down
2 changes: 1 addition & 1 deletion example/del-keys-without-ttl/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.18
replace github.com/redis/go-redis/v9 => ../..

require (
github.com/redis/go-redis/v9 v9.7.0
github.com/redis/go-redis/v9 v9.7.1
go.uber.org/zap v1.24.0
)

Expand Down
2 changes: 1 addition & 1 deletion example/hll/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.18

replace github.com/redis/go-redis/v9 => ../..

require github.com/redis/go-redis/v9 v9.7.0
require github.com/redis/go-redis/v9 v9.7.1

require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
Expand Down
2 changes: 1 addition & 1 deletion example/lua-scripting/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.18

replace github.com/redis/go-redis/v9 => ../..

require github.com/redis/go-redis/v9 v9.7.0
require github.com/redis/go-redis/v9 v9.7.1

require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
Expand Down
6 changes: 3 additions & 3 deletions example/otel/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ replace github.com/redis/go-redis/extra/redisotel/v9 => ../../extra/redisotel
replace github.com/redis/go-redis/extra/rediscmd/v9 => ../../extra/rediscmd

require (
github.com/redis/go-redis/extra/redisotel/v9 v9.7.0
github.com/redis/go-redis/v9 v9.7.0
github.com/redis/go-redis/extra/redisotel/v9 v9.7.1
github.com/redis/go-redis/v9 v9.7.1
github.com/uptrace/uptrace-go v1.21.0
go.opentelemetry.io/otel v1.22.0
)
Expand All @@ -23,7 +23,7 @@ require (
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect
github.com/redis/go-redis/extra/rediscmd/v9 v9.7.0 // indirect
github.com/redis/go-redis/extra/rediscmd/v9 v9.7.1 // indirect
go.opentelemetry.io/contrib/instrumentation/runtime v0.46.1 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect
Expand Down
2 changes: 1 addition & 1 deletion example/redis-bloom/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.18

replace github.com/redis/go-redis/v9 => ../..

require github.com/redis/go-redis/v9 v9.7.0
require github.com/redis/go-redis/v9 v9.7.1

require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
Expand Down
2 changes: 1 addition & 1 deletion example/scan-struct/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ replace github.com/redis/go-redis/v9 => ../..

require (
github.com/davecgh/go-spew v1.1.1
github.com/redis/go-redis/v9 v9.7.0
github.com/redis/go-redis/v9 v9.7.1
)

require (
Expand Down
4 changes: 2 additions & 2 deletions extra/rediscensus/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ replace github.com/redis/go-redis/v9 => ../..
replace github.com/redis/go-redis/extra/rediscmd/v9 => ../rediscmd

require (
github.com/redis/go-redis/extra/rediscmd/v9 v9.7.0
github.com/redis/go-redis/v9 v9.7.0
github.com/redis/go-redis/extra/rediscmd/v9 v9.7.1
github.com/redis/go-redis/v9 v9.7.1
go.opencensus.io v0.24.0
)

Expand Down
2 changes: 1 addition & 1 deletion extra/rediscmd/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ replace github.com/redis/go-redis/v9 => ../..
require (
github.com/bsm/ginkgo/v2 v2.12.0
github.com/bsm/gomega v1.27.10
github.com/redis/go-redis/v9 v9.7.0
github.com/redis/go-redis/v9 v9.7.1
)

require (
Expand Down
4 changes: 2 additions & 2 deletions extra/redisotel/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ replace github.com/redis/go-redis/v9 => ../..
replace github.com/redis/go-redis/extra/rediscmd/v9 => ../rediscmd

require (
github.com/redis/go-redis/extra/rediscmd/v9 v9.7.0
github.com/redis/go-redis/v9 v9.7.0
github.com/redis/go-redis/extra/rediscmd/v9 v9.7.1
github.com/redis/go-redis/v9 v9.7.1
go.opentelemetry.io/otel v1.22.0
go.opentelemetry.io/otel/metric v1.22.0
go.opentelemetry.io/otel/sdk v1.22.0
Expand Down
2 changes: 1 addition & 1 deletion extra/redisprometheus/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ replace github.com/redis/go-redis/v9 => ../..

require (
github.com/prometheus/client_golang v1.14.0
github.com/redis/go-redis/v9 v9.7.0
github.com/redis/go-redis/v9 v9.7.1
)

require (
Expand Down
2 changes: 1 addition & 1 deletion hash_commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ func (c cmdable) HExpire(ctx context.Context, key string, expiration time.Durati
return cmd
}

// HExpire - Sets the expiration time for specified fields in a hash in seconds.
// HExpireWithArgs - Sets the expiration time for specified fields in a hash in seconds.
// It requires a key, an expiration duration, a struct with boolean flags for conditional expiration settings (NX, XX, GT, LT), and a list of fields.
// The command constructs an argument list starting with "HEXPIRE", followed by the key, duration, any conditional flags, and the specified fields.
// For more information - https://redis.io/commands/hexpire/
Expand Down
2 changes: 1 addition & 1 deletion options.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ type Options struct {
// Add suffix to client name. Default is empty.
IdentitySuffix string

// Enable Unstable mode for Redis Search module with RESP3.
// UnstableResp3 enables Unstable mode for Redis Search module with RESP3.
UnstableResp3 bool
}

Expand Down
12 changes: 9 additions & 3 deletions osscluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ type ClusterOptions struct {
DisableIndentity bool // Disable set-lib on connect. Default is false.

IdentitySuffix string // Add suffix to client name. Default is empty.

// UnstableResp3 enables Unstable mode for Redis Search module with RESP3.
UnstableResp3 bool
}

func (opt *ClusterOptions) init() {
Expand Down Expand Up @@ -304,7 +307,8 @@ func (opt *ClusterOptions) clientOptions() *Options {
// much use for ClusterSlots config). This means we cannot execute the
// READONLY command against that node -- setting readOnly to false in such
// situations in the options below will prevent that from happening.
readOnly: opt.ReadOnly && opt.ClusterSlots == nil,
readOnly: opt.ReadOnly && opt.ClusterSlots == nil,
UnstableResp3: opt.UnstableResp3,
}
}

Expand Down Expand Up @@ -465,9 +469,11 @@ func (c *clusterNodes) Addrs() ([]string, error) {
closed := c.closed //nolint:ifshort
if !closed {
if len(c.activeAddrs) > 0 {
addrs = c.activeAddrs
addrs = make([]string, len(c.activeAddrs))
copy(addrs, c.activeAddrs)
} else {
addrs = c.addrs
addrs = make([]string, len(c.addrs))
copy(addrs, c.addrs)
}
}
c.mu.RUnlock()
Expand Down
17 changes: 11 additions & 6 deletions redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ type (
)

type hooksMixin struct {
hooksMu *sync.Mutex
hooksMu *sync.RWMutex

slice []Hook
initial hooks
current hooks
}

func (hs *hooksMixin) initHooks(hooks hooks) {
hs.hooksMu = new(sync.Mutex)
hs.hooksMu = new(sync.RWMutex)
hs.initial = hooks
hs.chain()
}
Expand Down Expand Up @@ -151,7 +151,7 @@ func (hs *hooksMixin) clone() hooksMixin {
clone := *hs
l := len(clone.slice)
clone.slice = clone.slice[:l:l]
clone.hooksMu = new(sync.Mutex)
clone.hooksMu = new(sync.RWMutex)
return clone
}

Expand All @@ -176,9 +176,14 @@ func (hs *hooksMixin) withProcessPipelineHook(
}

func (hs *hooksMixin) dialHook(ctx context.Context, network, addr string) (net.Conn, error) {
hs.hooksMu.Lock()
defer hs.hooksMu.Unlock()
return hs.current.dial(ctx, network, addr)
// Access to hs.current is guarded by a read-only lock since it may be mutated by AddHook(...)
// while this dialer is concurrently accessed by the background connection pool population
// routine when MinIdleConns > 0.
hs.hooksMu.RLock()
current := hs.current
hs.hooksMu.RUnlock()

return current.dial(ctx, network, addr)
}

func (hs *hooksMixin) processHook(ctx context.Context, cmd Cmder) error {
Expand Down
65 changes: 65 additions & 0 deletions redis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"net"
"sync"
"testing"
"time"

Expand Down Expand Up @@ -633,3 +634,67 @@ var _ = Describe("Hook with MinIdleConns", func() {
}))
})
})

var _ = Describe("Dialer connection timeouts", func() {
var client *redis.Client

const dialSimulatedDelay = 1 * time.Second

BeforeEach(func() {
options := redisOptions()
options.Dialer = func(ctx context.Context, network, addr string) (net.Conn, error) {
// Simulated slow dialer.
// Note that the following sleep is deliberately not context-aware.
time.Sleep(dialSimulatedDelay)
return net.Dial("tcp", options.Addr)
}
options.MinIdleConns = 1
client = redis.NewClient(options)
})

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

It("does not contend on connection dial for concurrent commands", func() {
var wg sync.WaitGroup

const concurrency = 10

durations := make(chan time.Duration, concurrency)
errs := make(chan error, concurrency)

start := time.Now()
wg.Add(concurrency)

for i := 0; i < concurrency; i++ {
go func() {
defer wg.Done()

start := time.Now()
err := client.Ping(ctx).Err()
durations <- time.Since(start)
errs <- err
}()
}

wg.Wait()
close(durations)
close(errs)

// All commands should eventually succeed, after acquiring a connection.
for err := range errs {
Expect(err).NotTo(HaveOccurred())
}

// Each individual command should complete within the simulated dial duration bound.
for duration := range durations {
Expect(duration).To(BeNumerically("<", 2*dialSimulatedDelay))
}

// Due to concurrent execution, the entire test suite should also complete within
// the same dial duration bound applied for individual commands.
Expect(time.Since(start)).To(BeNumerically("<", 2*dialSimulatedDelay))
})
})
Loading
Loading