1
0
mirror of https://github.com/redis/go-redis.git synced 2025-11-02 15:33:16 +03:00

chore(ci): Add redis 8.4-RC1-pre & examples (#3572)

* add disable maintnotifications example

* add 8.4-RC1-pre

* println -> printf for linter

* address jit comment
This commit is contained in:
Nedyalko Dyakov
2025-10-28 15:47:39 +02:00
committed by GitHub
parent f7a8a1c1d7
commit 5771fa474a
9 changed files with 314 additions and 20 deletions

View File

@@ -18,22 +18,20 @@ runs:
- name: Setup Test environment
env:
REDIS_VERSION: ${{ inputs.redis-version }}
CLIENT_LIBS_TEST_IMAGE: "redislabs/client-libs-test:${{ inputs.redis-version }}"
run: |
set -e
redis_version_np=$(echo "$REDIS_VERSION" | grep -oP '^\d+.\d+')
# Mapping of redis version to redis testing containers
declare -A redis_version_mapping=(
["8.4.x"]="8.4-RC1-pre"
["8.2.x"]="8.2.1-pre"
["8.0.x"]="8.0.2"
["7.4.x"]="rs-7.4.0-v5"
["7.2.x"]="rs-7.2.0-v17"
)
if [[ -v redis_version_mapping[$REDIS_VERSION] ]]; then
echo "REDIS_VERSION=${redis_version_np}" >> $GITHUB_ENV
echo "REDIS_IMAGE=redis:${{ inputs.redis-version }}" >> $GITHUB_ENV
echo "REDIS_IMAGE=redis:${REDIS_VERSION}" >> $GITHUB_ENV
echo "CLIENT_LIBS_TEST_IMAGE=redislabs/client-libs-test:${redis_version_mapping[$REDIS_VERSION]}" >> $GITHUB_ENV
else
echo "Version not found in the mapping."

View File

@@ -2,7 +2,7 @@ name: Go
on:
push:
branches: [master, v9, v9.7, v9.8, 'ndyakov/*', 'ofekshenawa/*', 'htemelski-redis/*', 'ce/*']
branches: [master, v9, 'v9.*']
pull_request:
branches: [master, v9, v9.7, v9.8, 'ndyakov/*', 'ofekshenawa/*', 'htemelski-redis/*', 'ce/*']
@@ -18,9 +18,9 @@ jobs:
fail-fast: false
matrix:
redis-version:
- "8.4.x" # Redis CE 8.4
- "8.2.x" # Redis CE 8.2
- "8.0.x" # Redis CE 8.0
- "7.4.x" # Redis stack 7.4
go-version:
- "1.23.x"
- "1.24.x"
@@ -44,9 +44,9 @@ jobs:
# Mapping of redis version to redis testing containers
declare -A redis_version_mapping=(
["8.4.x"]="8.4-RC1-pre"
["8.2.x"]="8.2.1-pre"
["8.0.x"]="8.0.2"
["7.4.x"]="rs-7.4.0-v5"
)
if [[ -v redis_version_mapping[$REDIS_VERSION] ]]; then
echo "REDIS_VERSION=${redis_version_np}" >> $GITHUB_ENV
@@ -74,10 +74,9 @@ jobs:
fail-fast: false
matrix:
redis-version:
- "8.4.x" # Redis CE 8.4
- "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
go-version:
- "1.23.x"
- "1.24.x"

View File

@@ -1,8 +1,8 @@
GO_MOD_DIRS := $(shell find . -type f -name 'go.mod' -exec dirname {} \; | sort)
REDIS_VERSION ?= 8.2
REDIS_VERSION ?= 8.4
RE_CLUSTER ?= false
RCE_DOCKER ?= true
CLIENT_LIBS_TEST_IMAGE ?= redislabs/client-libs-test:8.2.1-pre
CLIENT_LIBS_TEST_IMAGE ?= redislabs/client-libs-test:8.4-RC1-pre
docker.start:
export RE_CLUSTER=$(RE_CLUSTER) && \

View File

@@ -2,7 +2,7 @@
services:
redis:
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:8.2.1-pre}
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:8.4-RC1-pre}
platform: linux/amd64
container_name: redis-standalone
environment:
@@ -23,7 +23,7 @@ services:
- all
osscluster:
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:8.2.1-pre}
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:8.4-RC1-pre}
platform: linux/amd64
container_name: redis-osscluster
environment:
@@ -40,7 +40,7 @@ services:
- all
sentinel-cluster:
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:8.2.1-pre}
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:8.4-RC1-pre}
platform: linux/amd64
container_name: redis-sentinel-cluster
network_mode: "host"
@@ -60,7 +60,7 @@ services:
- all
sentinel:
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:8.2.1-pre}
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:8.4-RC1-pre}
platform: linux/amd64
container_name: redis-sentinel
depends_on:
@@ -84,7 +84,7 @@ services:
- all
ring-cluster:
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:8.2.1-pre}
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:8.4-RC1-pre}
platform: linux/amd64
container_name: redis-ring-cluster
environment:

View File

@@ -0,0 +1,133 @@
# Disable Maintenance Notifications Example
This example demonstrates how to use the go-redis client with maintenance notifications **disabled**.
## What are Maintenance Notifications?
Maintenance notifications are a Redis Cloud feature that allows the server to notify clients about:
- Planned maintenance events
- Failover operations
- Node migrations
- Cluster topology changes
The go-redis client supports three modes:
- **`ModeDisabled`**: Client doesn't send `CLIENT MAINT_NOTIFICATIONS ON` command
- **`ModeEnabled`**: Client forcefully sends the command, interrupts connection on error
- **`ModeAuto`** (default): Client tries to send the command, disables feature on error
## When to Disable Maintenance Notifications
You should disable maintenance notifications when:
1. **Connecting to non-Redis Cloud / Redis Enterprise instances** - Standard Redis servers don't support this feature
2. **You want to handle failovers manually** - Your application has custom failover logic
3. **Minimizing client-side overhead** - You want the simplest possible client behavior
4. **The Redis server doesn't support the feature** - Older Redis versions or forks
## Usage
### Basic Example
```go
import (
"github.com/redis/go-redis/v9"
"github.com/redis/go-redis/v9/maintnotifications"
)
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
// Explicitly disable maintenance notifications
MaintNotificationsConfig: &maintnotifications.Config{
Mode: maintnotifications.ModeDisabled,
},
})
defer rdb.Close()
```
### Cluster Client Example
```go
rdbCluster := redis.NewClusterClient(&redis.ClusterOptions{
Addrs: []string{"localhost:7000", "localhost:7001", "localhost:7002"},
// Disable maintenance notifications for cluster
MaintNotificationsConfig: &maintnotifications.Config{
Mode: maintnotifications.ModeDisabled,
},
})
defer rdbCluster.Close()
```
### Default Behavior (ModeAuto)
If you don't specify `MaintNotifications`, the client defaults to `ModeAuto`:
```go
// This uses ModeAuto by default
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
// MaintNotificationsConfig: nil means ModeAuto
})
```
With `ModeAuto`, the client will:
1. Try to enable maintenance notifications
2. If the server doesn't support it, silently disable the feature
3. Continue normal operation
## Running the Example
1. Start a Redis server:
```bash
redis-server --port 6379
```
2. Run the example:
```bash
go run main.go
```
## Expected Output
```
=== Example 1: Explicitly Disabled ===
✓ Connected successfully (maintenance notifications disabled)
✓ SET operation successful
✓ GET operation successful: value1
=== Example 2: Default Behavior (ModeAuto) ===
✓ Connected successfully (maintenance notifications auto-enabled)
=== Example 3: Cluster Client with Disabled Notifications ===
Cluster not available (expected): ...
=== Example 4: Performance Comparison ===
✓ 1000 SET operations (disabled): 45ms
✓ 1000 SET operations (auto): 46ms
=== Cleanup ===
✓ Database flushed
=== Summary ===
Maintenance notifications can be disabled by setting:
MaintNotificationsConfig: &maintnotifications.Config{
Mode: maintnotifications.ModeDisabled,
}
This is useful when:
- Connecting to non-Redis Cloud instances
- You want to handle failovers manually
- You want to minimize client-side overhead
- The Redis server doesn't support CLIENT MAINT_NOTIFICATIONS
```
## Performance Impact
Disabling maintenance notifications has minimal performance impact. The main differences are:
1. **Connection Setup**: One less command (`CLIENT MAINT_NOTIFICATIONS ON`) during connection initialization
2. **Runtime Overhead**: No background processing of maintenance notifications
3. **Memory Usage**: Slightly lower memory footprint (no notification handlers)
In most cases, the performance difference is negligible (< 1%).

View File

@@ -0,0 +1,12 @@
module github.com/redis/go-redis/example/disable-maintnotifications
go 1.23
replace github.com/redis/go-redis/v9 => ../..
require github.com/redis/go-redis/v9 v9.7.0
require (
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
)

View File

@@ -0,0 +1,8 @@
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
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/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=

View File

@@ -0,0 +1,144 @@
package main
import (
"context"
"fmt"
"time"
"github.com/redis/go-redis/v9"
"github.com/redis/go-redis/v9/maintnotifications"
)
func main() {
ctx := context.Background()
// Example 0: Explicitly disable maintenance notifications
fmt.Println("=== Example 0: Explicitly Enabled ===")
rdb0 := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
// Explicitly disable maintenance notifications
// This prevents the client from sending CLIENT MAINT_NOTIFICATIONS ON
MaintNotificationsConfig: &maintnotifications.Config{
Mode: maintnotifications.ModeEnabled,
},
})
defer rdb0.Close()
// Test the connection
if err := rdb0.Ping(ctx).Err(); err != nil {
fmt.Printf("Failed to connect: %v\n\n", err)
}
fmt.Println("When ModeEnabled, the client will return an error if the server doesn't support maintenance notifications.")
fmt.Printf("ModeAuto will silently disable the feature.\n\n")
// Example 1: Explicitly disable maintenance notifications
fmt.Println("=== Example 1: Explicitly Disabled ===")
rdb1 := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
// Explicitly disable maintenance notifications
// This prevents the client from sending CLIENT MAINT_NOTIFICATIONS ON
MaintNotificationsConfig: &maintnotifications.Config{
Mode: maintnotifications.ModeDisabled,
},
})
defer rdb1.Close()
// Test the connection
if err := rdb1.Ping(ctx).Err(); err != nil {
fmt.Printf("Failed to connect: %v\n\n", err)
return
}
fmt.Println("✓ Connected successfully (maintenance notifications disabled)")
// Perform some operations
if err := rdb1.Set(ctx, "example:key1", "value1", 0).Err(); err != nil {
fmt.Printf("Failed to set key: %v\n\n", err)
return
}
fmt.Println("✓ SET operation successful")
val, err := rdb1.Get(ctx, "example:key1").Result()
if err != nil {
fmt.Printf("Failed to get key: %v\n\n", err)
return
}
fmt.Printf("✓ GET operation successful: %s\n\n", val)
// Example 2: Using nil config (defaults to ModeAuto)
fmt.Printf("\n=== Example 2: Default Behavior (ModeAuto) ===\n")
rdb2 := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
// MaintNotifications: nil means ModeAuto (enabled for Redis Cloud)
})
defer rdb2.Close()
if err := rdb2.Ping(ctx).Err(); err != nil {
fmt.Printf("Failed to connect: %v\n\n", err)
return
}
fmt.Println("✓ Connected successfully (maintenance notifications auto-enabled)")
// Example 4: Comparing behavior with and without maintenance notifications
fmt.Printf("\n=== Example 4: Performance Comparison ===\n")
// Client with auto-enabled notifications
startauto := time.Now()
for i := 0; i < 1000; i++ {
key := fmt.Sprintf("test:auto:%d", i)
if err := rdb2.Set(ctx, key, i, time.Minute).Err(); err != nil {
fmt.Printf("Failed to set key: %v\n", err)
return
}
}
autoDuration := time.Since(startauto)
fmt.Printf("✓ 1000 SET operations (auto): %v\n", autoDuration)
// print pool stats
fmt.Printf("Pool stats (auto): %+v\n", rdb2.PoolStats())
// give the server a moment to take chill
fmt.Println("---")
time.Sleep(time.Second)
// Client with disabled notifications
start := time.Now()
for i := 0; i < 1000; i++ {
key := fmt.Sprintf("test:disabled:%d", i)
if err := rdb1.Set(ctx, key, i, time.Minute).Err(); err != nil {
fmt.Printf("Failed to set key: %v\n", err)
return
}
}
disabledDuration := time.Since(start)
fmt.Printf("✓ 1000 SET operations (disabled): %v\n", disabledDuration)
fmt.Printf("Pool stats (disabled): %+v\n", rdb1.PoolStats())
// performance comparison note
fmt.Printf("\nNote: The pool stats and performance are identical because there is no background processing overhead.\n")
fmt.Println("Since the server doesn't support maintenance notifications, there is no difference in behavior.")
fmt.Printf("The only difference is that the \"ModeDisabled\" client doesn't send the CLIENT MAINT_NOTIFICATIONS ON command.\n\n")
fmt.Println("p.s. reordering the execution here makes it look like there is a small performance difference, but it's just noise.")
// Cleanup
fmt.Printf("\n=== Cleanup ===\n")
if err := rdb1.FlushDB(ctx).Err(); err != nil {
fmt.Printf("Failed to flush DB: %v\n", err)
return
}
fmt.Println("✓ Database flushed")
fmt.Printf("\n=== Summary ===\n")
fmt.Println("Maintenance notifications can be disabled by setting:")
fmt.Println(" MaintNotifications: &maintnotifications.Config{")
fmt.Println(" Mode: maintnotifications.ModeDisabled,")
fmt.Println(" }")
fmt.Printf("\nThis is useful when:\n")
fmt.Println(" - Connecting to non-Redis Cloud instances")
fmt.Println(" - You want to handle failovers manually")
fmt.Println(" - You want to minimize client-side overhead")
fmt.Println(" - The Redis server doesn't support CLIENT MAINT_NOTIFICATIONS")
fmt.Printf("\nFor more information, see:\n")
fmt.Println(" https://github.com/redis/go-redis/tree/master/maintnotifications")
}

View File

@@ -69,7 +69,7 @@ var RCEDocker = false
// Notes version of redis we are executing tests against.
// This can be used before we change the bsm fork of ginkgo for one,
// which have support for label sets, so we can filter tests per redis version.
var RedisVersion float64 = 8.2
var RedisVersion float64 = 8.4
func SkipBeforeRedisVersion(version float64, msg string) {
if RedisVersion < version {
@@ -96,7 +96,7 @@ var _ = BeforeSuite(func() {
RedisVersion, _ = strconv.ParseFloat(strings.Trim(os.Getenv("REDIS_VERSION"), "\""), 64)
if RedisVersion == 0 {
RedisVersion = 8.2
RedisVersion = 8.4
}
fmt.Printf("RECluster: %v\n", RECluster)