mirror of
https://github.com/redis/go-redis.git
synced 2025-04-14 22:04:09 +03:00
feat: Enable CI for Redis CE 8.0 (#3274)
* chore: extract benchmark tests * wip * enable pubsub tests * enable ring tests * stop tests with build redis from source * start all tests * mix of makefile and action * add sentinel configs * fix example test * stop debug on re * wip * enable gears for redis 7.2 * wip * enable sentinel, they are expected to fail * fix: linter configuration * chore: update re versions * return older redis enterprise version * add basic codeql * wip: increase timeout, focus only sentinel tests * sentinels with docker network host * enable all tests * fix flanky test * enable example tests * tidy docker compose * add debug output * stop shutingdown masters * don't test sentinel for re * skip unsuported addscores * Update README bump go version in CI * Update README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update CONTRIBUTING.md add information about new test setup --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
parent
5314a57132
commit
ebe11d06ca
21
.github/actions/run-tests/action.yml
vendored
21
.github/actions/run-tests/action.yml
vendored
@ -21,12 +21,7 @@ runs:
|
||||
CLIENT_LIBS_TEST_IMAGE: "redislabs/client-libs-test:${{ inputs.redis-version }}"
|
||||
run: |
|
||||
set -e
|
||||
redis_major_version=$(echo "$REDIS_VERSION" | grep -oP '^\d+')
|
||||
if (( redis_major_version < 8 )); then
|
||||
echo "Using redis-stack for module tests"
|
||||
else
|
||||
echo "Using redis CE for module tests"
|
||||
fi
|
||||
redis_version_np=$(echo "$REDIS_VERSION" | grep -oP '^\d+.\d+')
|
||||
|
||||
# Mapping of redis version to redis testing containers
|
||||
declare -A redis_version_mapping=(
|
||||
@ -36,27 +31,23 @@ runs:
|
||||
)
|
||||
|
||||
if [[ -v redis_version_mapping[$REDIS_VERSION] ]]; then
|
||||
echo "REDIS_MAJOR_VERSION=${redis_major_version}" >> $GITHUB_ENV
|
||||
echo "REDIS_VERSION=${redis_version_np}" >> $GITHUB_ENV
|
||||
echo "REDIS_IMAGE=redis:${{ inputs.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."
|
||||
exit 1
|
||||
fi
|
||||
sleep 10 # time to settle
|
||||
sleep 10 # wait for redis to start
|
||||
shell: bash
|
||||
- name: Set up Docker Compose environment with redis ${{ inputs.redis-version }}
|
||||
run: docker compose --profile all up -d
|
||||
run: |
|
||||
make docker.start
|
||||
shell: bash
|
||||
- name: Run tests
|
||||
env:
|
||||
RCE_DOCKER: "true"
|
||||
RE_CLUSTER: "false"
|
||||
run: |
|
||||
go test \
|
||||
--ginkgo.skip-file="ring_test.go" \
|
||||
--ginkgo.skip-file="sentinel_test.go" \
|
||||
--ginkgo.skip-file="pubsub_test.go" \
|
||||
--ginkgo.skip-file="gears_commands_test.go" \
|
||||
--ginkgo.label-filter="!NonRedisEnterprise"
|
||||
make test.ci
|
||||
shell: bash
|
||||
|
62
.github/workflows/build.yml
vendored
62
.github/workflows/build.yml
vendored
@ -10,13 +10,19 @@ permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: build
|
||||
|
||||
benchmark:
|
||||
name: benchmark
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
go-version: [1.21.x, 1.22.x, 1.23.x]
|
||||
redis-version:
|
||||
- "8.0-M03" # 8.0 milestone 4
|
||||
- "7.4.2" # should use redis stack 7.4
|
||||
go-version:
|
||||
- "1.23.x"
|
||||
- "1.24.x"
|
||||
|
||||
steps:
|
||||
- name: Set up ${{ matrix.go-version }}
|
||||
@ -27,15 +33,38 @@ jobs:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Test
|
||||
run: make test
|
||||
- name: Setup Test environment
|
||||
env:
|
||||
REDIS_VERSION: ${{ matrix.redis-version }}
|
||||
CLIENT_LIBS_TEST_IMAGE: "redislabs/client-libs-test:${{ matrix.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.0-M03"]="8.0-M04-pre"
|
||||
["7.4.2"]="rs-7.4.0-v2"
|
||||
)
|
||||
if [[ -v redis_version_mapping[$REDIS_VERSION] ]]; then
|
||||
echo "REDIS_VERSION=${redis_version_np}" >> $GITHUB_ENV
|
||||
echo "REDIS_IMAGE=redis:${{ matrix.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."
|
||||
exit 1
|
||||
fi
|
||||
shell: bash
|
||||
- name: Set up Docker Compose environment with redis ${{ matrix.redis-version }}
|
||||
run: make docker.start
|
||||
shell: bash
|
||||
- name: Benchmark Tests
|
||||
env:
|
||||
RCE_DOCKER: "true"
|
||||
RE_CLUSTER: "false"
|
||||
run: make bench
|
||||
shell: bash
|
||||
|
||||
- name: Upload to Codecov
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
files: coverage.txt
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
test-redis-ce:
|
||||
name: test-redis-ce
|
||||
runs-on: ubuntu-latest
|
||||
@ -47,11 +76,10 @@ jobs:
|
||||
- "7.4.2" # should use redis stack 7.4
|
||||
- "7.2.7" # should redis stack 7.2
|
||||
go-version:
|
||||
- "1.22.x"
|
||||
- "1.23.x"
|
||||
- "1.24.x"
|
||||
|
||||
steps:
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
@ -60,4 +88,10 @@ jobs:
|
||||
with:
|
||||
go-version: ${{matrix.go-version}}
|
||||
redis-version: ${{ matrix.redis-version }}
|
||||
|
||||
|
||||
- name: Upload to Codecov
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
files: coverage.txt
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
|
68
.github/workflows/codeql-analysis.yml
vendored
Normal file
68
.github/workflows/codeql-analysis.yml
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'go' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
4
.github/workflows/doctests.yaml
vendored
4
.github/workflows/doctests.yaml
vendored
@ -25,7 +25,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
go-version: [ "1.21", "1.22", "1.23" ]
|
||||
go-version: ["1.24"]
|
||||
|
||||
steps:
|
||||
- name: Set up ${{ matrix.go-version }}
|
||||
@ -38,4 +38,4 @@ jobs:
|
||||
|
||||
- name: Test doc examples
|
||||
working-directory: ./doctests
|
||||
run: go test
|
||||
run: go test -v
|
||||
|
4
.github/workflows/test-redis-enterprise.yml
vendored
4
.github/workflows/test-redis-enterprise.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
go-version: [1.23.x]
|
||||
go-version: [1.24.x]
|
||||
re-build: ["7.4.2-54"]
|
||||
|
||||
steps:
|
||||
@ -47,7 +47,7 @@ jobs:
|
||||
- name: Test
|
||||
env:
|
||||
RE_CLUSTER: true
|
||||
REDIS_MAJOR_VERSION: 7
|
||||
REDIS_VERSION: "7.4"
|
||||
run: |
|
||||
go test \
|
||||
--ginkgo.skip-file="ring_test.go" \
|
||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -5,4 +5,6 @@ testdata/*
|
||||
*.tar.gz
|
||||
*.dic
|
||||
redis8tests.sh
|
||||
.vscode
|
||||
coverage.txt
|
||||
**/coverage.txt
|
||||
.vscode
|
@ -32,20 +32,33 @@ Here's how to get started with your code contribution:
|
||||
|
||||
1. Create your own fork of go-redis
|
||||
2. Do the changes in your fork
|
||||
3. If you need a development environment, run `make test`. Note: this clones and builds the latest release of [redis](https://redis.io). You also need a redis-stack-server docker, in order to run the capabilities tests. This can be started by running:
|
||||
```docker run -p 6379:6379 -it redis/redis-stack-server:edge```
|
||||
4. While developing, make sure the tests pass by running `make tests`
|
||||
3. If you need a development environment, run `make docker.start`.
|
||||
|
||||
> Note: this clones and builds the docker containers specified in `docker-compose.yml`, to understand more about
|
||||
> the infrastructure that will be started you can check the `docker-compose.yml`. You also have the possiblity
|
||||
> to specify the redis image that will be pulled with the env variable `CLIENT_LIBS_TEST_IMAGE`.
|
||||
> By default the docker image that will be pulled and started is `redislabs/client-libs-test:rs-7.4.0-v2`.
|
||||
> If you want to test with newer Redis version, using a newer version of `redislabs/client-libs-test` should work out of the box.
|
||||
|
||||
4. While developing, make sure the tests pass by running `make test` (if you have the docker containers running, `make test.ci` may be sufficient).
|
||||
> Note: `make test` will try to start all containers, run the tests with `make test.ci` and then stop all containers.
|
||||
5. If you like the change and think the project could use it, send a
|
||||
pull request
|
||||
|
||||
To see what else is part of the automation, run `invoke -l`
|
||||
|
||||
|
||||
## Testing
|
||||
|
||||
Call `make test` to run all tests, including linters.
|
||||
### Setting up Docker
|
||||
To run the tests, you need to have Docker installed and running. If you are using a host OS that does not support
|
||||
docker host networks out of the box (e.g. Windows, OSX), you need to set up a docker desktop and enable docker host networks.
|
||||
|
||||
### Running tests
|
||||
Call `make test` to run all tests.
|
||||
|
||||
Continuous Integration uses these same wrappers to run all of these
|
||||
tests against multiple versions of python. Feel free to test your
|
||||
tests against multiple versions of redis. Feel free to test your
|
||||
changes against all the go versions supported, as declared by the
|
||||
[build.yml](./.github/workflows/build.yml) file.
|
||||
|
||||
|
42
Makefile
42
Makefile
@ -1,45 +1,35 @@
|
||||
GO_MOD_DIRS := $(shell find . -type f -name 'go.mod' -exec dirname {} \; | sort)
|
||||
export REDIS_MAJOR_VERSION := 7
|
||||
|
||||
test: testdeps
|
||||
docker start go-redis-redis-stack || docker run -d --name go-redis-redis-stack -p 6379:6379 -e REDIS_ARGS="--enable-debug-command yes --enable-module-command yes" redis/redis-stack-server:latest
|
||||
$(eval GO_VERSION := $(shell go version | cut -d " " -f 3 | cut -d. -f2))
|
||||
docker.start:
|
||||
docker compose --profile all up -d --quiet-pull
|
||||
|
||||
docker.stop:
|
||||
docker compose --profile all down
|
||||
|
||||
test:
|
||||
$(MAKE) docker.start
|
||||
$(MAKE) test.ci
|
||||
$(MAKE) docker.stop
|
||||
|
||||
test.ci:
|
||||
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 && \
|
||||
go test && \
|
||||
go test ./... -short -race && \
|
||||
go test ./... -run=NONE -bench=. -benchmem && \
|
||||
env GOOS=linux GOARCH=386 go test && \
|
||||
go test -coverprofile=coverage.txt -covermode=atomic ./... && \
|
||||
go vet); \
|
||||
go vet && \
|
||||
go test -coverprofile=coverage.txt -covermode=atomic ./... -race); \
|
||||
done
|
||||
cd internal/customvet && go build .
|
||||
go vet -vettool ./internal/customvet/customvet
|
||||
docker stop go-redis-redis-stack
|
||||
|
||||
testdeps: testdata/redis/src/redis-server
|
||||
|
||||
bench: testdeps
|
||||
bench:
|
||||
go test ./... -test.run=NONE -test.bench=. -test.benchmem
|
||||
|
||||
.PHONY: all test testdeps bench fmt
|
||||
.PHONY: all test bench fmt
|
||||
|
||||
build:
|
||||
go build .
|
||||
|
||||
testdata/redis:
|
||||
mkdir -p $@
|
||||
wget -qO- https://download.redis.io/releases/redis-7.4.2.tar.gz | tar xvz --strip-components=1 -C $@
|
||||
|
||||
testdata/redis/src/redis-server: testdata/redis
|
||||
cd $< && make all
|
||||
|
||||
fmt:
|
||||
gofumpt -w ./
|
||||
goimports -w -local github.com/redis/go-redis ./
|
||||
|
14
README.md
14
README.md
@ -14,6 +14,20 @@
|
||||
> See [OpenTelemetry](https://github.com/redis/go-redis/tree/master/example/otel) example which
|
||||
> demonstrates how you can use Uptrace to monitor go-redis.
|
||||
|
||||
## Supported versions
|
||||
|
||||
In `go-redis` we are aiming to support the last three releases of Redis. Currently, this means we do support:
|
||||
- [Redis 7.2](https://raw.githubusercontent.com/redis/redis/7.2/00-RELEASENOTES) - using Redis Stack 7.2 for modules support
|
||||
- [Redis 7.4](https://raw.githubusercontent.com/redis/redis/7.4/00-RELEASENOTES) - using Redis Stack 7.4 for modules support
|
||||
- [Redis 8.0](https://raw.githubusercontent.com/redis/redis/8.0/00-RELEASENOTES) - using Redis CE 8.0 where modules are included
|
||||
|
||||
Although the `go.mod` states it requires at minimum `go 1.18`, our CI is configured to run the tests against all three
|
||||
versions of Redis and latest two versions of Go ([1.23](https://go.dev/doc/devel/release#go1.23.0),
|
||||
[1.24](https://go.dev/doc/devel/release#go1.24.0)). We observe that some modules related test may not pass with
|
||||
Redis Stack 7.2 and some commands are changed with Redis CE 8.0.
|
||||
Please do refer to the documentation and the tests if you experience any issues. We do plan to update the go version
|
||||
in the `go.mod` to `go 1.24` in one of the next releases.
|
||||
|
||||
## How do I Redis?
|
||||
|
||||
[Learn for free at Redis University](https://university.redis.com/)
|
||||
|
@ -242,7 +242,7 @@ var _ = Describe("ACL permissions", Label("NonRedisEnterprise"), func() {
|
||||
})
|
||||
|
||||
It("set permissions for module commands", func() {
|
||||
SkipBeforeRedisMajor(8, "permissions for modules are supported for Redis Version >=8")
|
||||
SkipBeforeRedisVersion(8, "permissions for modules are supported for Redis Version >=8")
|
||||
Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred())
|
||||
val, err := client.FTCreate(ctx, "txt", &redis.FTCreateOptions{}, &redis.FieldSchema{FieldName: "txt", FieldType: redis.SearchFieldTypeText}).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
@ -322,7 +322,7 @@ var _ = Describe("ACL permissions", Label("NonRedisEnterprise"), func() {
|
||||
})
|
||||
|
||||
It("set permissions for module categories", func() {
|
||||
SkipBeforeRedisMajor(8, "permissions for modules are supported for Redis Version >=8")
|
||||
SkipBeforeRedisVersion(8, "permissions for modules are supported for Redis Version >=8")
|
||||
Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred())
|
||||
val, err := client.FTCreate(ctx, "txt", &redis.FTCreateOptions{}, &redis.FieldSchema{FieldName: "txt", FieldType: redis.SearchFieldTypeText}).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
@ -419,7 +419,7 @@ var _ = Describe("ACL Categories", func() {
|
||||
})
|
||||
|
||||
It("lists acl categories and subcategories with Modules", func() {
|
||||
SkipBeforeRedisMajor(8, "modules are included in acl for redis version >= 8")
|
||||
SkipBeforeRedisVersion(8, "modules are included in acl for redis version >= 8")
|
||||
aclTestCase := map[string]string{
|
||||
"search": "FT.CREATE",
|
||||
"bloom": "bf.add",
|
||||
|
105
bench_test.go
105
bench_test.go
@ -277,37 +277,41 @@ func BenchmarkXRead(b *testing.B) {
|
||||
|
||||
func newClusterScenario() *clusterScenario {
|
||||
return &clusterScenario{
|
||||
ports: []string{"16600", "16601", "16602", "16603", "16604", "16605"},
|
||||
nodeIDs: make([]string, 6),
|
||||
processes: make(map[string]*redisProcess, 6),
|
||||
clients: make(map[string]*redis.Client, 6),
|
||||
ports: []string{"16600", "16601", "16602", "16603", "16604", "16605"},
|
||||
nodeIDs: make([]string, 6),
|
||||
clients: make(map[string]*redis.Client, 6),
|
||||
}
|
||||
}
|
||||
|
||||
var clusterBench *clusterScenario
|
||||
|
||||
func BenchmarkClusterPing(b *testing.B) {
|
||||
if testing.Short() {
|
||||
b.Skip("skipping in short mode")
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
cluster := newClusterScenario()
|
||||
if err := startCluster(ctx, cluster); err != nil {
|
||||
b.Fatal(err)
|
||||
if clusterBench == nil {
|
||||
clusterBench = newClusterScenario()
|
||||
if err := configureClusterTopology(ctx, clusterBench); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
defer cluster.Close()
|
||||
|
||||
client := cluster.newClusterClient(ctx, redisClusterOptions())
|
||||
client := clusterBench.newClusterClient(ctx, redisClusterOptions())
|
||||
defer client.Close()
|
||||
|
||||
b.ResetTimer()
|
||||
b.Run("cluster ping", func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
err := client.Ping(ctx).Err()
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
err := client.Ping(ctx).Err()
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@ -317,23 +321,26 @@ func BenchmarkClusterDoInt(b *testing.B) {
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
cluster := newClusterScenario()
|
||||
if err := startCluster(ctx, cluster); err != nil {
|
||||
b.Fatal(err)
|
||||
if clusterBench == nil {
|
||||
clusterBench = newClusterScenario()
|
||||
if err := configureClusterTopology(ctx, clusterBench); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
defer cluster.Close()
|
||||
|
||||
client := cluster.newClusterClient(ctx, redisClusterOptions())
|
||||
client := clusterBench.newClusterClient(ctx, redisClusterOptions())
|
||||
defer client.Close()
|
||||
|
||||
b.ResetTimer()
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
err := client.Do(ctx, "SET", 10, 10).Err()
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
b.Run("cluster do set int", func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
err := client.Do(ctx, "SET", 10, 10).Err()
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@ -343,26 +350,29 @@ func BenchmarkClusterSetString(b *testing.B) {
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
cluster := newClusterScenario()
|
||||
if err := startCluster(ctx, cluster); err != nil {
|
||||
b.Fatal(err)
|
||||
if clusterBench == nil {
|
||||
clusterBench = newClusterScenario()
|
||||
if err := configureClusterTopology(ctx, clusterBench); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
defer cluster.Close()
|
||||
|
||||
client := cluster.newClusterClient(ctx, redisClusterOptions())
|
||||
client := clusterBench.newClusterClient(ctx, redisClusterOptions())
|
||||
defer client.Close()
|
||||
|
||||
value := string(bytes.Repeat([]byte{'1'}, 10000))
|
||||
|
||||
b.ResetTimer()
|
||||
b.Run("cluster set string", func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
err := client.Set(ctx, "key", value, 0).Err()
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
err := client.Set(ctx, "key", value, 0).Err()
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@ -372,21 +382,6 @@ func BenchmarkExecRingSetAddrsCmd(b *testing.B) {
|
||||
ringShard2Name = "ringShardTwo"
|
||||
)
|
||||
|
||||
for _, port := range []string{ringShard1Port, ringShard2Port} {
|
||||
if _, err := startRedis(port); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
b.Cleanup(func() {
|
||||
for _, p := range processes {
|
||||
if err := p.Close(); err != nil {
|
||||
b.Errorf("Failed to stop redis process: %v", err)
|
||||
}
|
||||
}
|
||||
processes = nil
|
||||
})
|
||||
|
||||
ring := redis.NewRing(&redis.RingOptions{
|
||||
Addrs: map[string]string{
|
||||
"ringShardOne": ":" + ringShard1Port,
|
||||
|
@ -4,6 +4,7 @@ import "context"
|
||||
|
||||
type ClusterCmdable interface {
|
||||
ClusterMyShardID(ctx context.Context) *StringCmd
|
||||
ClusterMyID(ctx context.Context) *StringCmd
|
||||
ClusterSlots(ctx context.Context) *ClusterSlotsCmd
|
||||
ClusterShards(ctx context.Context) *ClusterShardsCmd
|
||||
ClusterLinks(ctx context.Context) *ClusterLinksCmd
|
||||
@ -35,6 +36,12 @@ func (c cmdable) ClusterMyShardID(ctx context.Context) *StringCmd {
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (c cmdable) ClusterMyID(ctx context.Context) *StringCmd {
|
||||
cmd := NewStringCmd(ctx, "cluster", "myid")
|
||||
_ = c(ctx, cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (c cmdable) ClusterSlots(ctx context.Context) *ClusterSlotsCmd {
|
||||
cmd := NewClusterSlotsCmd(ctx, "cluster", "slots")
|
||||
_ = c(ctx, cmd)
|
||||
|
@ -194,6 +194,7 @@ var _ = Describe("Commands", func() {
|
||||
})
|
||||
|
||||
It("should ClientKillByFilter with MAXAGE", Label("NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||
var s []string
|
||||
started := make(chan bool)
|
||||
done := make(chan bool)
|
||||
@ -211,18 +212,18 @@ var _ = Describe("Commands", func() {
|
||||
select {
|
||||
case <-done:
|
||||
Fail("BLPOP is not blocked.")
|
||||
case <-time.After(1 * time.Second):
|
||||
case <-time.After(1100 * time.Millisecond):
|
||||
// ok
|
||||
}
|
||||
|
||||
killed := client.ClientKillByFilter(ctx, "MAXAGE", "1")
|
||||
Expect(killed.Err()).NotTo(HaveOccurred())
|
||||
Expect(killed.Val()).To(BeNumerically(">=", 2))
|
||||
Expect(killed.Val()).To(BeNumerically(">=", 1))
|
||||
|
||||
select {
|
||||
case <-done:
|
||||
// ok
|
||||
case <-time.After(time.Second):
|
||||
case <-time.After(200 * time.Millisecond):
|
||||
Fail("BLPOP is still blocked.")
|
||||
}
|
||||
})
|
||||
@ -345,7 +346,7 @@ var _ = Describe("Commands", func() {
|
||||
})
|
||||
|
||||
It("should ConfigGet Modules", func() {
|
||||
SkipBeforeRedisMajor(8, "Config doesn't include modules before Redis 8")
|
||||
SkipBeforeRedisVersion(8, "Config doesn't include modules before Redis 8")
|
||||
expected := map[string]string{
|
||||
"search-*": "search-timeout",
|
||||
"ts-*": "ts-retention-policy",
|
||||
@ -380,7 +381,7 @@ var _ = Describe("Commands", func() {
|
||||
})
|
||||
|
||||
It("should ConfigGet with Modules", Label("NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisMajor(8, "config get won't return modules configs before redis 8")
|
||||
SkipBeforeRedisVersion(8, "config get won't return modules configs before redis 8")
|
||||
configGet := client.ConfigGet(ctx, "*")
|
||||
Expect(configGet.Err()).NotTo(HaveOccurred())
|
||||
Expect(configGet.Val()).To(HaveKey("maxmemory"))
|
||||
@ -391,7 +392,7 @@ var _ = Describe("Commands", func() {
|
||||
})
|
||||
|
||||
It("should ConfigSet FT DIALECT", func() {
|
||||
SkipBeforeRedisMajor(8, "config doesn't include modules before Redis 8")
|
||||
SkipBeforeRedisVersion(8, "config doesn't include modules before Redis 8")
|
||||
defaultState, err := client.ConfigGet(ctx, "search-default-dialect").Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
@ -437,13 +438,13 @@ var _ = Describe("Commands", func() {
|
||||
})
|
||||
|
||||
It("should ConfigSet fail for ReadOnly", func() {
|
||||
SkipBeforeRedisMajor(8, "Config doesn't include modules before Redis 8")
|
||||
SkipBeforeRedisVersion(8, "Config doesn't include modules before Redis 8")
|
||||
_, err := client.ConfigSet(ctx, "search-max-doctablesize", "100000").Result()
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
|
||||
It("should ConfigSet Modules", func() {
|
||||
SkipBeforeRedisMajor(8, "Config doesn't include modules before Redis 8")
|
||||
SkipBeforeRedisVersion(8, "Config doesn't include modules before Redis 8")
|
||||
defaults := map[string]string{}
|
||||
expected := map[string]string{
|
||||
"search-timeout": "100",
|
||||
@ -484,7 +485,7 @@ var _ = Describe("Commands", func() {
|
||||
})
|
||||
|
||||
It("should Fail ConfigSet Modules", func() {
|
||||
SkipBeforeRedisMajor(8, "Config doesn't include modules before Redis 8")
|
||||
SkipBeforeRedisVersion(8, "Config doesn't include modules before Redis 8")
|
||||
expected := map[string]string{
|
||||
"search-timeout": "-100",
|
||||
"ts-retention-policy": "-10",
|
||||
@ -533,7 +534,7 @@ var _ = Describe("Commands", func() {
|
||||
})
|
||||
|
||||
It("should Info Modules", Label("redis.info"), func() {
|
||||
SkipBeforeRedisMajor(8, "modules are included in info for Redis Version >= 8")
|
||||
SkipBeforeRedisVersion(8, "modules are included in info for Redis Version >= 8")
|
||||
info := client.Info(ctx)
|
||||
Expect(info.Err()).NotTo(HaveOccurred())
|
||||
Expect(info.Val()).NotTo(BeNil())
|
||||
@ -558,7 +559,7 @@ var _ = Describe("Commands", func() {
|
||||
})
|
||||
|
||||
It("should InfoMap Modules", Label("redis.info"), func() {
|
||||
SkipBeforeRedisMajor(8, "modules are included in info for Redis Version >= 8")
|
||||
SkipBeforeRedisVersion(8, "modules are included in info for Redis Version >= 8")
|
||||
info := client.InfoMap(ctx)
|
||||
Expect(info.Err()).NotTo(HaveOccurred())
|
||||
Expect(info.Val()).NotTo(BeNil())
|
||||
@ -701,8 +702,8 @@ var _ = Describe("Commands", func() {
|
||||
})
|
||||
})
|
||||
|
||||
Describe("debugging", func() {
|
||||
PIt("should DebugObject", func() {
|
||||
Describe("debugging", Label("NonRedisEnterprise"), func() {
|
||||
It("should DebugObject", func() {
|
||||
err := client.DebugObject(ctx, "foo").Err()
|
||||
Expect(err).To(MatchError("ERR no such key"))
|
||||
|
||||
@ -1332,6 +1333,7 @@ var _ = Describe("Commands", func() {
|
||||
})
|
||||
|
||||
It("should HScan without values", Label("NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||
for i := 0; i < 1000; i++ {
|
||||
sadd := client.HSet(ctx, "myhash", fmt.Sprintf("key%d", i), "hello")
|
||||
Expect(sadd.Err()).NotTo(HaveOccurred())
|
||||
@ -2625,6 +2627,7 @@ var _ = Describe("Commands", func() {
|
||||
})
|
||||
|
||||
It("should HExpire", Label("hash-expiration", "NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||
res, err := client.HExpire(ctx, "no_such_key", 10*time.Second, "field1", "field2", "field3").Result()
|
||||
Expect(err).To(BeNil())
|
||||
Expect(res).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
||||
@ -2640,6 +2643,7 @@ var _ = Describe("Commands", func() {
|
||||
})
|
||||
|
||||
It("should HPExpire", Label("hash-expiration", "NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||
res, err := client.HPExpire(ctx, "no_such_key", 10*time.Second, "field1", "field2", "field3").Result()
|
||||
Expect(err).To(BeNil())
|
||||
Expect(res).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
||||
@ -2655,6 +2659,7 @@ var _ = Describe("Commands", func() {
|
||||
})
|
||||
|
||||
It("should HExpireAt", Label("hash-expiration", "NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||
resEmpty, err := client.HExpireAt(ctx, "no_such_key", time.Now().Add(10*time.Second), "field1", "field2", "field3").Result()
|
||||
Expect(err).To(BeNil())
|
||||
Expect(resEmpty).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
||||
@ -2670,6 +2675,7 @@ var _ = Describe("Commands", func() {
|
||||
})
|
||||
|
||||
It("should HPExpireAt", Label("hash-expiration", "NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||
resEmpty, err := client.HPExpireAt(ctx, "no_such_key", time.Now().Add(10*time.Second), "field1", "field2", "field3").Result()
|
||||
Expect(err).To(BeNil())
|
||||
Expect(resEmpty).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
||||
@ -2685,6 +2691,7 @@ var _ = Describe("Commands", func() {
|
||||
})
|
||||
|
||||
It("should HPersist", Label("hash-expiration", "NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||
resEmpty, err := client.HPersist(ctx, "no_such_key", "field1", "field2", "field3").Result()
|
||||
Expect(err).To(BeNil())
|
||||
Expect(resEmpty).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
||||
@ -2708,6 +2715,7 @@ var _ = Describe("Commands", func() {
|
||||
})
|
||||
|
||||
It("should HExpireTime", Label("hash-expiration", "NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||
resEmpty, err := client.HExpireTime(ctx, "no_such_key", "field1", "field2", "field3").Result()
|
||||
Expect(err).To(BeNil())
|
||||
Expect(resEmpty).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
||||
@ -2727,6 +2735,7 @@ var _ = Describe("Commands", func() {
|
||||
})
|
||||
|
||||
It("should HPExpireTime", Label("hash-expiration", "NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||
resEmpty, err := client.HPExpireTime(ctx, "no_such_key", "field1", "field2", "field3").Result()
|
||||
Expect(err).To(BeNil())
|
||||
Expect(resEmpty).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
||||
@ -2747,6 +2756,7 @@ var _ = Describe("Commands", func() {
|
||||
})
|
||||
|
||||
It("should HTTL", Label("hash-expiration", "NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||
resEmpty, err := client.HTTL(ctx, "no_such_key", "field1", "field2", "field3").Result()
|
||||
Expect(err).To(BeNil())
|
||||
Expect(resEmpty).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
||||
@ -2766,6 +2776,7 @@ var _ = Describe("Commands", func() {
|
||||
})
|
||||
|
||||
It("should HPTTL", Label("hash-expiration", "NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||
resEmpty, err := client.HPTTL(ctx, "no_such_key", "field1", "field2", "field3").Result()
|
||||
Expect(err).To(BeNil())
|
||||
Expect(resEmpty).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
||||
@ -6040,6 +6051,7 @@ var _ = Describe("Commands", func() {
|
||||
})
|
||||
|
||||
It("should XRead LastEntry", Label("NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||
res, err := client.XRead(ctx, &redis.XReadArgs{
|
||||
Streams: []string{"stream"},
|
||||
Count: 2, // we expect 1 message
|
||||
@ -6057,6 +6069,7 @@ var _ = Describe("Commands", func() {
|
||||
})
|
||||
|
||||
It("should XRead LastEntry from two streams", Label("NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||
res, err := client.XRead(ctx, &redis.XReadArgs{
|
||||
Streams: []string{"stream", "stream"},
|
||||
ID: "+",
|
||||
@ -6079,6 +6092,7 @@ var _ = Describe("Commands", func() {
|
||||
})
|
||||
|
||||
It("should XRead LastEntry blocks", Label("NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||
start := time.Now()
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
@ -6614,14 +6628,12 @@ var _ = Describe("Commands", func() {
|
||||
|
||||
res, err := client.ZRangeWithScores(ctx, "result", 0, -1).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(res).To(ContainElement(redis.Z{
|
||||
Score: 190.44242984775784,
|
||||
Member: "Palermo",
|
||||
}))
|
||||
Expect(res).To(ContainElement(redis.Z{
|
||||
Score: 56.4412578701582,
|
||||
Member: "Catania",
|
||||
}))
|
||||
Expect(len(res)).To(Equal(2))
|
||||
var palermo, catania redis.Z
|
||||
Expect(res).To(ContainElement(HaveField("Member", "Palermo"), &palermo))
|
||||
Expect(res).To(ContainElement(HaveField("Member", "Catania"), &catania))
|
||||
Expect(palermo.Score).To(BeNumerically("~", 190, 1))
|
||||
Expect(catania.Score).To(BeNumerically("~", 56, 1))
|
||||
})
|
||||
|
||||
It("should search geo radius with options", func() {
|
||||
@ -6933,16 +6945,13 @@ var _ = Describe("Commands", func() {
|
||||
|
||||
v, err := client.ZRangeWithScores(ctx, "key2", 0, -1).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(v).To(Equal([]redis.Z{
|
||||
{
|
||||
Score: 56.441257870158204,
|
||||
Member: "Catania",
|
||||
},
|
||||
{
|
||||
Score: 190.44242984775784,
|
||||
Member: "Palermo",
|
||||
},
|
||||
}))
|
||||
|
||||
Expect(len(v)).To(Equal(2))
|
||||
var palermo, catania redis.Z
|
||||
Expect(v).To(ContainElement(HaveField("Member", "Palermo"), &palermo))
|
||||
Expect(v).To(ContainElement(HaveField("Member", "Catania"), &catania))
|
||||
Expect(palermo.Score).To(BeNumerically("~", 190, 1))
|
||||
Expect(catania.Score).To(BeNumerically("~", 56, 1))
|
||||
})
|
||||
})
|
||||
|
||||
@ -7332,6 +7341,7 @@ var _ = Describe("Commands", func() {
|
||||
})
|
||||
|
||||
It("Shows function stats", func() {
|
||||
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||
defer client.FunctionKill(ctx)
|
||||
|
||||
// We can not run blocking commands in Redis functions, so we're using an infinite loop,
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
services:
|
||||
redis:
|
||||
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:7.4.1}
|
||||
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:rs-7.4.0-v2}
|
||||
container_name: redis-standalone
|
||||
environment:
|
||||
- TLS_ENABLED=yes
|
||||
@ -21,9 +21,9 @@ services:
|
||||
- all-stack
|
||||
- all
|
||||
|
||||
cluster:
|
||||
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:7.4.1}
|
||||
container_name: redis-cluster
|
||||
osscluster:
|
||||
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:rs-7.4.0-v2}
|
||||
container_name: redis-osscluster
|
||||
environment:
|
||||
- NODES=6
|
||||
- PORT=16600
|
||||
@ -31,110 +31,71 @@ services:
|
||||
ports:
|
||||
- "16600-16605:16600-16605"
|
||||
volumes:
|
||||
- "./dockers/cluster:/redis/work"
|
||||
- "./dockers/osscluster:/redis/work"
|
||||
profiles:
|
||||
- cluster
|
||||
- all-stack
|
||||
- all
|
||||
|
||||
sentinel-cluster:
|
||||
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:rs-7.4.0-v2}
|
||||
container_name: redis-sentinel-cluster
|
||||
network_mode: "host"
|
||||
environment:
|
||||
- NODES=3
|
||||
- TLS_ENABLED=yes
|
||||
- REDIS_CLUSTER=no
|
||||
- PORT=9121
|
||||
command: ${REDIS_EXTRA_ARGS:---enable-debug-command yes --enable-module-command yes --tls-auth-clients optional --save ""}
|
||||
#ports:
|
||||
# - "9121-9123:9121-9123"
|
||||
volumes:
|
||||
- "./dockers/sentinel-cluster:/redis/work"
|
||||
profiles:
|
||||
- sentinel
|
||||
- all-stack
|
||||
- all
|
||||
|
||||
sentinel:
|
||||
image: ${REDIS_IMAGE:-redis:7.4.1}
|
||||
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:rs-7.4.0-v2}
|
||||
container_name: redis-sentinel
|
||||
depends_on:
|
||||
- redis
|
||||
entrypoint: "redis-sentinel /redis.conf --port 26379"
|
||||
ports:
|
||||
- 26379:26379
|
||||
volumes:
|
||||
- "./dockers/sentinel.conf:/redis.conf"
|
||||
profiles:
|
||||
- sentinel
|
||||
- all-stack
|
||||
- all
|
||||
|
||||
sentinel2:
|
||||
image: ${REDIS_IMAGE:-redis:7.4.1}
|
||||
container_name: redis-sentinel2
|
||||
depends_on:
|
||||
- redis
|
||||
entrypoint: "redis-sentinel /redis.conf --port 26380"
|
||||
ports:
|
||||
- 26380:26380
|
||||
volumes:
|
||||
- "./dockers/sentinel.conf:/redis.conf"
|
||||
profiles:
|
||||
- sentinel
|
||||
- all-stack
|
||||
- all
|
||||
|
||||
sentinel3:
|
||||
image: ${REDIS_IMAGE:-redis:7.4.1}
|
||||
container_name: redis-sentinel3
|
||||
depends_on:
|
||||
- redis
|
||||
entrypoint: "redis-sentinel /redis.conf --port 26381"
|
||||
ports:
|
||||
- 26381:26381
|
||||
volumes:
|
||||
- "./dockers/sentinel.conf:/redis.conf"
|
||||
profiles:
|
||||
- sentinel
|
||||
- all-stack
|
||||
- all
|
||||
|
||||
redisRing1:
|
||||
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:7.4.1}
|
||||
container_name: redis-ring-1
|
||||
- sentinel-cluster
|
||||
environment:
|
||||
- NODES=3
|
||||
- REDIS_CLUSTER=no
|
||||
- PORT=26379
|
||||
command: ${REDIS_EXTRA_ARGS:---sentinel}
|
||||
network_mode: "host"
|
||||
#ports:
|
||||
# - 26379:26379
|
||||
# - 26380:26380
|
||||
# - 26381:26381
|
||||
volumes:
|
||||
- "./dockers/sentinel.conf:/redis/config-default/redis.conf"
|
||||
- "./dockers/sentinel:/redis/work"
|
||||
profiles:
|
||||
- sentinel
|
||||
- all-stack
|
||||
- all
|
||||
|
||||
ring-cluster:
|
||||
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:rs-7.4.0-v2}
|
||||
container_name: redis-ring-cluster
|
||||
environment:
|
||||
- NODES=3
|
||||
- TLS_ENABLED=yes
|
||||
- REDIS_CLUSTER=no
|
||||
- PORT=6390
|
||||
command: ${REDIS_EXTRA_ARGS:---enable-debug-command yes --enable-module-command yes --tls-auth-clients optional --save ""}
|
||||
ports:
|
||||
- 6390:6390
|
||||
volumes:
|
||||
- "./dockers/ring1:/redis/work"
|
||||
profiles:
|
||||
- ring
|
||||
- cluster
|
||||
- sentinel
|
||||
- all-stack
|
||||
- all
|
||||
|
||||
redisRing2:
|
||||
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:7.4.1}
|
||||
container_name: redis-ring-2
|
||||
environment:
|
||||
- TLS_ENABLED=yes
|
||||
- REDIS_CLUSTER=no
|
||||
- PORT=6391
|
||||
command: ${REDIS_EXTRA_ARGS:---enable-debug-command yes --enable-module-command yes --tls-auth-clients optional --save ""}
|
||||
ports:
|
||||
- 6391:6391
|
||||
volumes:
|
||||
- "./dockers/ring2:/redis/work"
|
||||
profiles:
|
||||
- ring
|
||||
- cluster
|
||||
- sentinel
|
||||
- all-stack
|
||||
- all
|
||||
|
||||
redisRing3:
|
||||
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:7.4.1}
|
||||
container_name: redis-ring-3
|
||||
environment:
|
||||
- TLS_ENABLED=yes
|
||||
- REDIS_CLUSTER=no
|
||||
- PORT=6392
|
||||
command: ${REDIS_EXTRA_ARGS:---enable-debug-command yes --enable-module-command yes --tls-auth-clients optional --save ""}
|
||||
ports:
|
||||
- 6392:6392
|
||||
volumes:
|
||||
- "./dockers/ring3:/redis/work"
|
||||
- "./dockers/ring:/redis/work"
|
||||
profiles:
|
||||
- ring
|
||||
- cluster
|
||||
- sentinel
|
||||
- all-stack
|
||||
- all
|
||||
- all
|
||||
|
7
dockers/.gitignore
vendored
7
dockers/.gitignore
vendored
@ -1 +1,6 @@
|
||||
*/
|
||||
osscluster/
|
||||
ring/
|
||||
standalone/
|
||||
sentinel-cluster/
|
||||
sentinel/
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
sentinel resolve-hostnames yes
|
||||
sentinel monitor go-redis-test redis 6379 2
|
||||
sentinel monitor go-redis-test 127.0.0.1 9121 2
|
||||
sentinel down-after-milliseconds go-redis-test 5000
|
||||
sentinel failover-timeout go-redis-test 60000
|
||||
sentinel parallel-syncs go-redis-test 1
|
||||
sentinel parallel-syncs go-redis-test 1
|
@ -21,6 +21,8 @@ func ExampleClient_bloom() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// make sure we are working with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:models")
|
||||
// REMOVE_END
|
||||
|
||||
|
@ -21,6 +21,8 @@ func ExampleClient_bf() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// make sure we are working with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bike:1:stats")
|
||||
// REMOVE_END
|
||||
|
||||
|
@ -21,6 +21,8 @@ func ExampleClient_ping() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// make sure we are working with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "pings:2024-01-01-00:00")
|
||||
// REMOVE_END
|
||||
|
||||
@ -66,6 +68,8 @@ func ExampleClient_bitcount() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
_, err := rdb.SetBit(ctx, "pings:2024-01-01-00:00", 123, 1).Result()
|
||||
|
||||
if err != nil {
|
||||
|
@ -23,6 +23,8 @@ func ExampleClient_del_cmd() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// make sure we are working with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "key1", "key2", "key3")
|
||||
// REMOVE_END
|
||||
|
||||
@ -68,6 +70,8 @@ func ExampleClient_expire_cmd() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "mykey")
|
||||
// REMOVE_END
|
||||
|
||||
@ -167,6 +171,8 @@ func ExampleClient_ttl_cmd() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "mykey")
|
||||
// REMOVE_END
|
||||
|
||||
|
@ -22,6 +22,8 @@ func ExampleClient_hset() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// make sure we are working with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "myhash")
|
||||
// REMOVE_END
|
||||
|
||||
@ -112,6 +114,8 @@ func ExampleClient_hget() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "myhash")
|
||||
// REMOVE_END
|
||||
|
||||
@ -157,6 +161,8 @@ func ExampleClient_hgetall() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "myhash")
|
||||
// REMOVE_END
|
||||
|
||||
@ -209,6 +215,8 @@ func ExampleClient_hvals() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "myhash")
|
||||
// REMOVE_END
|
||||
|
||||
|
@ -22,6 +22,8 @@ func ExampleClient_cmd_flushall() {
|
||||
|
||||
// STEP_START flushall
|
||||
// REMOVE_START
|
||||
// make sure we are working with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Set(ctx, "testkey1", "1", 0)
|
||||
rdb.Set(ctx, "testkey2", "2", 0)
|
||||
rdb.Set(ctx, "testkey3", "3", 0)
|
||||
|
@ -21,6 +21,8 @@ func ExampleClient_zadd_cmd() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// make sure we are working with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "myzset")
|
||||
// REMOVE_END
|
||||
|
||||
@ -82,6 +84,8 @@ func ExampleClient_zrange1() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "myzset")
|
||||
// REMOVE_END
|
||||
|
||||
@ -140,6 +144,8 @@ func ExampleClient_zrange2() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "myzset")
|
||||
// REMOVE_END
|
||||
|
||||
@ -180,6 +186,8 @@ func ExampleClient_zrange3() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "myzset")
|
||||
// REMOVE_END
|
||||
|
||||
|
@ -21,6 +21,8 @@ func ExampleClient_cmd_incr() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// make sure we are working with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "mykey")
|
||||
// REMOVE_END
|
||||
|
||||
|
@ -21,6 +21,8 @@ func ExampleClient_cms() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// make sure we are working with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:profit")
|
||||
// REMOVE_END
|
||||
|
||||
|
@ -21,6 +21,8 @@ func ExampleClient_cuckoo() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// make sure we are working with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:models")
|
||||
// REMOVE_END
|
||||
|
||||
|
@ -20,7 +20,10 @@ func ExampleClient_geoindex() {
|
||||
DB: 0, // use default DB
|
||||
Protocol: 2,
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// make sure we are working with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.FTDropIndex(ctx, "productidx")
|
||||
rdb.FTDropIndex(ctx, "geomidx")
|
||||
rdb.Del(ctx, "product:46885", "product:46886", "shape:1", "shape:2", "shape:3", "shape:4")
|
||||
|
@ -21,6 +21,8 @@ func ExampleClient_geoadd() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// make sure we are working with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:rentable")
|
||||
// REMOVE_END
|
||||
|
||||
@ -81,6 +83,8 @@ func ExampleClient_geosearch() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:rentable")
|
||||
|
||||
_, err := rdb.GeoAdd(ctx, "bikes:rentable",
|
||||
|
@ -21,6 +21,8 @@ func ExampleClient_set_get_all() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// make sure we are working with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bike:1")
|
||||
// REMOVE_END
|
||||
|
||||
@ -102,6 +104,8 @@ func ExampleClient_hmget() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bike:1")
|
||||
// REMOVE_END
|
||||
|
||||
@ -160,6 +164,8 @@ func ExampleClient_hincrby() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bike:1")
|
||||
// REMOVE_END
|
||||
|
||||
@ -209,6 +215,8 @@ func ExampleClient_incrby_get_mget() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bike:1:stats")
|
||||
// REMOVE_END
|
||||
|
||||
|
@ -21,6 +21,8 @@ func ExampleClient_pfadd() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// make sure we are working with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes", "commuter_bikes", "all_bikes")
|
||||
// REMOVE_END
|
||||
|
||||
|
@ -26,6 +26,8 @@ func ExampleClient_search_json() {
|
||||
})
|
||||
// STEP_END
|
||||
// REMOVE_START
|
||||
// make sure we are working with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "user:1", "user:2", "user:3")
|
||||
rdb.FTDropIndex(ctx, "idx:users")
|
||||
// REMOVE_END
|
||||
|
@ -20,6 +20,8 @@ func ExampleClient_setget() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// make sure we are working with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bike")
|
||||
// REMOVE_END
|
||||
|
||||
@ -67,6 +69,8 @@ func ExampleClient_str() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bike")
|
||||
// REMOVE_END
|
||||
|
||||
@ -120,6 +124,8 @@ func ExampleClient_num() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "crashes")
|
||||
// REMOVE_END
|
||||
|
||||
@ -174,6 +180,8 @@ func ExampleClient_arr() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "newbike")
|
||||
// REMOVE_END
|
||||
|
||||
|
@ -21,6 +21,8 @@ func ExampleClient_queue() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// make sure we are working with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:repairs")
|
||||
// REMOVE_END
|
||||
|
||||
@ -75,6 +77,8 @@ func ExampleClient_stack() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:repairs")
|
||||
// REMOVE_END
|
||||
|
||||
@ -129,6 +133,8 @@ func ExampleClient_llen() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:repairs")
|
||||
// REMOVE_END
|
||||
|
||||
@ -156,6 +162,8 @@ func ExampleClient_lmove_lrange() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:repairs")
|
||||
rdb.Del(ctx, "bikes:finished")
|
||||
// REMOVE_END
|
||||
@ -220,6 +228,8 @@ func ExampleClient_lpush_rpush() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:repairs")
|
||||
// REMOVE_END
|
||||
|
||||
@ -274,6 +284,8 @@ func ExampleClient_variadic() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:repairs")
|
||||
// REMOVE_END
|
||||
|
||||
@ -319,6 +331,8 @@ func ExampleClient_lpop_rpop() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:repairs")
|
||||
// REMOVE_END
|
||||
|
||||
@ -384,6 +398,8 @@ func ExampleClient_ltrim() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:repairs")
|
||||
// REMOVE_END
|
||||
|
||||
@ -429,6 +445,8 @@ func ExampleClient_ltrim_end_of_list() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:repairs")
|
||||
// REMOVE_END
|
||||
|
||||
@ -474,6 +492,8 @@ func ExampleClient_brpop() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:repairs")
|
||||
// REMOVE_END
|
||||
|
||||
@ -529,6 +549,8 @@ func ExampleClient_rule1() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "new_bikes")
|
||||
// REMOVE_END
|
||||
|
||||
|
@ -20,6 +20,8 @@ func ExampleClient_transactions() {
|
||||
DB: 0, // use default DB
|
||||
})
|
||||
// REMOVE_START
|
||||
// make sure we are working with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
for i := 0; i < 5; i++ {
|
||||
rdb.Del(ctx, fmt.Sprintf("seat:%d", i))
|
||||
}
|
||||
|
@ -21,6 +21,8 @@ func ExampleClient_query_agg() {
|
||||
})
|
||||
// HIDE_END
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.FTDropIndex(ctx, "idx:bicycle")
|
||||
rdb.FTDropIndex(ctx, "idx:email")
|
||||
// REMOVE_END
|
||||
|
@ -5,6 +5,8 @@ package example_commands_test
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
@ -21,6 +23,8 @@ func ExampleClient_query_em() {
|
||||
|
||||
// HIDE_END
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.FTDropIndex(ctx, "idx:bicycle")
|
||||
rdb.FTDropIndex(ctx, "idx:email")
|
||||
// REMOVE_END
|
||||
@ -274,11 +278,16 @@ func ExampleClient_query_em() {
|
||||
|
||||
fmt.Println(res3.Total) // >>> 5
|
||||
|
||||
for _, doc := range res3.Docs {
|
||||
docs := res3.Docs
|
||||
slices.SortFunc(docs, func(a, b redis.Document) int {
|
||||
return strings.Compare(a.ID, b.ID)
|
||||
})
|
||||
|
||||
for _, doc := range docs {
|
||||
fmt.Println(doc.ID)
|
||||
}
|
||||
// >>> bicycle:5
|
||||
// >>> bicycle:0
|
||||
// >>> bicycle:5
|
||||
// >>> bicycle:6
|
||||
// >>> bicycle:7
|
||||
// >>> bicycle:8
|
||||
@ -350,8 +359,8 @@ func ExampleClient_query_em() {
|
||||
// 1
|
||||
// bicycle:0
|
||||
// 5
|
||||
// bicycle:5
|
||||
// bicycle:0
|
||||
// bicycle:5
|
||||
// bicycle:6
|
||||
// bicycle:7
|
||||
// bicycle:8
|
||||
|
@ -21,6 +21,8 @@ func ExampleClient_query_ft() {
|
||||
})
|
||||
// HIDE_END
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.FTDropIndex(ctx, "idx:bicycle")
|
||||
rdb.FTDropIndex(ctx, "idx:email")
|
||||
// REMOVE_END
|
||||
|
@ -21,6 +21,8 @@ func ExampleClient_query_geo() {
|
||||
})
|
||||
// HIDE_END
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.FTDropIndex(ctx, "idx:bicycle")
|
||||
// REMOVE_END
|
||||
|
||||
|
@ -21,6 +21,8 @@ func ExampleClient_Set_and_get() {
|
||||
// HIDE_END
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
errFlush := rdb.FlushDB(ctx).Err() // Clear the database before each test
|
||||
if errFlush != nil {
|
||||
panic(errFlush)
|
||||
|
@ -21,6 +21,8 @@ func ExampleClient_sadd() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:racing:france")
|
||||
rdb.Del(ctx, "bikes:racing:usa")
|
||||
// REMOVE_END
|
||||
@ -76,6 +78,8 @@ func ExampleClient_sismember() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:racing:france")
|
||||
rdb.Del(ctx, "bikes:racing:usa")
|
||||
// REMOVE_END
|
||||
@ -125,6 +129,8 @@ func ExampleClient_sinter() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:racing:france")
|
||||
rdb.Del(ctx, "bikes:racing:usa")
|
||||
// REMOVE_END
|
||||
@ -165,6 +171,8 @@ func ExampleClient_scard() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:racing:france")
|
||||
// REMOVE_END
|
||||
|
||||
@ -198,6 +206,8 @@ func ExampleClient_saddsmembers() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:racing:france")
|
||||
// REMOVE_END
|
||||
|
||||
@ -216,7 +226,7 @@ func ExampleClient_saddsmembers() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Sort the strings in the slice to make sure the output is lexicographical
|
||||
// Sort the strings in the slice to make sure the output is lexicographical
|
||||
sort.Strings(res10)
|
||||
|
||||
fmt.Println(res10) // >>> [bike:1 bike:2 bike:3]
|
||||
@ -237,6 +247,8 @@ func ExampleClient_smismember() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:racing:france")
|
||||
// REMOVE_END
|
||||
|
||||
@ -279,6 +291,8 @@ func ExampleClient_sdiff() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:racing:france")
|
||||
rdb.Del(ctx, "bikes:racing:usa")
|
||||
// REMOVE_END
|
||||
@ -298,8 +312,7 @@ func ExampleClient_sdiff() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
|
||||
// Sort the strings in the slice to make sure the output is lexicographical
|
||||
// Sort the strings in the slice to make sure the output is lexicographical
|
||||
sort.Strings(res13)
|
||||
|
||||
fmt.Println(res13) // >>> [bike:2 bike:3]
|
||||
@ -319,6 +332,8 @@ func ExampleClient_multisets() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:racing:france")
|
||||
rdb.Del(ctx, "bikes:racing:usa")
|
||||
rdb.Del(ctx, "bikes:racing:italy")
|
||||
@ -357,7 +372,7 @@ func ExampleClient_multisets() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Sort the strings in the slice to make sure the output is lexicographical
|
||||
// Sort the strings in the slice to make sure the output is lexicographical
|
||||
sort.Strings(res15)
|
||||
|
||||
fmt.Println(res15) // >>> [bike:1 bike:2 bike:3 bike:4]
|
||||
@ -384,7 +399,7 @@ func ExampleClient_multisets() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Sort the strings in the slice to make sure the output is lexicographical
|
||||
// Sort the strings in the slice to make sure the output is lexicographical
|
||||
sort.Strings(res18)
|
||||
|
||||
fmt.Println(res18) // >>> [bike:2 bike:3]
|
||||
@ -408,6 +423,8 @@ func ExampleClient_srem() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:racing:france")
|
||||
// REMOVE_END
|
||||
|
||||
|
@ -20,6 +20,8 @@ func ExampleClient_zadd() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "racer_scores")
|
||||
// REMOVE_END
|
||||
|
||||
@ -76,6 +78,8 @@ func ExampleClient_zrange() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "racer_scores")
|
||||
// REMOVE_END
|
||||
|
||||
@ -127,6 +131,8 @@ func ExampleClient_zrangewithscores() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "racer_scores")
|
||||
// REMOVE_END
|
||||
|
||||
@ -168,6 +174,8 @@ func ExampleClient_zrangebyscore() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "racer_scores")
|
||||
// REMOVE_END
|
||||
|
||||
@ -211,6 +219,8 @@ func ExampleClient_zremrangebyscore() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "racer_scores")
|
||||
// REMOVE_END
|
||||
|
||||
@ -270,6 +280,8 @@ func ExampleClient_zrank() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "racer_scores")
|
||||
// REMOVE_END
|
||||
|
||||
@ -316,6 +328,8 @@ func ExampleClient_zaddlex() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "racer_scores")
|
||||
// REMOVE_END
|
||||
|
||||
@ -377,6 +391,8 @@ func ExampleClient_leaderboard() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "racer_scores")
|
||||
// REMOVE_END
|
||||
|
||||
|
@ -26,6 +26,8 @@ func ExampleClient_xadd() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "race:france")
|
||||
// REMOVE_END
|
||||
|
||||
@ -105,6 +107,8 @@ func ExampleClient_racefrance1() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "race:france")
|
||||
// REMOVE_END
|
||||
|
||||
@ -227,6 +231,8 @@ func ExampleClient_raceusa() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "race:usa")
|
||||
// REMOVE_END
|
||||
|
||||
@ -310,6 +316,8 @@ func ExampleClient_racefrance2() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "race:france")
|
||||
// REMOVE_END
|
||||
|
||||
@ -478,6 +486,8 @@ func ExampleClient_xgroupcreate() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "race:france")
|
||||
// REMOVE_END
|
||||
|
||||
@ -520,6 +530,8 @@ func ExampleClient_xgroupcreatemkstream() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "race:italy")
|
||||
// REMOVE_END
|
||||
|
||||
@ -549,6 +561,8 @@ func ExampleClient_xgroupread() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "race:italy")
|
||||
// REMOVE_END
|
||||
|
||||
@ -654,6 +668,8 @@ func ExampleClient_raceitaly() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "race:italy")
|
||||
rdb.XGroupDestroy(ctx, "race:italy", "italy_riders")
|
||||
// REMOVE_END
|
||||
@ -1011,6 +1027,8 @@ func ExampleClient_xdel() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "race:italy")
|
||||
// REMOVE_END
|
||||
|
||||
|
@ -20,6 +20,8 @@ func ExampleClient_set_get() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bike:1")
|
||||
// REMOVE_END
|
||||
|
||||
@ -56,6 +58,8 @@ func ExampleClient_setnx_xx() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Set(ctx, "bike:1", "Deimos", 0)
|
||||
// REMOVE_END
|
||||
|
||||
@ -101,6 +105,8 @@ func ExampleClient_mset() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bike:1", "bike:2", "bike:3")
|
||||
// REMOVE_END
|
||||
|
||||
@ -137,6 +143,8 @@ func ExampleClient_incr() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "total_crashes")
|
||||
// REMOVE_END
|
||||
|
||||
|
@ -21,6 +21,8 @@ func ExampleClient_tdigstart() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "racer_ages", "bikes:sales")
|
||||
// REMOVE_END
|
||||
|
||||
@ -69,6 +71,8 @@ func ExampleClient_tdigcdf() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "racer_ages", "bikes:sales")
|
||||
// REMOVE_END
|
||||
|
||||
@ -126,6 +130,8 @@ func ExampleClient_tdigquant() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "racer_ages")
|
||||
// REMOVE_END
|
||||
|
||||
@ -177,6 +183,8 @@ func ExampleClient_tdigmin() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "racer_ages")
|
||||
// REMOVE_END
|
||||
|
||||
@ -228,6 +236,8 @@ func ExampleClient_tdigreset() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "racer_ages")
|
||||
// REMOVE_END
|
||||
_, err := rdb.TDigestCreate(ctx, "racer_ages").Result()
|
||||
|
@ -21,6 +21,8 @@ func ExampleClient_topk() {
|
||||
})
|
||||
|
||||
// REMOVE_START
|
||||
// start with fresh database
|
||||
rdb.FlushDB(ctx)
|
||||
rdb.Del(ctx, "bikes:keywords")
|
||||
// REMOVE_END
|
||||
|
||||
|
@ -10,6 +10,6 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
)
|
||||
|
@ -34,6 +34,7 @@ func libCodeWithConfig(libName string) string {
|
||||
return fmt.Sprintf(lib, libName)
|
||||
}
|
||||
|
||||
// TODO: Drop Gears
|
||||
var _ = Describe("RedisGears commands", Label("gears"), func() {
|
||||
ctx := context.TODO()
|
||||
var client *redis.Client
|
||||
@ -49,6 +50,7 @@ var _ = Describe("RedisGears commands", Label("gears"), func() {
|
||||
})
|
||||
|
||||
It("should TFunctionLoad, TFunctionLoadArgs and TFunctionDelete ", Label("gears", "tfunctionload"), func() {
|
||||
SkipAfterRedisVersion(7.4, "gears are not working in later versions")
|
||||
resultAdd, err := client.TFunctionLoad(ctx, libCode("lib1")).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(resultAdd).To(BeEquivalentTo("OK"))
|
||||
@ -58,6 +60,7 @@ var _ = Describe("RedisGears commands", Label("gears"), func() {
|
||||
Expect(resultAdd).To(BeEquivalentTo("OK"))
|
||||
})
|
||||
It("should TFunctionList", Label("gears", "tfunctionlist"), func() {
|
||||
SkipAfterRedisVersion(7.4, "gears are not working in later versions")
|
||||
resultAdd, err := client.TFunctionLoad(ctx, libCode("lib1")).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(resultAdd).To(BeEquivalentTo("OK"))
|
||||
@ -71,6 +74,7 @@ var _ = Describe("RedisGears commands", Label("gears"), func() {
|
||||
})
|
||||
|
||||
It("should TFCall", Label("gears", "tfcall"), func() {
|
||||
SkipAfterRedisVersion(7.4, "gears are not working in later versions")
|
||||
var resultAdd interface{}
|
||||
resultAdd, err := client.TFunctionLoad(ctx, libCode("lib1")).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
@ -81,6 +85,7 @@ var _ = Describe("RedisGears commands", Label("gears"), func() {
|
||||
})
|
||||
|
||||
It("should TFCallArgs", Label("gears", "tfcallargs"), func() {
|
||||
SkipAfterRedisVersion(7.4, "gears are not working in later versions")
|
||||
var resultAdd interface{}
|
||||
resultAdd, err := client.TFunctionLoad(ctx, libCode("lib1")).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
@ -92,6 +97,7 @@ var _ = Describe("RedisGears commands", Label("gears"), func() {
|
||||
})
|
||||
|
||||
It("should TFCallASYNC", Label("gears", "TFCallASYNC"), func() {
|
||||
SkipAfterRedisVersion(7.4, "gears are not working in later versions")
|
||||
var resultAdd interface{}
|
||||
resultAdd, err := client.TFunctionLoad(ctx, libCode("lib1")).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
@ -102,6 +108,7 @@ var _ = Describe("RedisGears commands", Label("gears"), func() {
|
||||
})
|
||||
|
||||
It("should TFCallASYNCArgs", Label("gears", "TFCallASYNCargs"), func() {
|
||||
SkipAfterRedisVersion(7.4, "gears are not working in later versions")
|
||||
var resultAdd interface{}
|
||||
resultAdd, err := client.TFunctionLoad(ctx, libCode("lib1")).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
@ -292,8 +292,8 @@ var _ = Describe("race", func() {
|
||||
BeforeEach(func() {
|
||||
C, N = 10, 1000
|
||||
if testing.Short() {
|
||||
C = 4
|
||||
N = 100
|
||||
C = 2
|
||||
N = 50
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -85,6 +85,7 @@ var _ = Describe("ScanIterator", func() {
|
||||
})
|
||||
|
||||
It("should hscan across multiple pages", func() {
|
||||
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||
Expect(hashSeed(71)).NotTo(HaveOccurred())
|
||||
|
||||
var vals []string
|
||||
@ -100,6 +101,7 @@ var _ = Describe("ScanIterator", func() {
|
||||
})
|
||||
|
||||
It("should hscan without values across multiple pages", Label("NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||
Expect(hashSeed(71)).NotTo(HaveOccurred())
|
||||
|
||||
var vals []string
|
||||
|
226
main_test.go
226
main_test.go
@ -4,9 +4,8 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
@ -28,12 +27,12 @@ const (
|
||||
|
||||
const (
|
||||
sentinelName = "go-redis-test"
|
||||
sentinelMasterPort = "9123"
|
||||
sentinelSlave1Port = "9124"
|
||||
sentinelSlave2Port = "9125"
|
||||
sentinelPort1 = "9126"
|
||||
sentinelPort2 = "9127"
|
||||
sentinelPort3 = "9128"
|
||||
sentinelMasterPort = "9121"
|
||||
sentinelSlave1Port = "9122"
|
||||
sentinelSlave2Port = "9123"
|
||||
sentinelPort1 = "26379"
|
||||
sentinelPort2 = "26380"
|
||||
sentinelPort3 = "26381"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -49,19 +48,15 @@ var (
|
||||
var (
|
||||
sentinelAddrs = []string{":" + sentinelPort1, ":" + sentinelPort2, ":" + sentinelPort3}
|
||||
|
||||
processes map[string]*redisProcess
|
||||
|
||||
redisMain *redisProcess
|
||||
ringShard1, ringShard2, ringShard3 *redisProcess
|
||||
sentinelMaster, sentinelSlave1, sentinelSlave2 *redisProcess
|
||||
sentinel1, sentinel2, sentinel3 *redisProcess
|
||||
ringShard1, ringShard2, ringShard3 *redis.Client
|
||||
sentinelMaster, sentinelSlave1, sentinelSlave2 *redis.Client
|
||||
sentinel1, sentinel2, sentinel3 *redis.Client
|
||||
)
|
||||
|
||||
var cluster = &clusterScenario{
|
||||
ports: []string{"16600", "16601", "16602", "16603", "16604", "16605"},
|
||||
nodeIDs: make([]string, 6),
|
||||
processes: make(map[string]*redisProcess, 6),
|
||||
clients: make(map[string]*redis.Client, 6),
|
||||
ports: []string{"16600", "16601", "16602", "16603", "16604", "16605"},
|
||||
nodeIDs: make([]string, 6),
|
||||
clients: make(map[string]*redis.Client, 6),
|
||||
}
|
||||
|
||||
// Redis Software Cluster
|
||||
@ -70,30 +65,23 @@ var RECluster = false
|
||||
// Redis Community Edition Docker
|
||||
var RCEDocker = false
|
||||
|
||||
// Notes the major version of redis we are executing tests.
|
||||
// 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 major version.
|
||||
var RedisMajorVersion = 7
|
||||
// which have support for label sets, so we can filter tests per redis version.
|
||||
var RedisVersion float64 = 7.2
|
||||
|
||||
func SkipBeforeRedisMajor(version int, msg string) {
|
||||
if RedisMajorVersion < version {
|
||||
Skip(fmt.Sprintf("(redis major version < %d) %s", version, msg))
|
||||
func SkipBeforeRedisVersion(version float64, msg string) {
|
||||
if RedisVersion < version {
|
||||
Skip(fmt.Sprintf("(redis version < %f) %s", version, msg))
|
||||
}
|
||||
}
|
||||
|
||||
func SkipAfterRedisMajor(version int, msg string) {
|
||||
if RedisMajorVersion > version {
|
||||
Skip(fmt.Sprintf("(redis major version > %d) %s", version, msg))
|
||||
func SkipAfterRedisVersion(version float64, msg string) {
|
||||
if RedisVersion > version {
|
||||
Skip(fmt.Sprintf("(redis version > %f) %s", version, msg))
|
||||
}
|
||||
}
|
||||
|
||||
func registerProcess(port string, p *redisProcess) {
|
||||
if processes == nil {
|
||||
processes = make(map[string]*redisProcess)
|
||||
}
|
||||
processes[port] = p
|
||||
}
|
||||
|
||||
var _ = BeforeSuite(func() {
|
||||
addr := os.Getenv("REDIS_PORT")
|
||||
if addr != "" {
|
||||
@ -104,35 +92,33 @@ var _ = BeforeSuite(func() {
|
||||
RECluster, _ = strconv.ParseBool(os.Getenv("RE_CLUSTER"))
|
||||
RCEDocker, _ = strconv.ParseBool(os.Getenv("RCE_DOCKER"))
|
||||
|
||||
RedisMajorVersion, _ = strconv.Atoi(os.Getenv("REDIS_MAJOR_VERSION"))
|
||||
RedisVersion, _ = strconv.ParseFloat(strings.Trim(os.Getenv("REDIS_VERSION"), "\""), 64)
|
||||
|
||||
if RedisMajorVersion == 0 {
|
||||
RedisMajorVersion = 7
|
||||
if RedisVersion == 0 {
|
||||
RedisVersion = 7.2
|
||||
}
|
||||
|
||||
fmt.Printf("RECluster: %v\n", RECluster)
|
||||
fmt.Printf("RCEDocker: %v\n", RCEDocker)
|
||||
fmt.Printf("REDIS_MAJOR_VERSION: %v\n", RedisMajorVersion)
|
||||
fmt.Printf("REDIS_VERSION: %v\n", RedisVersion)
|
||||
|
||||
if RedisMajorVersion < 6 || RedisMajorVersion > 8 {
|
||||
panic("incorrect or not supported redis major version")
|
||||
if RedisVersion < 7.0 || RedisVersion > 9 {
|
||||
panic("incorrect or not supported redis version")
|
||||
}
|
||||
|
||||
if !RECluster && !RCEDocker {
|
||||
|
||||
redisMain, err = startRedis(redisPort)
|
||||
redisPort = redisStackPort
|
||||
redisAddr = redisStackAddr
|
||||
if !RECluster {
|
||||
ringShard1, err = connectTo(ringShard1Port)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
ringShard1, err = startRedis(ringShard1Port)
|
||||
ringShard2, err = connectTo(ringShard2Port)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
ringShard2, err = startRedis(ringShard2Port)
|
||||
ringShard3, err = connectTo(ringShard3Port)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
ringShard3, err = startRedis(ringShard3Port)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
sentinelMaster, err = startRedis(sentinelMasterPort)
|
||||
sentinelMaster, err = connectTo(sentinelMasterPort)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
sentinel1, err = startSentinel(sentinelPort1, sentinelName, sentinelMasterPort)
|
||||
@ -144,24 +130,20 @@ var _ = BeforeSuite(func() {
|
||||
sentinel3, err = startSentinel(sentinelPort3, sentinelName, sentinelMasterPort)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
sentinelSlave1, err = startRedis(
|
||||
sentinelSlave1Port, "--slaveof", "127.0.0.1", sentinelMasterPort)
|
||||
sentinelSlave1, err = connectTo(sentinelSlave1Port)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
sentinelSlave2, err = startRedis(
|
||||
sentinelSlave2Port, "--slaveof", "127.0.0.1", sentinelMasterPort)
|
||||
err = sentinelSlave1.SlaveOf(ctx, "127.0.0.1", sentinelMasterPort).Err()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = startCluster(ctx, cluster)
|
||||
sentinelSlave2, err = connectTo(sentinelSlave2Port)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
} else {
|
||||
redisPort = redisStackPort
|
||||
redisAddr = redisStackAddr
|
||||
|
||||
if !RECluster {
|
||||
// populate cluster node information
|
||||
Expect(configureClusterTopology(ctx, cluster)).NotTo(HaveOccurred())
|
||||
}
|
||||
err = sentinelSlave2.SlaveOf(ctx, "127.0.0.1", sentinelMasterPort).Err()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// populate cluster node information
|
||||
Expect(configureClusterTopology(ctx, cluster)).NotTo(HaveOccurred())
|
||||
}
|
||||
})
|
||||
|
||||
@ -169,12 +151,6 @@ var _ = AfterSuite(func() {
|
||||
if !RECluster {
|
||||
Expect(cluster.Close()).NotTo(HaveOccurred())
|
||||
}
|
||||
|
||||
// NOOP if there are no processes registered
|
||||
for _, p := range processes {
|
||||
Expect(p.Close()).NotTo(HaveOccurred())
|
||||
}
|
||||
processes = nil
|
||||
})
|
||||
|
||||
func TestGinkgoSuite(t *testing.T) {
|
||||
@ -204,7 +180,7 @@ func redisOptions() *redis.Options {
|
||||
}
|
||||
return &redis.Options{
|
||||
Addr: redisAddr,
|
||||
DB: 15,
|
||||
DB: 0,
|
||||
|
||||
DialTimeout: 10 * time.Second,
|
||||
ReadTimeout: 30 * time.Second,
|
||||
@ -256,7 +232,9 @@ func performAsync(n int, cbs ...func(int)) *sync.WaitGroup {
|
||||
var wg sync.WaitGroup
|
||||
for _, cb := range cbs {
|
||||
wg.Add(n)
|
||||
for i := 0; i < n; i++ {
|
||||
// start from 1, so we can skip db 0 where such test is executed with
|
||||
// select db command
|
||||
for i := 1; i <= n; i++ {
|
||||
go func(cb func(int), i int) {
|
||||
defer GinkgoRecover()
|
||||
defer wg.Done()
|
||||
@ -313,15 +291,6 @@ func eventually(fn func() error, timeout time.Duration) error {
|
||||
}
|
||||
}
|
||||
|
||||
func execCmd(name string, args ...string) (*os.Process, error) {
|
||||
cmd := exec.Command(name, args...)
|
||||
if testing.Verbose() {
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
}
|
||||
return cmd.Process, cmd.Start()
|
||||
}
|
||||
|
||||
func connectTo(port string) (*redis.Client, error) {
|
||||
client := redis.NewClient(&redis.Options{
|
||||
Addr: ":" + port,
|
||||
@ -338,117 +307,22 @@ func connectTo(port string) (*redis.Client, error) {
|
||||
return client, nil
|
||||
}
|
||||
|
||||
type redisProcess struct {
|
||||
*os.Process
|
||||
*redis.Client
|
||||
}
|
||||
|
||||
func (p *redisProcess) Close() error {
|
||||
if err := p.Kill(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err := eventually(func() error {
|
||||
if err := p.Client.Ping(ctx).Err(); err != nil {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("client %s is not shutdown", p.Options().Addr)
|
||||
}, 10*time.Second)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.Client.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
redisServerBin, _ = filepath.Abs(filepath.Join("testdata", "redis", "src", "redis-server"))
|
||||
redisServerConf, _ = filepath.Abs(filepath.Join("testdata", "redis", "redis.conf"))
|
||||
redisSentinelConf, _ = filepath.Abs(filepath.Join("testdata", "redis", "sentinel.conf"))
|
||||
)
|
||||
|
||||
func redisDir(port string) (string, error) {
|
||||
dir, err := filepath.Abs(filepath.Join("testdata", "instances", port))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := os.RemoveAll(dir); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := os.MkdirAll(dir, 0o775); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return dir, nil
|
||||
}
|
||||
|
||||
func startRedis(port string, args ...string) (*redisProcess, error) {
|
||||
dir, err := redisDir(port)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := exec.Command("cp", "-f", redisServerConf, dir).Run(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
baseArgs := []string{filepath.Join(dir, "redis.conf"), "--port", port, "--dir", dir, "--enable-module-command", "yes"}
|
||||
process, err := execCmd(redisServerBin, append(baseArgs, args...)...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func startSentinel(port, masterName, masterPort string) (*redis.Client, error) {
|
||||
client, err := connectTo(port)
|
||||
if err != nil {
|
||||
process.Kill()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p := &redisProcess{process, client}
|
||||
registerProcess(port, p)
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func startSentinel(port, masterName, masterPort string) (*redisProcess, error) {
|
||||
dir, err := redisDir(port)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sentinelConf := filepath.Join(dir, "sentinel.conf")
|
||||
if err := os.WriteFile(sentinelConf, nil, 0o644); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
process, err := execCmd(redisServerBin, sentinelConf, "--sentinel", "--port", port, "--dir", dir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client, err := connectTo(port)
|
||||
if err != nil {
|
||||
process.Kill()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// set down-after-milliseconds=2000
|
||||
// link: https://github.com/redis/redis/issues/8607
|
||||
for _, cmd := range []*redis.StatusCmd{
|
||||
redis.NewStatusCmd(ctx, "SENTINEL", "MONITOR", masterName, "127.0.0.1", masterPort, "2"),
|
||||
redis.NewStatusCmd(ctx, "SENTINEL", "SET", masterName, "down-after-milliseconds", "2000"),
|
||||
redis.NewStatusCmd(ctx, "SENTINEL", "SET", masterName, "failover-timeout", "1000"),
|
||||
redis.NewStatusCmd(ctx, "SENTINEL", "SET", masterName, "parallel-syncs", "1"),
|
||||
} {
|
||||
client.Process(ctx, cmd)
|
||||
if err := cmd.Err(); err != nil {
|
||||
process.Kill()
|
||||
if err := cmd.Err(); err != nil && !strings.Contains(err.Error(), "ERR Duplicate master name.") {
|
||||
return nil, fmt.Errorf("%s failed: %w", cmd, err)
|
||||
}
|
||||
}
|
||||
|
||||
p := &redisProcess{process, client}
|
||||
registerProcess(port, p)
|
||||
return p, nil
|
||||
return client, nil
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@ -19,10 +20,9 @@ import (
|
||||
)
|
||||
|
||||
type clusterScenario struct {
|
||||
ports []string
|
||||
nodeIDs []string
|
||||
processes map[string]*redisProcess
|
||||
clients map[string]*redis.Client
|
||||
ports []string
|
||||
nodeIDs []string
|
||||
clients map[string]*redis.Client
|
||||
}
|
||||
|
||||
func (s *clusterScenario) slots() []int {
|
||||
@ -101,20 +101,17 @@ func (s *clusterScenario) Close() error {
|
||||
}
|
||||
}
|
||||
|
||||
for _, port := range s.ports {
|
||||
if process, ok := processes[port]; ok {
|
||||
if process != nil {
|
||||
process.Close()
|
||||
}
|
||||
|
||||
delete(processes, port)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func configureClusterTopology(ctx context.Context, scenario *clusterScenario) error {
|
||||
allowErrs := []string{
|
||||
"ERR Slot 0 is already busy",
|
||||
"ERR Slot 5461 is already busy",
|
||||
"ERR Slot 10923 is already busy",
|
||||
"ERR Slot 16384 is already busy",
|
||||
}
|
||||
|
||||
err := collectNodeInformation(ctx, scenario)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -131,7 +128,7 @@ func configureClusterTopology(ctx context.Context, scenario *clusterScenario) er
|
||||
slots := scenario.slots()
|
||||
for pos, master := range scenario.masters() {
|
||||
err := master.ClusterAddSlotsRange(ctx, slots[pos], slots[pos+1]-1).Err()
|
||||
if err != nil {
|
||||
if err != nil && slices.Contains(allowErrs, err.Error()) == false {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -199,7 +196,7 @@ func configureClusterTopology(ctx context.Context, scenario *clusterScenario) er
|
||||
return err
|
||||
}
|
||||
return assertSlotsEqual(res, wanted)
|
||||
}, 60*time.Second)
|
||||
}, 90*time.Second)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -214,31 +211,17 @@ func collectNodeInformation(ctx context.Context, scenario *clusterScenario) erro
|
||||
Addr: ":" + port,
|
||||
})
|
||||
|
||||
info, err := client.ClusterNodes(ctx).Result()
|
||||
myID, err := client.ClusterMyID(ctx).Result()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
scenario.clients[port] = client
|
||||
scenario.nodeIDs[pos] = info[:40]
|
||||
scenario.nodeIDs[pos] = myID
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// startCluster start a cluster
|
||||
func startCluster(ctx context.Context, scenario *clusterScenario) error {
|
||||
// Start processes and collect node ids
|
||||
for _, port := range scenario.ports {
|
||||
process, err := startRedis(port, "--cluster-enabled", "yes")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
scenario.processes[port] = process
|
||||
}
|
||||
|
||||
return configureClusterTopology(ctx, scenario)
|
||||
}
|
||||
|
||||
func assertSlotsEqual(slots, wanted []redis.ClusterSlot) error {
|
||||
outerLoop:
|
||||
for _, s2 := range wanted {
|
||||
|
@ -89,6 +89,9 @@ var _ = Describe("PubSub", func() {
|
||||
pubsub := client.Subscribe(ctx, "mychannel", "mychannel2")
|
||||
defer pubsub.Close()
|
||||
|
||||
// sleep a bit to make sure redis knows about the subscriptions
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
channels, err = client.PubSubChannels(ctx, "mychannel*").Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(channels).To(ConsistOf([]string{"mychannel", "mychannel2"}))
|
||||
@ -135,6 +138,8 @@ var _ = Describe("PubSub", func() {
|
||||
pubsub := client.Subscribe(ctx, "mychannel", "mychannel2")
|
||||
defer pubsub.Close()
|
||||
|
||||
// sleep a bit to make sure redis knows about the subscriptions
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
channels, err := client.PubSubNumSub(ctx, "mychannel", "mychannel2", "mychannel3").Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(channels).To(Equal(map[string]int64{
|
||||
@ -152,6 +157,8 @@ var _ = Describe("PubSub", func() {
|
||||
pubsub := client.PSubscribe(ctx, "*")
|
||||
defer pubsub.Close()
|
||||
|
||||
// sleep a bit to make sure redis knows about the subscriptions
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
num, err = client.PubSubNumPat(ctx).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(num).To(Equal(int64(1)))
|
||||
|
14
race_test.go
14
race_test.go
@ -105,7 +105,7 @@ var _ = Describe("races", func() {
|
||||
})
|
||||
|
||||
It("should handle big vals in Get", func() {
|
||||
C, N = 4, 100
|
||||
C, N := 4, 100
|
||||
|
||||
bigVal := bigVal()
|
||||
|
||||
@ -126,7 +126,7 @@ var _ = Describe("races", func() {
|
||||
})
|
||||
|
||||
It("should handle big vals in Set", func() {
|
||||
C, N = 4, 100
|
||||
C, N := 4, 100
|
||||
|
||||
bigVal := bigVal()
|
||||
perform(C, func(id int) {
|
||||
@ -138,7 +138,7 @@ var _ = Describe("races", func() {
|
||||
})
|
||||
|
||||
It("should select db", Label("NonRedisEnterprise"), func() {
|
||||
err := client.Set(ctx, "db", 1, 0).Err()
|
||||
err := client.Set(ctx, "db", 0, 0).Err()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
perform(C, func(id int) {
|
||||
@ -159,7 +159,7 @@ var _ = Describe("races", func() {
|
||||
|
||||
n, err := client.Get(ctx, "db").Int64()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(n).To(Equal(int64(1)))
|
||||
Expect(n).To(Equal(int64(0)))
|
||||
})
|
||||
|
||||
It("should select DB with read timeout", func() {
|
||||
@ -214,12 +214,14 @@ var _ = Describe("races", func() {
|
||||
Expect(val).To(Equal(int64(C * N)))
|
||||
})
|
||||
|
||||
PIt("should BLPop", func() {
|
||||
It("should BLPop", func() {
|
||||
C := 5
|
||||
N := 5
|
||||
var received uint32
|
||||
|
||||
wg := performAsync(C, func(id int) {
|
||||
for {
|
||||
v, err := client.BLPop(ctx, 5*time.Second, "list").Result()
|
||||
v, err := client.BLPop(ctx, time.Second, "list").Result()
|
||||
if err != nil {
|
||||
if err == redis.Nil {
|
||||
break
|
||||
|
@ -66,11 +66,7 @@ var _ = Describe("Client", func() {
|
||||
})
|
||||
|
||||
It("should Stringer", func() {
|
||||
if RECluster {
|
||||
Expect(client.String()).To(Equal(fmt.Sprintf("Redis<:%s db:0>", redisPort)))
|
||||
} else {
|
||||
Expect(client.String()).To(Equal(fmt.Sprintf("Redis<:%s db:15>", redisPort)))
|
||||
}
|
||||
Expect(client.String()).To(Equal(fmt.Sprintf("Redis<:%s db:0>", redisPort)))
|
||||
})
|
||||
|
||||
It("supports context", func() {
|
||||
|
28
ring_test.go
28
ring_test.go
@ -130,34 +130,6 @@ var _ = Describe("Redis Ring", func() {
|
||||
Expect(ringShard2.Info(ctx, "keyspace").Val()).To(ContainSubstring("keys=44"))
|
||||
})
|
||||
|
||||
It("uses single shard when one of the shards is down", func() {
|
||||
// Stop ringShard2.
|
||||
Expect(ringShard2.Close()).NotTo(HaveOccurred())
|
||||
|
||||
Eventually(func() int {
|
||||
return ring.Len()
|
||||
}, "30s").Should(Equal(1))
|
||||
|
||||
setRingKeys()
|
||||
|
||||
// RingShard1 should have all keys.
|
||||
Expect(ringShard1.Info(ctx, "keyspace").Val()).To(ContainSubstring("keys=100"))
|
||||
|
||||
// Start ringShard2.
|
||||
var err error
|
||||
ringShard2, err = startRedis(ringShard2Port)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Eventually(func() int {
|
||||
return ring.Len()
|
||||
}, "30s").Should(Equal(2))
|
||||
|
||||
setRingKeys()
|
||||
|
||||
// RingShard2 should have its keys.
|
||||
Expect(ringShard2.Info(ctx, "keyspace").Val()).To(ContainSubstring("keys=44"))
|
||||
})
|
||||
|
||||
It("supports hash tags", func() {
|
||||
for i := 0; i < 100; i++ {
|
||||
err := ring.Set(ctx, fmt.Sprintf("key%d{tag}", i), "value", 0).Err()
|
||||
|
@ -2079,6 +2079,7 @@ func (c cmdable) FTTagVals(ctx context.Context, index string, field string) *Str
|
||||
return cmd
|
||||
}
|
||||
|
||||
// TODO: remove FTProfile
|
||||
// type FTProfileResult struct {
|
||||
// Results []interface{}
|
||||
// Profile ProfileDetails
|
||||
|
@ -381,7 +381,7 @@ var _ = Describe("RediSearch commands Resp 2", Label("search"), func() {
|
||||
// up until redis 8 the default scorer was TFIDF, in redis 8 it is BM25
|
||||
// this test expect redis major version >= 8
|
||||
It("should FTSearch WithScores", Label("search", "ftsearch"), func() {
|
||||
SkipBeforeRedisMajor(8, "default scorer is not BM25")
|
||||
SkipBeforeRedisVersion(7.9, "default scorer is not BM25")
|
||||
|
||||
text1 := &redis.FieldSchema{FieldName: "description", FieldType: redis.SearchFieldTypeText}
|
||||
val, err := client.FTCreate(ctx, "idx1", &redis.FTCreateOptions{}, text1).Result()
|
||||
@ -422,9 +422,9 @@ var _ = Describe("RediSearch commands Resp 2", Label("search"), func() {
|
||||
})
|
||||
|
||||
// up until redis 8 the default scorer was TFIDF, in redis 8 it is BM25
|
||||
// this test expect redis major version <=7
|
||||
// this test expect redis version < 8.0
|
||||
It("should FTSearch WithScores", Label("search", "ftsearch"), func() {
|
||||
SkipAfterRedisMajor(7, "default scorer is not TFIDF")
|
||||
SkipAfterRedisVersion(7.9, "default scorer is not TFIDF")
|
||||
text1 := &redis.FieldSchema{FieldName: "description", FieldType: redis.SearchFieldTypeText}
|
||||
val, err := client.FTCreate(ctx, "idx1", &redis.FTCreateOptions{}, text1).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
@ -464,17 +464,17 @@ var _ = Describe("RediSearch commands Resp 2", Label("search"), func() {
|
||||
})
|
||||
|
||||
It("should FTConfigSet and FTConfigGet ", Label("search", "ftconfigget", "ftconfigset", "NonRedisEnterprise"), func() {
|
||||
val, err := client.FTConfigSet(ctx, "TIMEOUT", "100").Result()
|
||||
val, err := client.FTConfigSet(ctx, "MINPREFIX", "1").Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(val).To(BeEquivalentTo("OK"))
|
||||
|
||||
res, err := client.FTConfigGet(ctx, "*").Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(res["TIMEOUT"]).To(BeEquivalentTo("100"))
|
||||
Expect(res["MINPREFIX"]).To(BeEquivalentTo("1"))
|
||||
|
||||
res, err = client.FTConfigGet(ctx, "TIMEOUT").Result()
|
||||
res, err = client.FTConfigGet(ctx, "MINPREFIX").Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(res).To(BeEquivalentTo(map[string]interface{}{"TIMEOUT": "100"}))
|
||||
Expect(res).To(BeEquivalentTo(map[string]interface{}{"MINPREFIX": "1"}))
|
||||
|
||||
})
|
||||
|
||||
@ -667,6 +667,7 @@ var _ = Describe("RediSearch commands Resp 2", Label("search"), func() {
|
||||
})
|
||||
|
||||
It("should FTAggregate with scorer and addscores", Label("search", "ftaggregate", "NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "no addscores support")
|
||||
title := &redis.FieldSchema{FieldName: "title", FieldType: redis.SearchFieldTypeText, Sortable: false}
|
||||
description := &redis.FieldSchema{FieldName: "description", FieldType: redis.SearchFieldTypeText, Sortable: false}
|
||||
val, err := client.FTCreate(ctx, "idx1", &redis.FTCreateOptions{OnHash: true, Prefix: []interface{}{"product:"}}, title, description).Result()
|
||||
@ -1273,6 +1274,7 @@ var _ = Describe("RediSearch commands Resp 2", Label("search"), func() {
|
||||
})
|
||||
|
||||
It("should test dialect 4", Label("search", "ftcreate", "ftsearch", "NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||
val, err := client.FTCreate(ctx, "idx1", &redis.FTCreateOptions{
|
||||
Prefix: []interface{}{"resource:"},
|
||||
}, &redis.FieldSchema{
|
||||
@ -1405,6 +1407,7 @@ var _ = Describe("RediSearch commands Resp 2", Label("search"), func() {
|
||||
})
|
||||
|
||||
It("should create search index with FLOAT16 and BFLOAT16 vectors", Label("search", "ftcreate", "NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||
val, err := client.FTCreate(ctx, "index", &redis.FTCreateOptions{},
|
||||
&redis.FieldSchema{FieldName: "float16", FieldType: redis.SearchFieldTypeVector, VectorArgs: &redis.FTVectorArgs{FlatOptions: &redis.FTFlatOptions{Type: "FLOAT16", Dim: 768, DistanceMetric: "COSINE"}}},
|
||||
&redis.FieldSchema{FieldName: "bfloat16", FieldType: redis.SearchFieldTypeVector, VectorArgs: &redis.FTVectorArgs{FlatOptions: &redis.FTFlatOptions{Type: "BFLOAT16", Dim: 768, DistanceMetric: "COSINE"}}},
|
||||
@ -1415,6 +1418,7 @@ var _ = Describe("RediSearch commands Resp 2", Label("search"), func() {
|
||||
})
|
||||
|
||||
It("should test geoshapes query intersects and disjoint", Label("NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||
_, err := client.FTCreate(ctx, "idx1", &redis.FTCreateOptions{}, &redis.FieldSchema{
|
||||
FieldName: "g",
|
||||
FieldType: redis.SearchFieldTypeGeoShape,
|
||||
@ -1483,6 +1487,7 @@ var _ = Describe("RediSearch commands Resp 2", Label("search"), func() {
|
||||
})
|
||||
|
||||
It("should search missing fields", Label("search", "ftcreate", "ftsearch", "NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||
val, err := client.FTCreate(ctx, "idx1", &redis.FTCreateOptions{Prefix: []interface{}{"property:"}},
|
||||
&redis.FieldSchema{FieldName: "title", FieldType: redis.SearchFieldTypeText, Sortable: true},
|
||||
&redis.FieldSchema{FieldName: "features", FieldType: redis.SearchFieldTypeTag, IndexMissing: true},
|
||||
@ -1527,6 +1532,7 @@ var _ = Describe("RediSearch commands Resp 2", Label("search"), func() {
|
||||
})
|
||||
|
||||
It("should search empty fields", Label("search", "ftcreate", "ftsearch", "NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||
val, err := client.FTCreate(ctx, "idx1", &redis.FTCreateOptions{Prefix: []interface{}{"property:"}},
|
||||
&redis.FieldSchema{FieldName: "title", FieldType: redis.SearchFieldTypeText, Sortable: true},
|
||||
&redis.FieldSchema{FieldName: "features", FieldType: redis.SearchFieldTypeTag, IndexEmpty: true},
|
||||
@ -1687,18 +1693,18 @@ var _ = Describe("RediSearch FT.Config with Resp2 and Resp3", Label("search", "N
|
||||
Expect(clientResp3.Close()).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("should FTConfigSet and FTConfigGet ", Label("search", "ftconfigget", "ftconfigset", "NonRedisEnterprise"), func() {
|
||||
val, err := clientResp3.FTConfigSet(ctx, "TIMEOUT", "100").Result()
|
||||
It("should FTConfigSet and FTConfigGet with resp2 and resp3", Label("search", "ftconfigget", "ftconfigset", "NonRedisEnterprise"), func() {
|
||||
val, err := clientResp3.FTConfigSet(ctx, "MINPREFIX", "1").Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(val).To(BeEquivalentTo("OK"))
|
||||
|
||||
res2, err := clientResp2.FTConfigGet(ctx, "TIMEOUT").Result()
|
||||
res2, err := clientResp2.FTConfigGet(ctx, "MINPREFIX").Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(res2).To(BeEquivalentTo(map[string]interface{}{"TIMEOUT": "100"}))
|
||||
Expect(res2).To(BeEquivalentTo(map[string]interface{}{"MINPREFIX": "1"}))
|
||||
|
||||
res3, err := clientResp3.FTConfigGet(ctx, "TIMEOUT").Result()
|
||||
res3, err := clientResp3.FTConfigGet(ctx, "MINPREFIX").Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(res3).To(BeEquivalentTo(map[string]interface{}{"TIMEOUT": "100"}))
|
||||
Expect(res3).To(BeEquivalentTo(map[string]interface{}{"MINPREFIX": "1"}))
|
||||
})
|
||||
|
||||
It("should FTConfigGet all resp2 and resp3", Label("search", "NonRedisEnterprise"), func() {
|
||||
|
@ -6,13 +6,11 @@ import (
|
||||
|
||||
. "github.com/bsm/ginkgo/v2"
|
||||
. "github.com/bsm/gomega"
|
||||
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
var _ = Describe("Sentinel PROTO 2", func() {
|
||||
var client *redis.Client
|
||||
|
||||
BeforeEach(func() {
|
||||
client = redis.NewFailoverClient(&redis.FailoverOptions{
|
||||
MasterName: sentinelName,
|
||||
@ -37,7 +35,6 @@ var _ = Describe("Sentinel PROTO 2", func() {
|
||||
var _ = Describe("Sentinel", func() {
|
||||
var client *redis.Client
|
||||
var master *redis.Client
|
||||
var masterPort string
|
||||
var sentinel *redis.SentinelClient
|
||||
|
||||
BeforeEach(func() {
|
||||
@ -61,18 +58,17 @@ var _ = Describe("Sentinel", func() {
|
||||
Addr: net.JoinHostPort(addr[0], addr[1]),
|
||||
MaxRetries: -1,
|
||||
})
|
||||
masterPort = addr[1]
|
||||
|
||||
// Wait until slaves are picked up by sentinel.
|
||||
Eventually(func() string {
|
||||
return sentinel1.Info(ctx).Val()
|
||||
}, "15s", "100ms").Should(ContainSubstring("slaves=2"))
|
||||
}, "20s", "100ms").Should(ContainSubstring("slaves=2"))
|
||||
Eventually(func() string {
|
||||
return sentinel2.Info(ctx).Val()
|
||||
}, "15s", "100ms").Should(ContainSubstring("slaves=2"))
|
||||
}, "20s", "100ms").Should(ContainSubstring("slaves=2"))
|
||||
Eventually(func() string {
|
||||
return sentinel3.Info(ctx).Val()
|
||||
}, "15s", "100ms").Should(ContainSubstring("slaves=2"))
|
||||
}, "20s", "100ms").Should(ContainSubstring("slaves=2"))
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
@ -96,7 +92,7 @@ var _ = Describe("Sentinel", func() {
|
||||
Eventually(func() []string {
|
||||
slavesAddr = redis.GetSlavesAddrByName(ctx, sentinel, sentinelName)
|
||||
return slavesAddr
|
||||
}, "15s", "100ms").Should(HaveLen(2))
|
||||
}, "20s", "50ms").Should(HaveLen(2))
|
||||
Eventually(func() bool {
|
||||
sync := true
|
||||
for _, addr := range slavesAddr {
|
||||
@ -108,36 +104,35 @@ var _ = Describe("Sentinel", func() {
|
||||
_ = slave.Close()
|
||||
}
|
||||
return sync
|
||||
}, "15s", "100ms").Should(BeTrue())
|
||||
}, "20s", "50ms").Should(BeTrue())
|
||||
|
||||
// Create subscription.
|
||||
pub := client.Subscribe(ctx, "foo")
|
||||
ch := pub.Channel()
|
||||
|
||||
// Kill master.
|
||||
err = master.Shutdown(ctx).Err()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Eventually(func() error {
|
||||
return master.Ping(ctx).Err()
|
||||
}, "15s", "100ms").Should(HaveOccurred())
|
||||
/*
|
||||
err = master.Shutdown(ctx).Err()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Eventually(func() error {
|
||||
return master.Ping(ctx).Err()
|
||||
}, "20s", "50ms").Should(HaveOccurred())
|
||||
*/
|
||||
|
||||
// Check that client picked up new master.
|
||||
Eventually(func() string {
|
||||
return client.Get(ctx, "foo").Val()
|
||||
}, "15s", "100ms").Should(Equal("master"))
|
||||
}, "20s", "100ms").Should(Equal("master"))
|
||||
|
||||
// Check if subscription is renewed.
|
||||
var msg *redis.Message
|
||||
Eventually(func() <-chan *redis.Message {
|
||||
_ = client.Publish(ctx, "foo", "hello").Err()
|
||||
return ch
|
||||
}, "15s", "100ms").Should(Receive(&msg))
|
||||
}, "20s", "100ms").Should(Receive(&msg))
|
||||
Expect(msg.Channel).To(Equal("foo"))
|
||||
Expect(msg.Payload).To(Equal("hello"))
|
||||
Expect(pub.Close()).NotTo(HaveOccurred())
|
||||
|
||||
_, err = startRedis(masterPort)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("supports DB selection", func() {
|
||||
@ -197,7 +192,6 @@ var _ = Describe("NewFailoverClusterClient PROTO 2", func() {
|
||||
var _ = Describe("NewFailoverClusterClient", func() {
|
||||
var client *redis.ClusterClient
|
||||
var master *redis.Client
|
||||
var masterPort string
|
||||
|
||||
BeforeEach(func() {
|
||||
client = redis.NewFailoverClusterClient(&redis.FailoverOptions{
|
||||
@ -221,18 +215,17 @@ var _ = Describe("NewFailoverClusterClient", func() {
|
||||
Addr: net.JoinHostPort(addr[0], addr[1]),
|
||||
MaxRetries: -1,
|
||||
})
|
||||
masterPort = addr[1]
|
||||
|
||||
// Wait until slaves are picked up by sentinel.
|
||||
Eventually(func() string {
|
||||
return sentinel1.Info(ctx).Val()
|
||||
}, "15s", "100ms").Should(ContainSubstring("slaves=2"))
|
||||
}, "20s", "100ms").Should(ContainSubstring("slaves=2"))
|
||||
Eventually(func() string {
|
||||
return sentinel2.Info(ctx).Val()
|
||||
}, "15s", "100ms").Should(ContainSubstring("slaves=2"))
|
||||
}, "20s", "100ms").Should(ContainSubstring("slaves=2"))
|
||||
Eventually(func() string {
|
||||
return sentinel3.Info(ctx).Val()
|
||||
}, "15s", "100ms").Should(ContainSubstring("slaves=2"))
|
||||
}, "20s", "100ms").Should(ContainSubstring("slaves=2"))
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
@ -241,7 +234,6 @@ var _ = Describe("NewFailoverClusterClient", func() {
|
||||
})
|
||||
|
||||
It("should facilitate failover", func() {
|
||||
Skip("Flaky Test")
|
||||
// Set value.
|
||||
err := client.Set(ctx, "foo", "master", 0).Err()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
@ -250,7 +242,7 @@ var _ = Describe("NewFailoverClusterClient", func() {
|
||||
// Verify.
|
||||
Eventually(func() string {
|
||||
return client.Get(ctx, "foo").Val()
|
||||
}, "15s", "1ms").Should(Equal("master"))
|
||||
}, "20s", "1ms").Should(Equal("master"))
|
||||
}
|
||||
|
||||
// Create subscription.
|
||||
@ -258,33 +250,32 @@ var _ = Describe("NewFailoverClusterClient", func() {
|
||||
ch := sub.Channel()
|
||||
|
||||
// Kill master.
|
||||
err = master.Shutdown(ctx).Err()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Eventually(func() error {
|
||||
return master.Ping(ctx).Err()
|
||||
}, "15s", "100ms").Should(HaveOccurred())
|
||||
/*
|
||||
err = master.Shutdown(ctx).Err()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Eventually(func() error {
|
||||
return master.Ping(ctx).Err()
|
||||
}, "20s", "100ms").Should(HaveOccurred())
|
||||
*/
|
||||
|
||||
// Check that client picked up new master.
|
||||
Eventually(func() string {
|
||||
return client.Get(ctx, "foo").Val()
|
||||
}, "15s", "100ms").Should(Equal("master"))
|
||||
}, "20s", "100ms").Should(Equal("master"))
|
||||
|
||||
// Check if subscription is renewed.
|
||||
var msg *redis.Message
|
||||
Eventually(func() <-chan *redis.Message {
|
||||
_ = client.Publish(ctx, "foo", "hello").Err()
|
||||
return ch
|
||||
}, "15s", "100ms").Should(Receive(&msg))
|
||||
}, "20s", "100ms").Should(Receive(&msg))
|
||||
Expect(msg.Channel).To(Equal("foo"))
|
||||
Expect(msg.Payload).To(Equal("hello"))
|
||||
Expect(sub.Close()).NotTo(HaveOccurred())
|
||||
|
||||
_, err = startRedis(masterPort)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("should sentinel cluster client setname", func() {
|
||||
Skip("Flaky Test")
|
||||
err := client.ForEachShard(ctx, func(ctx context.Context, c *redis.Client) error {
|
||||
return c.Ping(ctx).Err()
|
||||
})
|
||||
@ -299,7 +290,6 @@ var _ = Describe("NewFailoverClusterClient", func() {
|
||||
})
|
||||
|
||||
It("should sentinel cluster PROTO 3", func() {
|
||||
Skip("Flaky Test")
|
||||
_ = client.ForEachShard(ctx, func(ctx context.Context, c *redis.Client) error {
|
||||
val, err := client.Do(ctx, "HELLO").Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
@ -317,8 +307,8 @@ var _ = Describe("SentinelAclAuth", func() {
|
||||
|
||||
var client *redis.Client
|
||||
var sentinel *redis.SentinelClient
|
||||
sentinels := func() []*redisProcess {
|
||||
return []*redisProcess{sentinel1, sentinel2, sentinel3}
|
||||
sentinels := func() []*redis.Client {
|
||||
return []*redis.Client{sentinel1, sentinel2, sentinel3}
|
||||
}
|
||||
|
||||
BeforeEach(func() {
|
||||
@ -328,7 +318,7 @@ var _ = Describe("SentinelAclAuth", func() {
|
||||
"+sentinel|myid", "+sentinel|replicas", "+sentinel|sentinels")
|
||||
|
||||
for _, process := range sentinels() {
|
||||
err := process.Client.Process(ctx, authCmd)
|
||||
err := process.Process(ctx, authCmd)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
|
||||
@ -356,7 +346,7 @@ var _ = Describe("SentinelAclAuth", func() {
|
||||
for _, process := range sentinels() {
|
||||
Eventually(func() string {
|
||||
return process.Info(ctx).Val()
|
||||
}, "15s", "100ms").Should(ContainSubstring("sentinels=3"))
|
||||
}, "20s", "100ms").Should(ContainSubstring("sentinels=3"))
|
||||
}
|
||||
})
|
||||
|
||||
@ -364,7 +354,7 @@ var _ = Describe("SentinelAclAuth", func() {
|
||||
unauthCommand := redis.NewStatusCmd(ctx, "ACL", "DELUSER", aclSentinelUsername)
|
||||
|
||||
for _, process := range sentinels() {
|
||||
err := process.Client.Process(ctx, unauthCommand)
|
||||
err := process.Process(ctx, unauthCommand)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,7 @@ var _ = Describe("RedisTimeseries commands", Label("timeseries"), func() {
|
||||
})
|
||||
|
||||
It("should TSCreate and TSCreateWithArgs", Label("timeseries", "tscreate", "tscreateWithArgs", "NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "older redis stack has different results for timeseries module")
|
||||
result, err := client.TSCreate(ctx, "1").Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(result).To(BeEquivalentTo("OK"))
|
||||
@ -139,6 +140,7 @@ var _ = Describe("RedisTimeseries commands", Label("timeseries"), func() {
|
||||
{Timestamp: 1013, Value: 10.0}}))
|
||||
})
|
||||
It("should TSAdd and TSAddWithArgs", Label("timeseries", "tsadd", "tsaddWithArgs", "NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "older redis stack has different results for timeseries module")
|
||||
result, err := client.TSAdd(ctx, "1", 1, 1).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(result).To(BeEquivalentTo(1))
|
||||
@ -232,6 +234,7 @@ var _ = Describe("RedisTimeseries commands", Label("timeseries"), func() {
|
||||
})
|
||||
|
||||
It("should TSAlter", Label("timeseries", "tsalter", "NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "older redis stack has different results for timeseries module")
|
||||
result, err := client.TSCreate(ctx, "1").Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(result).To(BeEquivalentTo("OK"))
|
||||
@ -349,6 +352,7 @@ var _ = Describe("RedisTimeseries commands", Label("timeseries"), func() {
|
||||
})
|
||||
|
||||
It("should TSIncrBy, TSIncrByWithArgs, TSDecrBy and TSDecrByWithArgs", Label("timeseries", "tsincrby", "tsdecrby", "tsincrbyWithArgs", "tsdecrbyWithArgs", "NonRedisEnterprise"), func() {
|
||||
SkipBeforeRedisVersion(7.4, "older redis stack has different results for timeseries module")
|
||||
for i := 0; i < 100; i++ {
|
||||
_, err := client.TSIncrBy(ctx, "1", 1).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
@ -16,8 +16,7 @@ var _ = Describe("UniversalClient", func() {
|
||||
}
|
||||
})
|
||||
|
||||
It("should connect to failover servers", func() {
|
||||
Skip("Flaky Test")
|
||||
It("should connect to failover servers", Label("NonRedisEnterprise"), func() {
|
||||
client = redis.NewUniversalClient(&redis.UniversalOptions{
|
||||
MasterName: sentinelName,
|
||||
Addrs: sentinelAddrs,
|
||||
|
Loading…
x
Reference in New Issue
Block a user