mirror of
https://github.com/redis/go-redis.git
synced 2025-04-17 20:17:02 +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 }}"
|
CLIENT_LIBS_TEST_IMAGE: "redislabs/client-libs-test:${{ inputs.redis-version }}"
|
||||||
run: |
|
run: |
|
||||||
set -e
|
set -e
|
||||||
redis_major_version=$(echo "$REDIS_VERSION" | grep -oP '^\d+')
|
redis_version_np=$(echo "$REDIS_VERSION" | grep -oP '^\d+.\d+')
|
||||||
if (( redis_major_version < 8 )); then
|
|
||||||
echo "Using redis-stack for module tests"
|
|
||||||
else
|
|
||||||
echo "Using redis CE for module tests"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Mapping of redis version to redis testing containers
|
# Mapping of redis version to redis testing containers
|
||||||
declare -A redis_version_mapping=(
|
declare -A redis_version_mapping=(
|
||||||
@ -36,27 +31,23 @@ runs:
|
|||||||
)
|
)
|
||||||
|
|
||||||
if [[ -v redis_version_mapping[$REDIS_VERSION] ]]; then
|
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 "REDIS_IMAGE=redis:${{ inputs.redis-version }}" >> $GITHUB_ENV
|
||||||
echo "CLIENT_LIBS_TEST_IMAGE=redislabs/client-libs-test:${redis_version_mapping[$REDIS_VERSION]}" >> $GITHUB_ENV
|
echo "CLIENT_LIBS_TEST_IMAGE=redislabs/client-libs-test:${redis_version_mapping[$REDIS_VERSION]}" >> $GITHUB_ENV
|
||||||
else
|
else
|
||||||
echo "Version not found in the mapping."
|
echo "Version not found in the mapping."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
sleep 10 # time to settle
|
sleep 10 # wait for redis to start
|
||||||
shell: bash
|
shell: bash
|
||||||
- name: Set up Docker Compose environment with redis ${{ inputs.redis-version }}
|
- name: Set up Docker Compose environment with redis ${{ inputs.redis-version }}
|
||||||
run: docker compose --profile all up -d
|
run: |
|
||||||
|
make docker.start
|
||||||
shell: bash
|
shell: bash
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
env:
|
env:
|
||||||
RCE_DOCKER: "true"
|
RCE_DOCKER: "true"
|
||||||
RE_CLUSTER: "false"
|
RE_CLUSTER: "false"
|
||||||
run: |
|
run: |
|
||||||
go test \
|
make test.ci
|
||||||
--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"
|
|
||||||
shell: bash
|
shell: bash
|
||||||
|
58
.github/workflows/build.yml
vendored
58
.github/workflows/build.yml
vendored
@ -10,13 +10,19 @@ permissions:
|
|||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
|
||||||
name: build
|
benchmark:
|
||||||
|
name: benchmark
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
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:
|
steps:
|
||||||
- name: Set up ${{ matrix.go-version }}
|
- name: Set up ${{ matrix.go-version }}
|
||||||
@ -27,14 +33,37 @@ jobs:
|
|||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Test
|
- name: Setup Test environment
|
||||||
run: make test
|
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+')
|
||||||
|
|
||||||
- name: Upload to Codecov
|
# Mapping of redis version to redis testing containers
|
||||||
uses: codecov/codecov-action@v5
|
declare -A redis_version_mapping=(
|
||||||
with:
|
["8.0-M03"]="8.0-M04-pre"
|
||||||
files: coverage.txt
|
["7.4.2"]="rs-7.4.0-v2"
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
)
|
||||||
|
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
|
||||||
|
|
||||||
test-redis-ce:
|
test-redis-ce:
|
||||||
name: test-redis-ce
|
name: test-redis-ce
|
||||||
@ -47,11 +76,10 @@ jobs:
|
|||||||
- "7.4.2" # should use redis stack 7.4
|
- "7.4.2" # should use redis stack 7.4
|
||||||
- "7.2.7" # should redis stack 7.2
|
- "7.2.7" # should redis stack 7.2
|
||||||
go-version:
|
go-version:
|
||||||
- "1.22.x"
|
|
||||||
- "1.23.x"
|
- "1.23.x"
|
||||||
|
- "1.24.x"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
@ -61,3 +89,9 @@ jobs:
|
|||||||
go-version: ${{matrix.go-version}}
|
go-version: ${{matrix.go-version}}
|
||||||
redis-version: ${{ matrix.redis-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:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
go-version: [ "1.21", "1.22", "1.23" ]
|
go-version: ["1.24"]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Set up ${{ matrix.go-version }}
|
- name: Set up ${{ matrix.go-version }}
|
||||||
@ -38,4 +38,4 @@ jobs:
|
|||||||
|
|
||||||
- name: Test doc examples
|
- name: Test doc examples
|
||||||
working-directory: ./doctests
|
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:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
go-version: [1.23.x]
|
go-version: [1.24.x]
|
||||||
re-build: ["7.4.2-54"]
|
re-build: ["7.4.2-54"]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@ -47,7 +47,7 @@ jobs:
|
|||||||
- name: Test
|
- name: Test
|
||||||
env:
|
env:
|
||||||
RE_CLUSTER: true
|
RE_CLUSTER: true
|
||||||
REDIS_MAJOR_VERSION: 7
|
REDIS_VERSION: "7.4"
|
||||||
run: |
|
run: |
|
||||||
go test \
|
go test \
|
||||||
--ginkgo.skip-file="ring_test.go" \
|
--ginkgo.skip-file="ring_test.go" \
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -5,4 +5,6 @@ testdata/*
|
|||||||
*.tar.gz
|
*.tar.gz
|
||||||
*.dic
|
*.dic
|
||||||
redis8tests.sh
|
redis8tests.sh
|
||||||
|
coverage.txt
|
||||||
|
**/coverage.txt
|
||||||
.vscode
|
.vscode
|
@ -32,20 +32,33 @@ Here's how to get started with your code contribution:
|
|||||||
|
|
||||||
1. Create your own fork of go-redis
|
1. Create your own fork of go-redis
|
||||||
2. Do the changes in your fork
|
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:
|
3. If you need a development environment, run `make docker.start`.
|
||||||
```docker run -p 6379:6379 -it redis/redis-stack-server:edge```
|
|
||||||
4. While developing, make sure the tests pass by running `make tests`
|
> 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
|
5. If you like the change and think the project could use it, send a
|
||||||
pull request
|
pull request
|
||||||
|
|
||||||
To see what else is part of the automation, run `invoke -l`
|
To see what else is part of the automation, run `invoke -l`
|
||||||
|
|
||||||
|
|
||||||
## Testing
|
## 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
|
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
|
changes against all the go versions supported, as declared by the
|
||||||
[build.yml](./.github/workflows/build.yml) file.
|
[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)
|
GO_MOD_DIRS := $(shell find . -type f -name 'go.mod' -exec dirname {} \; | sort)
|
||||||
export REDIS_MAJOR_VERSION := 7
|
|
||||||
|
|
||||||
test: testdeps
|
docker.start:
|
||||||
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
|
docker compose --profile all up -d --quiet-pull
|
||||||
$(eval GO_VERSION := $(shell go version | cut -d " " -f 3 | cut -d. -f2))
|
|
||||||
|
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 \
|
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}"; \
|
echo "go test in $${dir}"; \
|
||||||
(cd "$${dir}" && \
|
(cd "$${dir}" && \
|
||||||
go mod tidy -compat=1.18 && \
|
go mod tidy -compat=1.18 && \
|
||||||
go test && \
|
go vet && \
|
||||||
go test ./... -short -race && \
|
go test -coverprofile=coverage.txt -covermode=atomic ./... -race); \
|
||||||
go test ./... -run=NONE -bench=. -benchmem && \
|
|
||||||
env GOOS=linux GOARCH=386 go test && \
|
|
||||||
go test -coverprofile=coverage.txt -covermode=atomic ./... && \
|
|
||||||
go vet); \
|
|
||||||
done
|
done
|
||||||
cd internal/customvet && go build .
|
cd internal/customvet && go build .
|
||||||
go vet -vettool ./internal/customvet/customvet
|
go vet -vettool ./internal/customvet/customvet
|
||||||
docker stop go-redis-redis-stack
|
|
||||||
|
|
||||||
testdeps: testdata/redis/src/redis-server
|
bench:
|
||||||
|
|
||||||
bench: testdeps
|
|
||||||
go test ./... -test.run=NONE -test.bench=. -test.benchmem
|
go test ./... -test.run=NONE -test.bench=. -test.benchmem
|
||||||
|
|
||||||
.PHONY: all test testdeps bench fmt
|
.PHONY: all test bench fmt
|
||||||
|
|
||||||
build:
|
build:
|
||||||
go 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:
|
fmt:
|
||||||
gofumpt -w ./
|
gofumpt -w ./
|
||||||
goimports -w -local github.com/redis/go-redis ./
|
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
|
> See [OpenTelemetry](https://github.com/redis/go-redis/tree/master/example/otel) example which
|
||||||
> demonstrates how you can use Uptrace to monitor go-redis.
|
> 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?
|
## How do I Redis?
|
||||||
|
|
||||||
[Learn for free at Redis University](https://university.redis.com/)
|
[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() {
|
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())
|
Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred())
|
||||||
val, err := client.FTCreate(ctx, "txt", &redis.FTCreateOptions{}, &redis.FieldSchema{FieldName: "txt", FieldType: redis.SearchFieldTypeText}).Result()
|
val, err := client.FTCreate(ctx, "txt", &redis.FTCreateOptions{}, &redis.FieldSchema{FieldName: "txt", FieldType: redis.SearchFieldTypeText}).Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
@ -322,7 +322,7 @@ var _ = Describe("ACL permissions", Label("NonRedisEnterprise"), func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("set permissions for module categories", 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())
|
Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred())
|
||||||
val, err := client.FTCreate(ctx, "txt", &redis.FTCreateOptions{}, &redis.FieldSchema{FieldName: "txt", FieldType: redis.SearchFieldTypeText}).Result()
|
val, err := client.FTCreate(ctx, "txt", &redis.FTCreateOptions{}, &redis.FieldSchema{FieldName: "txt", FieldType: redis.SearchFieldTypeText}).Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
@ -419,7 +419,7 @@ var _ = Describe("ACL Categories", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("lists acl categories and subcategories with Modules", 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{
|
aclTestCase := map[string]string{
|
||||||
"search": "FT.CREATE",
|
"search": "FT.CREATE",
|
||||||
"bloom": "bf.add",
|
"bloom": "bf.add",
|
||||||
|
105
bench_test.go
105
bench_test.go
@ -277,37 +277,41 @@ func BenchmarkXRead(b *testing.B) {
|
|||||||
|
|
||||||
func newClusterScenario() *clusterScenario {
|
func newClusterScenario() *clusterScenario {
|
||||||
return &clusterScenario{
|
return &clusterScenario{
|
||||||
ports: []string{"16600", "16601", "16602", "16603", "16604", "16605"},
|
ports: []string{"16600", "16601", "16602", "16603", "16604", "16605"},
|
||||||
nodeIDs: make([]string, 6),
|
nodeIDs: make([]string, 6),
|
||||||
processes: make(map[string]*redisProcess, 6),
|
clients: make(map[string]*redis.Client, 6),
|
||||||
clients: make(map[string]*redis.Client, 6),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var clusterBench *clusterScenario
|
||||||
|
|
||||||
func BenchmarkClusterPing(b *testing.B) {
|
func BenchmarkClusterPing(b *testing.B) {
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
b.Skip("skipping in short mode")
|
b.Skip("skipping in short mode")
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
cluster := newClusterScenario()
|
if clusterBench == nil {
|
||||||
if err := startCluster(ctx, cluster); err != nil {
|
clusterBench = newClusterScenario()
|
||||||
b.Fatal(err)
|
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()
|
defer client.Close()
|
||||||
|
|
||||||
b.ResetTimer()
|
b.Run("cluster ping", func(b *testing.B) {
|
||||||
|
b.ResetTimer()
|
||||||
|
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
for pb.Next() {
|
for pb.Next() {
|
||||||
err := client.Ping(ctx).Err()
|
err := client.Ping(ctx).Err()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,23 +321,26 @@ func BenchmarkClusterDoInt(b *testing.B) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
cluster := newClusterScenario()
|
if clusterBench == nil {
|
||||||
if err := startCluster(ctx, cluster); err != nil {
|
clusterBench = newClusterScenario()
|
||||||
b.Fatal(err)
|
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()
|
defer client.Close()
|
||||||
|
|
||||||
b.ResetTimer()
|
b.Run("cluster do set int", func(b *testing.B) {
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
b.ResetTimer()
|
||||||
for pb.Next() {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
err := client.Do(ctx, "SET", 10, 10).Err()
|
for pb.Next() {
|
||||||
if err != nil {
|
err := client.Do(ctx, "SET", 10, 10).Err()
|
||||||
b.Fatal(err)
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,26 +350,29 @@ func BenchmarkClusterSetString(b *testing.B) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
cluster := newClusterScenario()
|
if clusterBench == nil {
|
||||||
if err := startCluster(ctx, cluster); err != nil {
|
clusterBench = newClusterScenario()
|
||||||
b.Fatal(err)
|
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()
|
defer client.Close()
|
||||||
|
|
||||||
value := string(bytes.Repeat([]byte{'1'}, 10000))
|
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) {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
for pb.Next() {
|
for pb.Next() {
|
||||||
err := client.Set(ctx, "key", value, 0).Err()
|
err := client.Set(ctx, "key", value, 0).Err()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,21 +382,6 @@ func BenchmarkExecRingSetAddrsCmd(b *testing.B) {
|
|||||||
ringShard2Name = "ringShardTwo"
|
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{
|
ring := redis.NewRing(&redis.RingOptions{
|
||||||
Addrs: map[string]string{
|
Addrs: map[string]string{
|
||||||
"ringShardOne": ":" + ringShard1Port,
|
"ringShardOne": ":" + ringShard1Port,
|
||||||
|
@ -4,6 +4,7 @@ import "context"
|
|||||||
|
|
||||||
type ClusterCmdable interface {
|
type ClusterCmdable interface {
|
||||||
ClusterMyShardID(ctx context.Context) *StringCmd
|
ClusterMyShardID(ctx context.Context) *StringCmd
|
||||||
|
ClusterMyID(ctx context.Context) *StringCmd
|
||||||
ClusterSlots(ctx context.Context) *ClusterSlotsCmd
|
ClusterSlots(ctx context.Context) *ClusterSlotsCmd
|
||||||
ClusterShards(ctx context.Context) *ClusterShardsCmd
|
ClusterShards(ctx context.Context) *ClusterShardsCmd
|
||||||
ClusterLinks(ctx context.Context) *ClusterLinksCmd
|
ClusterLinks(ctx context.Context) *ClusterLinksCmd
|
||||||
@ -35,6 +36,12 @@ func (c cmdable) ClusterMyShardID(ctx context.Context) *StringCmd {
|
|||||||
return cmd
|
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 {
|
func (c cmdable) ClusterSlots(ctx context.Context) *ClusterSlotsCmd {
|
||||||
cmd := NewClusterSlotsCmd(ctx, "cluster", "slots")
|
cmd := NewClusterSlotsCmd(ctx, "cluster", "slots")
|
||||||
_ = c(ctx, cmd)
|
_ = c(ctx, cmd)
|
||||||
|
@ -194,6 +194,7 @@ var _ = Describe("Commands", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should ClientKillByFilter with MAXAGE", Label("NonRedisEnterprise"), func() {
|
It("should ClientKillByFilter with MAXAGE", Label("NonRedisEnterprise"), func() {
|
||||||
|
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||||
var s []string
|
var s []string
|
||||||
started := make(chan bool)
|
started := make(chan bool)
|
||||||
done := make(chan bool)
|
done := make(chan bool)
|
||||||
@ -211,18 +212,18 @@ var _ = Describe("Commands", func() {
|
|||||||
select {
|
select {
|
||||||
case <-done:
|
case <-done:
|
||||||
Fail("BLPOP is not blocked.")
|
Fail("BLPOP is not blocked.")
|
||||||
case <-time.After(1 * time.Second):
|
case <-time.After(1100 * time.Millisecond):
|
||||||
// ok
|
// ok
|
||||||
}
|
}
|
||||||
|
|
||||||
killed := client.ClientKillByFilter(ctx, "MAXAGE", "1")
|
killed := client.ClientKillByFilter(ctx, "MAXAGE", "1")
|
||||||
Expect(killed.Err()).NotTo(HaveOccurred())
|
Expect(killed.Err()).NotTo(HaveOccurred())
|
||||||
Expect(killed.Val()).To(BeNumerically(">=", 2))
|
Expect(killed.Val()).To(BeNumerically(">=", 1))
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-done:
|
case <-done:
|
||||||
// ok
|
// ok
|
||||||
case <-time.After(time.Second):
|
case <-time.After(200 * time.Millisecond):
|
||||||
Fail("BLPOP is still blocked.")
|
Fail("BLPOP is still blocked.")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -345,7 +346,7 @@ var _ = Describe("Commands", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should ConfigGet Modules", 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{
|
expected := map[string]string{
|
||||||
"search-*": "search-timeout",
|
"search-*": "search-timeout",
|
||||||
"ts-*": "ts-retention-policy",
|
"ts-*": "ts-retention-policy",
|
||||||
@ -380,7 +381,7 @@ var _ = Describe("Commands", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should ConfigGet with Modules", Label("NonRedisEnterprise"), 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, "*")
|
configGet := client.ConfigGet(ctx, "*")
|
||||||
Expect(configGet.Err()).NotTo(HaveOccurred())
|
Expect(configGet.Err()).NotTo(HaveOccurred())
|
||||||
Expect(configGet.Val()).To(HaveKey("maxmemory"))
|
Expect(configGet.Val()).To(HaveKey("maxmemory"))
|
||||||
@ -391,7 +392,7 @@ var _ = Describe("Commands", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should ConfigSet FT DIALECT", 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()
|
defaultState, err := client.ConfigGet(ctx, "search-default-dialect").Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
@ -437,13 +438,13 @@ var _ = Describe("Commands", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should ConfigSet fail for ReadOnly", 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()
|
_, err := client.ConfigSet(ctx, "search-max-doctablesize", "100000").Result()
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).To(HaveOccurred())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should ConfigSet Modules", func() {
|
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{}
|
defaults := map[string]string{}
|
||||||
expected := map[string]string{
|
expected := map[string]string{
|
||||||
"search-timeout": "100",
|
"search-timeout": "100",
|
||||||
@ -484,7 +485,7 @@ var _ = Describe("Commands", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should Fail ConfigSet Modules", 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{
|
expected := map[string]string{
|
||||||
"search-timeout": "-100",
|
"search-timeout": "-100",
|
||||||
"ts-retention-policy": "-10",
|
"ts-retention-policy": "-10",
|
||||||
@ -533,7 +534,7 @@ var _ = Describe("Commands", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should Info Modules", Label("redis.info"), 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)
|
info := client.Info(ctx)
|
||||||
Expect(info.Err()).NotTo(HaveOccurred())
|
Expect(info.Err()).NotTo(HaveOccurred())
|
||||||
Expect(info.Val()).NotTo(BeNil())
|
Expect(info.Val()).NotTo(BeNil())
|
||||||
@ -558,7 +559,7 @@ var _ = Describe("Commands", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should InfoMap Modules", Label("redis.info"), 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)
|
info := client.InfoMap(ctx)
|
||||||
Expect(info.Err()).NotTo(HaveOccurred())
|
Expect(info.Err()).NotTo(HaveOccurred())
|
||||||
Expect(info.Val()).NotTo(BeNil())
|
Expect(info.Val()).NotTo(BeNil())
|
||||||
@ -701,8 +702,8 @@ var _ = Describe("Commands", func() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("debugging", func() {
|
Describe("debugging", Label("NonRedisEnterprise"), func() {
|
||||||
PIt("should DebugObject", func() {
|
It("should DebugObject", func() {
|
||||||
err := client.DebugObject(ctx, "foo").Err()
|
err := client.DebugObject(ctx, "foo").Err()
|
||||||
Expect(err).To(MatchError("ERR no such key"))
|
Expect(err).To(MatchError("ERR no such key"))
|
||||||
|
|
||||||
@ -1332,6 +1333,7 @@ var _ = Describe("Commands", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should HScan without values", Label("NonRedisEnterprise"), 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++ {
|
for i := 0; i < 1000; i++ {
|
||||||
sadd := client.HSet(ctx, "myhash", fmt.Sprintf("key%d", i), "hello")
|
sadd := client.HSet(ctx, "myhash", fmt.Sprintf("key%d", i), "hello")
|
||||||
Expect(sadd.Err()).NotTo(HaveOccurred())
|
Expect(sadd.Err()).NotTo(HaveOccurred())
|
||||||
@ -2625,6 +2627,7 @@ var _ = Describe("Commands", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should HExpire", Label("hash-expiration", "NonRedisEnterprise"), 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()
|
res, err := client.HExpire(ctx, "no_such_key", 10*time.Second, "field1", "field2", "field3").Result()
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(res).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
Expect(res).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
||||||
@ -2640,6 +2643,7 @@ var _ = Describe("Commands", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should HPExpire", Label("hash-expiration", "NonRedisEnterprise"), 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()
|
res, err := client.HPExpire(ctx, "no_such_key", 10*time.Second, "field1", "field2", "field3").Result()
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(res).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
Expect(res).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
||||||
@ -2655,6 +2659,7 @@ var _ = Describe("Commands", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should HExpireAt", Label("hash-expiration", "NonRedisEnterprise"), 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()
|
resEmpty, err := client.HExpireAt(ctx, "no_such_key", time.Now().Add(10*time.Second), "field1", "field2", "field3").Result()
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(resEmpty).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
Expect(resEmpty).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
||||||
@ -2670,6 +2675,7 @@ var _ = Describe("Commands", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should HPExpireAt", Label("hash-expiration", "NonRedisEnterprise"), 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()
|
resEmpty, err := client.HPExpireAt(ctx, "no_such_key", time.Now().Add(10*time.Second), "field1", "field2", "field3").Result()
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(resEmpty).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
Expect(resEmpty).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
||||||
@ -2685,6 +2691,7 @@ var _ = Describe("Commands", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should HPersist", Label("hash-expiration", "NonRedisEnterprise"), 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()
|
resEmpty, err := client.HPersist(ctx, "no_such_key", "field1", "field2", "field3").Result()
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(resEmpty).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
Expect(resEmpty).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
||||||
@ -2708,6 +2715,7 @@ var _ = Describe("Commands", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should HExpireTime", Label("hash-expiration", "NonRedisEnterprise"), 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()
|
resEmpty, err := client.HExpireTime(ctx, "no_such_key", "field1", "field2", "field3").Result()
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(resEmpty).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
Expect(resEmpty).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
||||||
@ -2727,6 +2735,7 @@ var _ = Describe("Commands", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should HPExpireTime", Label("hash-expiration", "NonRedisEnterprise"), 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()
|
resEmpty, err := client.HPExpireTime(ctx, "no_such_key", "field1", "field2", "field3").Result()
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(resEmpty).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
Expect(resEmpty).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
||||||
@ -2747,6 +2756,7 @@ var _ = Describe("Commands", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should HTTL", Label("hash-expiration", "NonRedisEnterprise"), 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()
|
resEmpty, err := client.HTTL(ctx, "no_such_key", "field1", "field2", "field3").Result()
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(resEmpty).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
Expect(resEmpty).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
||||||
@ -2766,6 +2776,7 @@ var _ = Describe("Commands", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should HPTTL", Label("hash-expiration", "NonRedisEnterprise"), 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()
|
resEmpty, err := client.HPTTL(ctx, "no_such_key", "field1", "field2", "field3").Result()
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(resEmpty).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
Expect(resEmpty).To(BeEquivalentTo([]int64{-2, -2, -2}))
|
||||||
@ -6040,6 +6051,7 @@ var _ = Describe("Commands", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should XRead LastEntry", Label("NonRedisEnterprise"), 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{
|
res, err := client.XRead(ctx, &redis.XReadArgs{
|
||||||
Streams: []string{"stream"},
|
Streams: []string{"stream"},
|
||||||
Count: 2, // we expect 1 message
|
Count: 2, // we expect 1 message
|
||||||
@ -6057,6 +6069,7 @@ var _ = Describe("Commands", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should XRead LastEntry from two streams", Label("NonRedisEnterprise"), 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{
|
res, err := client.XRead(ctx, &redis.XReadArgs{
|
||||||
Streams: []string{"stream", "stream"},
|
Streams: []string{"stream", "stream"},
|
||||||
ID: "+",
|
ID: "+",
|
||||||
@ -6079,6 +6092,7 @@ var _ = Describe("Commands", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should XRead LastEntry blocks", Label("NonRedisEnterprise"), func() {
|
It("should XRead LastEntry blocks", Label("NonRedisEnterprise"), func() {
|
||||||
|
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
go func() {
|
go func() {
|
||||||
defer GinkgoRecover()
|
defer GinkgoRecover()
|
||||||
@ -6614,14 +6628,12 @@ var _ = Describe("Commands", func() {
|
|||||||
|
|
||||||
res, err := client.ZRangeWithScores(ctx, "result", 0, -1).Result()
|
res, err := client.ZRangeWithScores(ctx, "result", 0, -1).Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(res).To(ContainElement(redis.Z{
|
Expect(len(res)).To(Equal(2))
|
||||||
Score: 190.44242984775784,
|
var palermo, catania redis.Z
|
||||||
Member: "Palermo",
|
Expect(res).To(ContainElement(HaveField("Member", "Palermo"), &palermo))
|
||||||
}))
|
Expect(res).To(ContainElement(HaveField("Member", "Catania"), &catania))
|
||||||
Expect(res).To(ContainElement(redis.Z{
|
Expect(palermo.Score).To(BeNumerically("~", 190, 1))
|
||||||
Score: 56.4412578701582,
|
Expect(catania.Score).To(BeNumerically("~", 56, 1))
|
||||||
Member: "Catania",
|
|
||||||
}))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should search geo radius with options", func() {
|
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()
|
v, err := client.ZRangeWithScores(ctx, "key2", 0, -1).Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(v).To(Equal([]redis.Z{
|
|
||||||
{
|
Expect(len(v)).To(Equal(2))
|
||||||
Score: 56.441257870158204,
|
var palermo, catania redis.Z
|
||||||
Member: "Catania",
|
Expect(v).To(ContainElement(HaveField("Member", "Palermo"), &palermo))
|
||||||
},
|
Expect(v).To(ContainElement(HaveField("Member", "Catania"), &catania))
|
||||||
{
|
Expect(palermo.Score).To(BeNumerically("~", 190, 1))
|
||||||
Score: 190.44242984775784,
|
Expect(catania.Score).To(BeNumerically("~", 56, 1))
|
||||||
Member: "Palermo",
|
|
||||||
},
|
|
||||||
}))
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -7332,6 +7341,7 @@ var _ = Describe("Commands", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("Shows function stats", func() {
|
It("Shows function stats", func() {
|
||||||
|
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||||
defer client.FunctionKill(ctx)
|
defer client.FunctionKill(ctx)
|
||||||
|
|
||||||
// We can not run blocking commands in Redis functions, so we're using an infinite loop,
|
// We can not run blocking commands in Redis functions, so we're using an infinite loop,
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
redis:
|
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
|
container_name: redis-standalone
|
||||||
environment:
|
environment:
|
||||||
- TLS_ENABLED=yes
|
- TLS_ENABLED=yes
|
||||||
@ -21,9 +21,9 @@ services:
|
|||||||
- all-stack
|
- all-stack
|
||||||
- all
|
- all
|
||||||
|
|
||||||
cluster:
|
osscluster:
|
||||||
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-cluster
|
container_name: redis-osscluster
|
||||||
environment:
|
environment:
|
||||||
- NODES=6
|
- NODES=6
|
||||||
- PORT=16600
|
- PORT=16600
|
||||||
@ -31,110 +31,71 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "16600-16605:16600-16605"
|
- "16600-16605:16600-16605"
|
||||||
volumes:
|
volumes:
|
||||||
- "./dockers/cluster:/redis/work"
|
- "./dockers/osscluster:/redis/work"
|
||||||
profiles:
|
profiles:
|
||||||
- cluster
|
- cluster
|
||||||
- all-stack
|
- all-stack
|
||||||
- all
|
- 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:
|
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
|
container_name: redis-sentinel
|
||||||
depends_on:
|
depends_on:
|
||||||
- redis
|
- sentinel-cluster
|
||||||
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
|
|
||||||
environment:
|
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
|
- TLS_ENABLED=yes
|
||||||
- REDIS_CLUSTER=no
|
- REDIS_CLUSTER=no
|
||||||
- PORT=6390
|
- PORT=6390
|
||||||
command: ${REDIS_EXTRA_ARGS:---enable-debug-command yes --enable-module-command yes --tls-auth-clients optional --save ""}
|
command: ${REDIS_EXTRA_ARGS:---enable-debug-command yes --enable-module-command yes --tls-auth-clients optional --save ""}
|
||||||
ports:
|
ports:
|
||||||
- 6390:6390
|
- 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
|
- 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
|
- 6392:6392
|
||||||
volumes:
|
volumes:
|
||||||
- "./dockers/ring3:/redis/work"
|
- "./dockers/ring:/redis/work"
|
||||||
profiles:
|
profiles:
|
||||||
- ring
|
- ring
|
||||||
- cluster
|
- cluster
|
||||||
- sentinel
|
|
||||||
- all-stack
|
- 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 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 down-after-milliseconds go-redis-test 5000
|
||||||
sentinel failover-timeout go-redis-test 60000
|
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
|
// REMOVE_START
|
||||||
|
// make sure we are working with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:models")
|
rdb.Del(ctx, "bikes:models")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@ func ExampleClient_bf() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// make sure we are working with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bike:1:stats")
|
rdb.Del(ctx, "bike:1:stats")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@ func ExampleClient_ping() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// make sure we are working with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "pings:2024-01-01-00:00")
|
rdb.Del(ctx, "pings:2024-01-01-00:00")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -66,6 +68,8 @@ func ExampleClient_bitcount() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
_, err := rdb.SetBit(ctx, "pings:2024-01-01-00:00", 123, 1).Result()
|
_, err := rdb.SetBit(ctx, "pings:2024-01-01-00:00", 123, 1).Result()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -23,6 +23,8 @@ func ExampleClient_del_cmd() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// make sure we are working with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "key1", "key2", "key3")
|
rdb.Del(ctx, "key1", "key2", "key3")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -68,6 +70,8 @@ func ExampleClient_expire_cmd() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "mykey")
|
rdb.Del(ctx, "mykey")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -167,6 +171,8 @@ func ExampleClient_ttl_cmd() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "mykey")
|
rdb.Del(ctx, "mykey")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
|
@ -22,6 +22,8 @@ func ExampleClient_hset() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// make sure we are working with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "myhash")
|
rdb.Del(ctx, "myhash")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -112,6 +114,8 @@ func ExampleClient_hget() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "myhash")
|
rdb.Del(ctx, "myhash")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -157,6 +161,8 @@ func ExampleClient_hgetall() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "myhash")
|
rdb.Del(ctx, "myhash")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -209,6 +215,8 @@ func ExampleClient_hvals() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "myhash")
|
rdb.Del(ctx, "myhash")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
|
@ -22,6 +22,8 @@ func ExampleClient_cmd_flushall() {
|
|||||||
|
|
||||||
// STEP_START flushall
|
// STEP_START flushall
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// make sure we are working with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Set(ctx, "testkey1", "1", 0)
|
rdb.Set(ctx, "testkey1", "1", 0)
|
||||||
rdb.Set(ctx, "testkey2", "2", 0)
|
rdb.Set(ctx, "testkey2", "2", 0)
|
||||||
rdb.Set(ctx, "testkey3", "3", 0)
|
rdb.Set(ctx, "testkey3", "3", 0)
|
||||||
|
@ -21,6 +21,8 @@ func ExampleClient_zadd_cmd() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// make sure we are working with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "myzset")
|
rdb.Del(ctx, "myzset")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -82,6 +84,8 @@ func ExampleClient_zrange1() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "myzset")
|
rdb.Del(ctx, "myzset")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -140,6 +144,8 @@ func ExampleClient_zrange2() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "myzset")
|
rdb.Del(ctx, "myzset")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -180,6 +186,8 @@ func ExampleClient_zrange3() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "myzset")
|
rdb.Del(ctx, "myzset")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@ func ExampleClient_cmd_incr() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// make sure we are working with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "mykey")
|
rdb.Del(ctx, "mykey")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@ func ExampleClient_cms() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// make sure we are working with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:profit")
|
rdb.Del(ctx, "bikes:profit")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@ func ExampleClient_cuckoo() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// make sure we are working with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:models")
|
rdb.Del(ctx, "bikes:models")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
|
@ -20,7 +20,10 @@ func ExampleClient_geoindex() {
|
|||||||
DB: 0, // use default DB
|
DB: 0, // use default DB
|
||||||
Protocol: 2,
|
Protocol: 2,
|
||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// make sure we are working with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.FTDropIndex(ctx, "productidx")
|
rdb.FTDropIndex(ctx, "productidx")
|
||||||
rdb.FTDropIndex(ctx, "geomidx")
|
rdb.FTDropIndex(ctx, "geomidx")
|
||||||
rdb.Del(ctx, "product:46885", "product:46886", "shape:1", "shape:2", "shape:3", "shape:4")
|
rdb.Del(ctx, "product:46885", "product:46886", "shape:1", "shape:2", "shape:3", "shape:4")
|
||||||
|
@ -21,6 +21,8 @@ func ExampleClient_geoadd() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// make sure we are working with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:rentable")
|
rdb.Del(ctx, "bikes:rentable")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -81,6 +83,8 @@ func ExampleClient_geosearch() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:rentable")
|
rdb.Del(ctx, "bikes:rentable")
|
||||||
|
|
||||||
_, err := rdb.GeoAdd(ctx, "bikes:rentable",
|
_, err := rdb.GeoAdd(ctx, "bikes:rentable",
|
||||||
|
@ -21,6 +21,8 @@ func ExampleClient_set_get_all() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// make sure we are working with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bike:1")
|
rdb.Del(ctx, "bike:1")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -102,6 +104,8 @@ func ExampleClient_hmget() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bike:1")
|
rdb.Del(ctx, "bike:1")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -160,6 +164,8 @@ func ExampleClient_hincrby() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bike:1")
|
rdb.Del(ctx, "bike:1")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -209,6 +215,8 @@ func ExampleClient_incrby_get_mget() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bike:1:stats")
|
rdb.Del(ctx, "bike:1:stats")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@ func ExampleClient_pfadd() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// make sure we are working with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes", "commuter_bikes", "all_bikes")
|
rdb.Del(ctx, "bikes", "commuter_bikes", "all_bikes")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
|
@ -26,6 +26,8 @@ func ExampleClient_search_json() {
|
|||||||
})
|
})
|
||||||
// STEP_END
|
// STEP_END
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// make sure we are working with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "user:1", "user:2", "user:3")
|
rdb.Del(ctx, "user:1", "user:2", "user:3")
|
||||||
rdb.FTDropIndex(ctx, "idx:users")
|
rdb.FTDropIndex(ctx, "idx:users")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
@ -20,6 +20,8 @@ func ExampleClient_setget() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// make sure we are working with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bike")
|
rdb.Del(ctx, "bike")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -67,6 +69,8 @@ func ExampleClient_str() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bike")
|
rdb.Del(ctx, "bike")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -120,6 +124,8 @@ func ExampleClient_num() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "crashes")
|
rdb.Del(ctx, "crashes")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -174,6 +180,8 @@ func ExampleClient_arr() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "newbike")
|
rdb.Del(ctx, "newbike")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@ func ExampleClient_queue() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// make sure we are working with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:repairs")
|
rdb.Del(ctx, "bikes:repairs")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -75,6 +77,8 @@ func ExampleClient_stack() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:repairs")
|
rdb.Del(ctx, "bikes:repairs")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -129,6 +133,8 @@ func ExampleClient_llen() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:repairs")
|
rdb.Del(ctx, "bikes:repairs")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -156,6 +162,8 @@ func ExampleClient_lmove_lrange() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:repairs")
|
rdb.Del(ctx, "bikes:repairs")
|
||||||
rdb.Del(ctx, "bikes:finished")
|
rdb.Del(ctx, "bikes:finished")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
@ -220,6 +228,8 @@ func ExampleClient_lpush_rpush() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:repairs")
|
rdb.Del(ctx, "bikes:repairs")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -274,6 +284,8 @@ func ExampleClient_variadic() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:repairs")
|
rdb.Del(ctx, "bikes:repairs")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -319,6 +331,8 @@ func ExampleClient_lpop_rpop() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:repairs")
|
rdb.Del(ctx, "bikes:repairs")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -384,6 +398,8 @@ func ExampleClient_ltrim() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:repairs")
|
rdb.Del(ctx, "bikes:repairs")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -429,6 +445,8 @@ func ExampleClient_ltrim_end_of_list() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:repairs")
|
rdb.Del(ctx, "bikes:repairs")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -474,6 +492,8 @@ func ExampleClient_brpop() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:repairs")
|
rdb.Del(ctx, "bikes:repairs")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -529,6 +549,8 @@ func ExampleClient_rule1() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "new_bikes")
|
rdb.Del(ctx, "new_bikes")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
|
@ -20,6 +20,8 @@ func ExampleClient_transactions() {
|
|||||||
DB: 0, // use default DB
|
DB: 0, // use default DB
|
||||||
})
|
})
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// make sure we are working with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
for i := 0; i < 5; i++ {
|
for i := 0; i < 5; i++ {
|
||||||
rdb.Del(ctx, fmt.Sprintf("seat:%d", i))
|
rdb.Del(ctx, fmt.Sprintf("seat:%d", i))
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,8 @@ func ExampleClient_query_agg() {
|
|||||||
})
|
})
|
||||||
// HIDE_END
|
// HIDE_END
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.FTDropIndex(ctx, "idx:bicycle")
|
rdb.FTDropIndex(ctx, "idx:bicycle")
|
||||||
rdb.FTDropIndex(ctx, "idx:email")
|
rdb.FTDropIndex(ctx, "idx:email")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
@ -5,6 +5,8 @@ package example_commands_test
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"slices"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/redis/go-redis/v9"
|
"github.com/redis/go-redis/v9"
|
||||||
)
|
)
|
||||||
@ -21,6 +23,8 @@ func ExampleClient_query_em() {
|
|||||||
|
|
||||||
// HIDE_END
|
// HIDE_END
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.FTDropIndex(ctx, "idx:bicycle")
|
rdb.FTDropIndex(ctx, "idx:bicycle")
|
||||||
rdb.FTDropIndex(ctx, "idx:email")
|
rdb.FTDropIndex(ctx, "idx:email")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
@ -274,11 +278,16 @@ func ExampleClient_query_em() {
|
|||||||
|
|
||||||
fmt.Println(res3.Total) // >>> 5
|
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)
|
fmt.Println(doc.ID)
|
||||||
}
|
}
|
||||||
// >>> bicycle:5
|
|
||||||
// >>> bicycle:0
|
// >>> bicycle:0
|
||||||
|
// >>> bicycle:5
|
||||||
// >>> bicycle:6
|
// >>> bicycle:6
|
||||||
// >>> bicycle:7
|
// >>> bicycle:7
|
||||||
// >>> bicycle:8
|
// >>> bicycle:8
|
||||||
@ -350,8 +359,8 @@ func ExampleClient_query_em() {
|
|||||||
// 1
|
// 1
|
||||||
// bicycle:0
|
// bicycle:0
|
||||||
// 5
|
// 5
|
||||||
// bicycle:5
|
|
||||||
// bicycle:0
|
// bicycle:0
|
||||||
|
// bicycle:5
|
||||||
// bicycle:6
|
// bicycle:6
|
||||||
// bicycle:7
|
// bicycle:7
|
||||||
// bicycle:8
|
// bicycle:8
|
||||||
|
@ -21,6 +21,8 @@ func ExampleClient_query_ft() {
|
|||||||
})
|
})
|
||||||
// HIDE_END
|
// HIDE_END
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.FTDropIndex(ctx, "idx:bicycle")
|
rdb.FTDropIndex(ctx, "idx:bicycle")
|
||||||
rdb.FTDropIndex(ctx, "idx:email")
|
rdb.FTDropIndex(ctx, "idx:email")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
@ -21,6 +21,8 @@ func ExampleClient_query_geo() {
|
|||||||
})
|
})
|
||||||
// HIDE_END
|
// HIDE_END
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.FTDropIndex(ctx, "idx:bicycle")
|
rdb.FTDropIndex(ctx, "idx:bicycle")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@ func ExampleClient_Set_and_get() {
|
|||||||
// HIDE_END
|
// HIDE_END
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
errFlush := rdb.FlushDB(ctx).Err() // Clear the database before each test
|
errFlush := rdb.FlushDB(ctx).Err() // Clear the database before each test
|
||||||
if errFlush != nil {
|
if errFlush != nil {
|
||||||
panic(errFlush)
|
panic(errFlush)
|
||||||
|
@ -21,6 +21,8 @@ func ExampleClient_sadd() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:racing:france")
|
rdb.Del(ctx, "bikes:racing:france")
|
||||||
rdb.Del(ctx, "bikes:racing:usa")
|
rdb.Del(ctx, "bikes:racing:usa")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
@ -76,6 +78,8 @@ func ExampleClient_sismember() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:racing:france")
|
rdb.Del(ctx, "bikes:racing:france")
|
||||||
rdb.Del(ctx, "bikes:racing:usa")
|
rdb.Del(ctx, "bikes:racing:usa")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
@ -125,6 +129,8 @@ func ExampleClient_sinter() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:racing:france")
|
rdb.Del(ctx, "bikes:racing:france")
|
||||||
rdb.Del(ctx, "bikes:racing:usa")
|
rdb.Del(ctx, "bikes:racing:usa")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
@ -165,6 +171,8 @@ func ExampleClient_scard() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:racing:france")
|
rdb.Del(ctx, "bikes:racing:france")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -198,6 +206,8 @@ func ExampleClient_saddsmembers() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:racing:france")
|
rdb.Del(ctx, "bikes:racing:france")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -237,6 +247,8 @@ func ExampleClient_smismember() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:racing:france")
|
rdb.Del(ctx, "bikes:racing:france")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -279,6 +291,8 @@ func ExampleClient_sdiff() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:racing:france")
|
rdb.Del(ctx, "bikes:racing:france")
|
||||||
rdb.Del(ctx, "bikes:racing:usa")
|
rdb.Del(ctx, "bikes:racing:usa")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
@ -298,7 +312,6 @@ func ExampleClient_sdiff() {
|
|||||||
panic(err)
|
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)
|
sort.Strings(res13)
|
||||||
|
|
||||||
@ -319,6 +332,8 @@ func ExampleClient_multisets() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:racing:france")
|
rdb.Del(ctx, "bikes:racing:france")
|
||||||
rdb.Del(ctx, "bikes:racing:usa")
|
rdb.Del(ctx, "bikes:racing:usa")
|
||||||
rdb.Del(ctx, "bikes:racing:italy")
|
rdb.Del(ctx, "bikes:racing:italy")
|
||||||
@ -408,6 +423,8 @@ func ExampleClient_srem() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:racing:france")
|
rdb.Del(ctx, "bikes:racing:france")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
|
@ -20,6 +20,8 @@ func ExampleClient_zadd() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "racer_scores")
|
rdb.Del(ctx, "racer_scores")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -76,6 +78,8 @@ func ExampleClient_zrange() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "racer_scores")
|
rdb.Del(ctx, "racer_scores")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -127,6 +131,8 @@ func ExampleClient_zrangewithscores() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "racer_scores")
|
rdb.Del(ctx, "racer_scores")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -168,6 +174,8 @@ func ExampleClient_zrangebyscore() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "racer_scores")
|
rdb.Del(ctx, "racer_scores")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -211,6 +219,8 @@ func ExampleClient_zremrangebyscore() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "racer_scores")
|
rdb.Del(ctx, "racer_scores")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -270,6 +280,8 @@ func ExampleClient_zrank() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "racer_scores")
|
rdb.Del(ctx, "racer_scores")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -316,6 +328,8 @@ func ExampleClient_zaddlex() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "racer_scores")
|
rdb.Del(ctx, "racer_scores")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -377,6 +391,8 @@ func ExampleClient_leaderboard() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "racer_scores")
|
rdb.Del(ctx, "racer_scores")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
|
@ -26,6 +26,8 @@ func ExampleClient_xadd() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "race:france")
|
rdb.Del(ctx, "race:france")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -105,6 +107,8 @@ func ExampleClient_racefrance1() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "race:france")
|
rdb.Del(ctx, "race:france")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -227,6 +231,8 @@ func ExampleClient_raceusa() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "race:usa")
|
rdb.Del(ctx, "race:usa")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -310,6 +316,8 @@ func ExampleClient_racefrance2() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "race:france")
|
rdb.Del(ctx, "race:france")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -478,6 +486,8 @@ func ExampleClient_xgroupcreate() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "race:france")
|
rdb.Del(ctx, "race:france")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -520,6 +530,8 @@ func ExampleClient_xgroupcreatemkstream() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "race:italy")
|
rdb.Del(ctx, "race:italy")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -549,6 +561,8 @@ func ExampleClient_xgroupread() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "race:italy")
|
rdb.Del(ctx, "race:italy")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -654,6 +668,8 @@ func ExampleClient_raceitaly() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "race:italy")
|
rdb.Del(ctx, "race:italy")
|
||||||
rdb.XGroupDestroy(ctx, "race:italy", "italy_riders")
|
rdb.XGroupDestroy(ctx, "race:italy", "italy_riders")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
@ -1011,6 +1027,8 @@ func ExampleClient_xdel() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "race:italy")
|
rdb.Del(ctx, "race:italy")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
|
@ -20,6 +20,8 @@ func ExampleClient_set_get() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bike:1")
|
rdb.Del(ctx, "bike:1")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -56,6 +58,8 @@ func ExampleClient_setnx_xx() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Set(ctx, "bike:1", "Deimos", 0)
|
rdb.Set(ctx, "bike:1", "Deimos", 0)
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -101,6 +105,8 @@ func ExampleClient_mset() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bike:1", "bike:2", "bike:3")
|
rdb.Del(ctx, "bike:1", "bike:2", "bike:3")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -137,6 +143,8 @@ func ExampleClient_incr() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "total_crashes")
|
rdb.Del(ctx, "total_crashes")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@ func ExampleClient_tdigstart() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "racer_ages", "bikes:sales")
|
rdb.Del(ctx, "racer_ages", "bikes:sales")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -69,6 +71,8 @@ func ExampleClient_tdigcdf() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "racer_ages", "bikes:sales")
|
rdb.Del(ctx, "racer_ages", "bikes:sales")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -126,6 +130,8 @@ func ExampleClient_tdigquant() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "racer_ages")
|
rdb.Del(ctx, "racer_ages")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -177,6 +183,8 @@ func ExampleClient_tdigmin() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "racer_ages")
|
rdb.Del(ctx, "racer_ages")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
@ -228,6 +236,8 @@ func ExampleClient_tdigreset() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "racer_ages")
|
rdb.Del(ctx, "racer_ages")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
_, err := rdb.TDigestCreate(ctx, "racer_ages").Result()
|
_, err := rdb.TDigestCreate(ctx, "racer_ages").Result()
|
||||||
|
@ -21,6 +21,8 @@ func ExampleClient_topk() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// REMOVE_START
|
// REMOVE_START
|
||||||
|
// start with fresh database
|
||||||
|
rdb.FlushDB(ctx)
|
||||||
rdb.Del(ctx, "bikes:keywords")
|
rdb.Del(ctx, "bikes:keywords")
|
||||||
// REMOVE_END
|
// REMOVE_END
|
||||||
|
|
||||||
|
@ -10,6 +10,6 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
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
|
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)
|
return fmt.Sprintf(lib, libName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Drop Gears
|
||||||
var _ = Describe("RedisGears commands", Label("gears"), func() {
|
var _ = Describe("RedisGears commands", Label("gears"), func() {
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
var client *redis.Client
|
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() {
|
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()
|
resultAdd, err := client.TFunctionLoad(ctx, libCode("lib1")).Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(resultAdd).To(BeEquivalentTo("OK"))
|
Expect(resultAdd).To(BeEquivalentTo("OK"))
|
||||||
@ -58,6 +60,7 @@ var _ = Describe("RedisGears commands", Label("gears"), func() {
|
|||||||
Expect(resultAdd).To(BeEquivalentTo("OK"))
|
Expect(resultAdd).To(BeEquivalentTo("OK"))
|
||||||
})
|
})
|
||||||
It("should TFunctionList", Label("gears", "tfunctionlist"), func() {
|
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()
|
resultAdd, err := client.TFunctionLoad(ctx, libCode("lib1")).Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(resultAdd).To(BeEquivalentTo("OK"))
|
Expect(resultAdd).To(BeEquivalentTo("OK"))
|
||||||
@ -71,6 +74,7 @@ var _ = Describe("RedisGears commands", Label("gears"), func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should TFCall", Label("gears", "tfcall"), func() {
|
It("should TFCall", Label("gears", "tfcall"), func() {
|
||||||
|
SkipAfterRedisVersion(7.4, "gears are not working in later versions")
|
||||||
var resultAdd interface{}
|
var resultAdd interface{}
|
||||||
resultAdd, err := client.TFunctionLoad(ctx, libCode("lib1")).Result()
|
resultAdd, err := client.TFunctionLoad(ctx, libCode("lib1")).Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
@ -81,6 +85,7 @@ var _ = Describe("RedisGears commands", Label("gears"), func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should TFCallArgs", Label("gears", "tfcallargs"), func() {
|
It("should TFCallArgs", Label("gears", "tfcallargs"), func() {
|
||||||
|
SkipAfterRedisVersion(7.4, "gears are not working in later versions")
|
||||||
var resultAdd interface{}
|
var resultAdd interface{}
|
||||||
resultAdd, err := client.TFunctionLoad(ctx, libCode("lib1")).Result()
|
resultAdd, err := client.TFunctionLoad(ctx, libCode("lib1")).Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
@ -92,6 +97,7 @@ var _ = Describe("RedisGears commands", Label("gears"), func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should TFCallASYNC", Label("gears", "TFCallASYNC"), func() {
|
It("should TFCallASYNC", Label("gears", "TFCallASYNC"), func() {
|
||||||
|
SkipAfterRedisVersion(7.4, "gears are not working in later versions")
|
||||||
var resultAdd interface{}
|
var resultAdd interface{}
|
||||||
resultAdd, err := client.TFunctionLoad(ctx, libCode("lib1")).Result()
|
resultAdd, err := client.TFunctionLoad(ctx, libCode("lib1")).Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
@ -102,6 +108,7 @@ var _ = Describe("RedisGears commands", Label("gears"), func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should TFCallASYNCArgs", Label("gears", "TFCallASYNCargs"), func() {
|
It("should TFCallASYNCArgs", Label("gears", "TFCallASYNCargs"), func() {
|
||||||
|
SkipAfterRedisVersion(7.4, "gears are not working in later versions")
|
||||||
var resultAdd interface{}
|
var resultAdd interface{}
|
||||||
resultAdd, err := client.TFunctionLoad(ctx, libCode("lib1")).Result()
|
resultAdd, err := client.TFunctionLoad(ctx, libCode("lib1")).Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
@ -292,8 +292,8 @@ var _ = Describe("race", func() {
|
|||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
C, N = 10, 1000
|
C, N = 10, 1000
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
C = 4
|
C = 2
|
||||||
N = 100
|
N = 50
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -85,6 +85,7 @@ var _ = Describe("ScanIterator", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should hscan across multiple pages", func() {
|
It("should hscan across multiple pages", func() {
|
||||||
|
SkipBeforeRedisVersion(7.4, "doesn't work with older redis stack images")
|
||||||
Expect(hashSeed(71)).NotTo(HaveOccurred())
|
Expect(hashSeed(71)).NotTo(HaveOccurred())
|
||||||
|
|
||||||
var vals []string
|
var vals []string
|
||||||
@ -100,6 +101,7 @@ var _ = Describe("ScanIterator", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should hscan without values across multiple pages", Label("NonRedisEnterprise"), 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())
|
Expect(hashSeed(71)).NotTo(HaveOccurred())
|
||||||
|
|
||||||
var vals []string
|
var vals []string
|
||||||
|
226
main_test.go
226
main_test.go
@ -4,9 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -28,12 +27,12 @@ const (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
sentinelName = "go-redis-test"
|
sentinelName = "go-redis-test"
|
||||||
sentinelMasterPort = "9123"
|
sentinelMasterPort = "9121"
|
||||||
sentinelSlave1Port = "9124"
|
sentinelSlave1Port = "9122"
|
||||||
sentinelSlave2Port = "9125"
|
sentinelSlave2Port = "9123"
|
||||||
sentinelPort1 = "9126"
|
sentinelPort1 = "26379"
|
||||||
sentinelPort2 = "9127"
|
sentinelPort2 = "26380"
|
||||||
sentinelPort3 = "9128"
|
sentinelPort3 = "26381"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -49,19 +48,15 @@ var (
|
|||||||
var (
|
var (
|
||||||
sentinelAddrs = []string{":" + sentinelPort1, ":" + sentinelPort2, ":" + sentinelPort3}
|
sentinelAddrs = []string{":" + sentinelPort1, ":" + sentinelPort2, ":" + sentinelPort3}
|
||||||
|
|
||||||
processes map[string]*redisProcess
|
ringShard1, ringShard2, ringShard3 *redis.Client
|
||||||
|
sentinelMaster, sentinelSlave1, sentinelSlave2 *redis.Client
|
||||||
redisMain *redisProcess
|
sentinel1, sentinel2, sentinel3 *redis.Client
|
||||||
ringShard1, ringShard2, ringShard3 *redisProcess
|
|
||||||
sentinelMaster, sentinelSlave1, sentinelSlave2 *redisProcess
|
|
||||||
sentinel1, sentinel2, sentinel3 *redisProcess
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cluster = &clusterScenario{
|
var cluster = &clusterScenario{
|
||||||
ports: []string{"16600", "16601", "16602", "16603", "16604", "16605"},
|
ports: []string{"16600", "16601", "16602", "16603", "16604", "16605"},
|
||||||
nodeIDs: make([]string, 6),
|
nodeIDs: make([]string, 6),
|
||||||
processes: make(map[string]*redisProcess, 6),
|
clients: make(map[string]*redis.Client, 6),
|
||||||
clients: make(map[string]*redis.Client, 6),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redis Software Cluster
|
// Redis Software Cluster
|
||||||
@ -70,30 +65,23 @@ var RECluster = false
|
|||||||
// Redis Community Edition Docker
|
// Redis Community Edition Docker
|
||||||
var RCEDocker = false
|
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,
|
// 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.
|
// which have support for label sets, so we can filter tests per redis version.
|
||||||
var RedisMajorVersion = 7
|
var RedisVersion float64 = 7.2
|
||||||
|
|
||||||
func SkipBeforeRedisMajor(version int, msg string) {
|
func SkipBeforeRedisVersion(version float64, msg string) {
|
||||||
if RedisMajorVersion < version {
|
if RedisVersion < version {
|
||||||
Skip(fmt.Sprintf("(redis major version < %d) %s", version, msg))
|
Skip(fmt.Sprintf("(redis version < %f) %s", version, msg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func SkipAfterRedisMajor(version int, msg string) {
|
func SkipAfterRedisVersion(version float64, msg string) {
|
||||||
if RedisMajorVersion > version {
|
if RedisVersion > version {
|
||||||
Skip(fmt.Sprintf("(redis major version > %d) %s", version, msg))
|
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() {
|
var _ = BeforeSuite(func() {
|
||||||
addr := os.Getenv("REDIS_PORT")
|
addr := os.Getenv("REDIS_PORT")
|
||||||
if addr != "" {
|
if addr != "" {
|
||||||
@ -104,35 +92,33 @@ var _ = BeforeSuite(func() {
|
|||||||
RECluster, _ = strconv.ParseBool(os.Getenv("RE_CLUSTER"))
|
RECluster, _ = strconv.ParseBool(os.Getenv("RE_CLUSTER"))
|
||||||
RCEDocker, _ = strconv.ParseBool(os.Getenv("RCE_DOCKER"))
|
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 {
|
if RedisVersion == 0 {
|
||||||
RedisMajorVersion = 7
|
RedisVersion = 7.2
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("RECluster: %v\n", RECluster)
|
fmt.Printf("RECluster: %v\n", RECluster)
|
||||||
fmt.Printf("RCEDocker: %v\n", RCEDocker)
|
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 {
|
if RedisVersion < 7.0 || RedisVersion > 9 {
|
||||||
panic("incorrect or not supported redis major version")
|
panic("incorrect or not supported redis version")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !RECluster && !RCEDocker {
|
redisPort = redisStackPort
|
||||||
|
redisAddr = redisStackAddr
|
||||||
redisMain, err = startRedis(redisPort)
|
if !RECluster {
|
||||||
|
ringShard1, err = connectTo(ringShard1Port)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
ringShard1, err = startRedis(ringShard1Port)
|
ringShard2, err = connectTo(ringShard2Port)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
ringShard2, err = startRedis(ringShard2Port)
|
ringShard3, err = connectTo(ringShard3Port)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
ringShard3, err = startRedis(ringShard3Port)
|
sentinelMaster, err = connectTo(sentinelMasterPort)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
|
|
||||||
sentinelMaster, err = startRedis(sentinelMasterPort)
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
sentinel1, err = startSentinel(sentinelPort1, sentinelName, sentinelMasterPort)
|
sentinel1, err = startSentinel(sentinelPort1, sentinelName, sentinelMasterPort)
|
||||||
@ -144,24 +130,20 @@ var _ = BeforeSuite(func() {
|
|||||||
sentinel3, err = startSentinel(sentinelPort3, sentinelName, sentinelMasterPort)
|
sentinel3, err = startSentinel(sentinelPort3, sentinelName, sentinelMasterPort)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
sentinelSlave1, err = startRedis(
|
sentinelSlave1, err = connectTo(sentinelSlave1Port)
|
||||||
sentinelSlave1Port, "--slaveof", "127.0.0.1", sentinelMasterPort)
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
sentinelSlave2, err = startRedis(
|
err = sentinelSlave1.SlaveOf(ctx, "127.0.0.1", sentinelMasterPort).Err()
|
||||||
sentinelSlave2Port, "--slaveof", "127.0.0.1", sentinelMasterPort)
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
err = startCluster(ctx, cluster)
|
sentinelSlave2, err = connectTo(sentinelSlave2Port)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
} else {
|
|
||||||
redisPort = redisStackPort
|
|
||||||
redisAddr = redisStackAddr
|
|
||||||
|
|
||||||
if !RECluster {
|
err = sentinelSlave2.SlaveOf(ctx, "127.0.0.1", sentinelMasterPort).Err()
|
||||||
// populate cluster node information
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(configureClusterTopology(ctx, cluster)).NotTo(HaveOccurred())
|
|
||||||
}
|
// populate cluster node information
|
||||||
|
Expect(configureClusterTopology(ctx, cluster)).NotTo(HaveOccurred())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -169,12 +151,6 @@ var _ = AfterSuite(func() {
|
|||||||
if !RECluster {
|
if !RECluster {
|
||||||
Expect(cluster.Close()).NotTo(HaveOccurred())
|
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) {
|
func TestGinkgoSuite(t *testing.T) {
|
||||||
@ -204,7 +180,7 @@ func redisOptions() *redis.Options {
|
|||||||
}
|
}
|
||||||
return &redis.Options{
|
return &redis.Options{
|
||||||
Addr: redisAddr,
|
Addr: redisAddr,
|
||||||
DB: 15,
|
DB: 0,
|
||||||
|
|
||||||
DialTimeout: 10 * time.Second,
|
DialTimeout: 10 * time.Second,
|
||||||
ReadTimeout: 30 * time.Second,
|
ReadTimeout: 30 * time.Second,
|
||||||
@ -256,7 +232,9 @@ func performAsync(n int, cbs ...func(int)) *sync.WaitGroup {
|
|||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
for _, cb := range cbs {
|
for _, cb := range cbs {
|
||||||
wg.Add(n)
|
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) {
|
go func(cb func(int), i int) {
|
||||||
defer GinkgoRecover()
|
defer GinkgoRecover()
|
||||||
defer wg.Done()
|
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) {
|
func connectTo(port string) (*redis.Client, error) {
|
||||||
client := redis.NewClient(&redis.Options{
|
client := redis.NewClient(&redis.Options{
|
||||||
Addr: ":" + port,
|
Addr: ":" + port,
|
||||||
@ -338,117 +307,22 @@ func connectTo(port string) (*redis.Client, error) {
|
|||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type redisProcess struct {
|
func startSentinel(port, masterName, masterPort string) (*redis.Client, error) {
|
||||||
*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
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := connectTo(port)
|
client, err := connectTo(port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
process.Kill()
|
|
||||||
return nil, err
|
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{
|
for _, cmd := range []*redis.StatusCmd{
|
||||||
redis.NewStatusCmd(ctx, "SENTINEL", "MONITOR", masterName, "127.0.0.1", masterPort, "2"),
|
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)
|
client.Process(ctx, cmd)
|
||||||
if err := cmd.Err(); err != nil {
|
if err := cmd.Err(); err != nil && !strings.Contains(err.Error(), "ERR Duplicate master name.") {
|
||||||
process.Kill()
|
|
||||||
return nil, fmt.Errorf("%s failed: %w", cmd, err)
|
return nil, fmt.Errorf("%s failed: %w", cmd, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p := &redisProcess{process, client}
|
return client, nil
|
||||||
registerProcess(port, p)
|
|
||||||
return p, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@ -19,10 +20,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type clusterScenario struct {
|
type clusterScenario struct {
|
||||||
ports []string
|
ports []string
|
||||||
nodeIDs []string
|
nodeIDs []string
|
||||||
processes map[string]*redisProcess
|
clients map[string]*redis.Client
|
||||||
clients map[string]*redis.Client
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *clusterScenario) slots() []int {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func configureClusterTopology(ctx context.Context, scenario *clusterScenario) error {
|
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)
|
err := collectNodeInformation(ctx, scenario)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -131,7 +128,7 @@ func configureClusterTopology(ctx context.Context, scenario *clusterScenario) er
|
|||||||
slots := scenario.slots()
|
slots := scenario.slots()
|
||||||
for pos, master := range scenario.masters() {
|
for pos, master := range scenario.masters() {
|
||||||
err := master.ClusterAddSlotsRange(ctx, slots[pos], slots[pos+1]-1).Err()
|
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
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -199,7 +196,7 @@ func configureClusterTopology(ctx context.Context, scenario *clusterScenario) er
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return assertSlotsEqual(res, wanted)
|
return assertSlotsEqual(res, wanted)
|
||||||
}, 60*time.Second)
|
}, 90*time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -214,31 +211,17 @@ func collectNodeInformation(ctx context.Context, scenario *clusterScenario) erro
|
|||||||
Addr: ":" + port,
|
Addr: ":" + port,
|
||||||
})
|
})
|
||||||
|
|
||||||
info, err := client.ClusterNodes(ctx).Result()
|
myID, err := client.ClusterMyID(ctx).Result()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
scenario.clients[port] = client
|
scenario.clients[port] = client
|
||||||
scenario.nodeIDs[pos] = info[:40]
|
scenario.nodeIDs[pos] = myID
|
||||||
}
|
}
|
||||||
return nil
|
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 {
|
func assertSlotsEqual(slots, wanted []redis.ClusterSlot) error {
|
||||||
outerLoop:
|
outerLoop:
|
||||||
for _, s2 := range wanted {
|
for _, s2 := range wanted {
|
||||||
|
@ -89,6 +89,9 @@ var _ = Describe("PubSub", func() {
|
|||||||
pubsub := client.Subscribe(ctx, "mychannel", "mychannel2")
|
pubsub := client.Subscribe(ctx, "mychannel", "mychannel2")
|
||||||
defer pubsub.Close()
|
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()
|
channels, err = client.PubSubChannels(ctx, "mychannel*").Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(channels).To(ConsistOf([]string{"mychannel", "mychannel2"}))
|
Expect(channels).To(ConsistOf([]string{"mychannel", "mychannel2"}))
|
||||||
@ -135,6 +138,8 @@ var _ = Describe("PubSub", func() {
|
|||||||
pubsub := client.Subscribe(ctx, "mychannel", "mychannel2")
|
pubsub := client.Subscribe(ctx, "mychannel", "mychannel2")
|
||||||
defer pubsub.Close()
|
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()
|
channels, err := client.PubSubNumSub(ctx, "mychannel", "mychannel2", "mychannel3").Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(channels).To(Equal(map[string]int64{
|
Expect(channels).To(Equal(map[string]int64{
|
||||||
@ -152,6 +157,8 @@ var _ = Describe("PubSub", func() {
|
|||||||
pubsub := client.PSubscribe(ctx, "*")
|
pubsub := client.PSubscribe(ctx, "*")
|
||||||
defer pubsub.Close()
|
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()
|
num, err = client.PubSubNumPat(ctx).Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(num).To(Equal(int64(1)))
|
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() {
|
It("should handle big vals in Get", func() {
|
||||||
C, N = 4, 100
|
C, N := 4, 100
|
||||||
|
|
||||||
bigVal := bigVal()
|
bigVal := bigVal()
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ var _ = Describe("races", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should handle big vals in Set", func() {
|
It("should handle big vals in Set", func() {
|
||||||
C, N = 4, 100
|
C, N := 4, 100
|
||||||
|
|
||||||
bigVal := bigVal()
|
bigVal := bigVal()
|
||||||
perform(C, func(id int) {
|
perform(C, func(id int) {
|
||||||
@ -138,7 +138,7 @@ var _ = Describe("races", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should select db", Label("NonRedisEnterprise"), 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())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
perform(C, func(id int) {
|
perform(C, func(id int) {
|
||||||
@ -159,7 +159,7 @@ var _ = Describe("races", func() {
|
|||||||
|
|
||||||
n, err := client.Get(ctx, "db").Int64()
|
n, err := client.Get(ctx, "db").Int64()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(n).To(Equal(int64(1)))
|
Expect(n).To(Equal(int64(0)))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should select DB with read timeout", func() {
|
It("should select DB with read timeout", func() {
|
||||||
@ -214,12 +214,14 @@ var _ = Describe("races", func() {
|
|||||||
Expect(val).To(Equal(int64(C * N)))
|
Expect(val).To(Equal(int64(C * N)))
|
||||||
})
|
})
|
||||||
|
|
||||||
PIt("should BLPop", func() {
|
It("should BLPop", func() {
|
||||||
|
C := 5
|
||||||
|
N := 5
|
||||||
var received uint32
|
var received uint32
|
||||||
|
|
||||||
wg := performAsync(C, func(id int) {
|
wg := performAsync(C, func(id int) {
|
||||||
for {
|
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 != nil {
|
||||||
if err == redis.Nil {
|
if err == redis.Nil {
|
||||||
break
|
break
|
||||||
|
@ -66,11 +66,7 @@ var _ = Describe("Client", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should Stringer", func() {
|
It("should Stringer", func() {
|
||||||
if RECluster {
|
Expect(client.String()).To(Equal(fmt.Sprintf("Redis<:%s db:0>", redisPort)))
|
||||||
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)))
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
It("supports context", func() {
|
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"))
|
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() {
|
It("supports hash tags", func() {
|
||||||
for i := 0; i < 100; i++ {
|
for i := 0; i < 100; i++ {
|
||||||
err := ring.Set(ctx, fmt.Sprintf("key%d{tag}", i), "value", 0).Err()
|
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
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: remove FTProfile
|
||||||
// type FTProfileResult struct {
|
// type FTProfileResult struct {
|
||||||
// Results []interface{}
|
// Results []interface{}
|
||||||
// Profile ProfileDetails
|
// 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
|
// up until redis 8 the default scorer was TFIDF, in redis 8 it is BM25
|
||||||
// this test expect redis major version >= 8
|
// this test expect redis major version >= 8
|
||||||
It("should FTSearch WithScores", Label("search", "ftsearch"), func() {
|
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}
|
text1 := &redis.FieldSchema{FieldName: "description", FieldType: redis.SearchFieldTypeText}
|
||||||
val, err := client.FTCreate(ctx, "idx1", &redis.FTCreateOptions{}, text1).Result()
|
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
|
// 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() {
|
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}
|
text1 := &redis.FieldSchema{FieldName: "description", FieldType: redis.SearchFieldTypeText}
|
||||||
val, err := client.FTCreate(ctx, "idx1", &redis.FTCreateOptions{}, text1).Result()
|
val, err := client.FTCreate(ctx, "idx1", &redis.FTCreateOptions{}, text1).Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
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() {
|
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(err).NotTo(HaveOccurred())
|
||||||
Expect(val).To(BeEquivalentTo("OK"))
|
Expect(val).To(BeEquivalentTo("OK"))
|
||||||
|
|
||||||
res, err := client.FTConfigGet(ctx, "*").Result()
|
res, err := client.FTConfigGet(ctx, "*").Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
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(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() {
|
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}
|
title := &redis.FieldSchema{FieldName: "title", FieldType: redis.SearchFieldTypeText, Sortable: false}
|
||||||
description := &redis.FieldSchema{FieldName: "description", 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()
|
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() {
|
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{
|
val, err := client.FTCreate(ctx, "idx1", &redis.FTCreateOptions{
|
||||||
Prefix: []interface{}{"resource:"},
|
Prefix: []interface{}{"resource:"},
|
||||||
}, &redis.FieldSchema{
|
}, &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() {
|
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{},
|
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: "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"}}},
|
&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() {
|
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{
|
_, err := client.FTCreate(ctx, "idx1", &redis.FTCreateOptions{}, &redis.FieldSchema{
|
||||||
FieldName: "g",
|
FieldName: "g",
|
||||||
FieldType: redis.SearchFieldTypeGeoShape,
|
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() {
|
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:"}},
|
val, err := client.FTCreate(ctx, "idx1", &redis.FTCreateOptions{Prefix: []interface{}{"property:"}},
|
||||||
&redis.FieldSchema{FieldName: "title", FieldType: redis.SearchFieldTypeText, Sortable: true},
|
&redis.FieldSchema{FieldName: "title", FieldType: redis.SearchFieldTypeText, Sortable: true},
|
||||||
&redis.FieldSchema{FieldName: "features", FieldType: redis.SearchFieldTypeTag, IndexMissing: 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() {
|
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:"}},
|
val, err := client.FTCreate(ctx, "idx1", &redis.FTCreateOptions{Prefix: []interface{}{"property:"}},
|
||||||
&redis.FieldSchema{FieldName: "title", FieldType: redis.SearchFieldTypeText, Sortable: true},
|
&redis.FieldSchema{FieldName: "title", FieldType: redis.SearchFieldTypeText, Sortable: true},
|
||||||
&redis.FieldSchema{FieldName: "features", FieldType: redis.SearchFieldTypeTag, IndexEmpty: 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())
|
Expect(clientResp3.Close()).NotTo(HaveOccurred())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should FTConfigSet and FTConfigGet ", Label("search", "ftconfigget", "ftconfigset", "NonRedisEnterprise"), func() {
|
It("should FTConfigSet and FTConfigGet with resp2 and resp3", Label("search", "ftconfigget", "ftconfigset", "NonRedisEnterprise"), func() {
|
||||||
val, err := clientResp3.FTConfigSet(ctx, "TIMEOUT", "100").Result()
|
val, err := clientResp3.FTConfigSet(ctx, "MINPREFIX", "1").Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(val).To(BeEquivalentTo("OK"))
|
Expect(val).To(BeEquivalentTo("OK"))
|
||||||
|
|
||||||
res2, err := clientResp2.FTConfigGet(ctx, "TIMEOUT").Result()
|
res2, err := clientResp2.FTConfigGet(ctx, "MINPREFIX").Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
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(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() {
|
It("should FTConfigGet all resp2 and resp3", Label("search", "NonRedisEnterprise"), func() {
|
||||||
|
@ -6,13 +6,11 @@ import (
|
|||||||
|
|
||||||
. "github.com/bsm/ginkgo/v2"
|
. "github.com/bsm/ginkgo/v2"
|
||||||
. "github.com/bsm/gomega"
|
. "github.com/bsm/gomega"
|
||||||
|
|
||||||
"github.com/redis/go-redis/v9"
|
"github.com/redis/go-redis/v9"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("Sentinel PROTO 2", func() {
|
var _ = Describe("Sentinel PROTO 2", func() {
|
||||||
var client *redis.Client
|
var client *redis.Client
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
client = redis.NewFailoverClient(&redis.FailoverOptions{
|
client = redis.NewFailoverClient(&redis.FailoverOptions{
|
||||||
MasterName: sentinelName,
|
MasterName: sentinelName,
|
||||||
@ -37,7 +35,6 @@ var _ = Describe("Sentinel PROTO 2", func() {
|
|||||||
var _ = Describe("Sentinel", func() {
|
var _ = Describe("Sentinel", func() {
|
||||||
var client *redis.Client
|
var client *redis.Client
|
||||||
var master *redis.Client
|
var master *redis.Client
|
||||||
var masterPort string
|
|
||||||
var sentinel *redis.SentinelClient
|
var sentinel *redis.SentinelClient
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
@ -61,18 +58,17 @@ var _ = Describe("Sentinel", func() {
|
|||||||
Addr: net.JoinHostPort(addr[0], addr[1]),
|
Addr: net.JoinHostPort(addr[0], addr[1]),
|
||||||
MaxRetries: -1,
|
MaxRetries: -1,
|
||||||
})
|
})
|
||||||
masterPort = addr[1]
|
|
||||||
|
|
||||||
// Wait until slaves are picked up by sentinel.
|
// Wait until slaves are picked up by sentinel.
|
||||||
Eventually(func() string {
|
Eventually(func() string {
|
||||||
return sentinel1.Info(ctx).Val()
|
return sentinel1.Info(ctx).Val()
|
||||||
}, "15s", "100ms").Should(ContainSubstring("slaves=2"))
|
}, "20s", "100ms").Should(ContainSubstring("slaves=2"))
|
||||||
Eventually(func() string {
|
Eventually(func() string {
|
||||||
return sentinel2.Info(ctx).Val()
|
return sentinel2.Info(ctx).Val()
|
||||||
}, "15s", "100ms").Should(ContainSubstring("slaves=2"))
|
}, "20s", "100ms").Should(ContainSubstring("slaves=2"))
|
||||||
Eventually(func() string {
|
Eventually(func() string {
|
||||||
return sentinel3.Info(ctx).Val()
|
return sentinel3.Info(ctx).Val()
|
||||||
}, "15s", "100ms").Should(ContainSubstring("slaves=2"))
|
}, "20s", "100ms").Should(ContainSubstring("slaves=2"))
|
||||||
})
|
})
|
||||||
|
|
||||||
AfterEach(func() {
|
AfterEach(func() {
|
||||||
@ -96,7 +92,7 @@ var _ = Describe("Sentinel", func() {
|
|||||||
Eventually(func() []string {
|
Eventually(func() []string {
|
||||||
slavesAddr = redis.GetSlavesAddrByName(ctx, sentinel, sentinelName)
|
slavesAddr = redis.GetSlavesAddrByName(ctx, sentinel, sentinelName)
|
||||||
return slavesAddr
|
return slavesAddr
|
||||||
}, "15s", "100ms").Should(HaveLen(2))
|
}, "20s", "50ms").Should(HaveLen(2))
|
||||||
Eventually(func() bool {
|
Eventually(func() bool {
|
||||||
sync := true
|
sync := true
|
||||||
for _, addr := range slavesAddr {
|
for _, addr := range slavesAddr {
|
||||||
@ -108,36 +104,35 @@ var _ = Describe("Sentinel", func() {
|
|||||||
_ = slave.Close()
|
_ = slave.Close()
|
||||||
}
|
}
|
||||||
return sync
|
return sync
|
||||||
}, "15s", "100ms").Should(BeTrue())
|
}, "20s", "50ms").Should(BeTrue())
|
||||||
|
|
||||||
// Create subscription.
|
// Create subscription.
|
||||||
pub := client.Subscribe(ctx, "foo")
|
pub := client.Subscribe(ctx, "foo")
|
||||||
ch := pub.Channel()
|
ch := pub.Channel()
|
||||||
|
|
||||||
// Kill master.
|
// Kill master.
|
||||||
err = master.Shutdown(ctx).Err()
|
/*
|
||||||
Expect(err).NotTo(HaveOccurred())
|
err = master.Shutdown(ctx).Err()
|
||||||
Eventually(func() error {
|
Expect(err).NotTo(HaveOccurred())
|
||||||
return master.Ping(ctx).Err()
|
Eventually(func() error {
|
||||||
}, "15s", "100ms").Should(HaveOccurred())
|
return master.Ping(ctx).Err()
|
||||||
|
}, "20s", "50ms").Should(HaveOccurred())
|
||||||
|
*/
|
||||||
|
|
||||||
// Check that client picked up new master.
|
// Check that client picked up new master.
|
||||||
Eventually(func() string {
|
Eventually(func() string {
|
||||||
return client.Get(ctx, "foo").Val()
|
return client.Get(ctx, "foo").Val()
|
||||||
}, "15s", "100ms").Should(Equal("master"))
|
}, "20s", "100ms").Should(Equal("master"))
|
||||||
|
|
||||||
// Check if subscription is renewed.
|
// Check if subscription is renewed.
|
||||||
var msg *redis.Message
|
var msg *redis.Message
|
||||||
Eventually(func() <-chan *redis.Message {
|
Eventually(func() <-chan *redis.Message {
|
||||||
_ = client.Publish(ctx, "foo", "hello").Err()
|
_ = client.Publish(ctx, "foo", "hello").Err()
|
||||||
return ch
|
return ch
|
||||||
}, "15s", "100ms").Should(Receive(&msg))
|
}, "20s", "100ms").Should(Receive(&msg))
|
||||||
Expect(msg.Channel).To(Equal("foo"))
|
Expect(msg.Channel).To(Equal("foo"))
|
||||||
Expect(msg.Payload).To(Equal("hello"))
|
Expect(msg.Payload).To(Equal("hello"))
|
||||||
Expect(pub.Close()).NotTo(HaveOccurred())
|
Expect(pub.Close()).NotTo(HaveOccurred())
|
||||||
|
|
||||||
_, err = startRedis(masterPort)
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
})
|
})
|
||||||
|
|
||||||
It("supports DB selection", func() {
|
It("supports DB selection", func() {
|
||||||
@ -197,7 +192,6 @@ var _ = Describe("NewFailoverClusterClient PROTO 2", func() {
|
|||||||
var _ = Describe("NewFailoverClusterClient", func() {
|
var _ = Describe("NewFailoverClusterClient", func() {
|
||||||
var client *redis.ClusterClient
|
var client *redis.ClusterClient
|
||||||
var master *redis.Client
|
var master *redis.Client
|
||||||
var masterPort string
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
client = redis.NewFailoverClusterClient(&redis.FailoverOptions{
|
client = redis.NewFailoverClusterClient(&redis.FailoverOptions{
|
||||||
@ -221,18 +215,17 @@ var _ = Describe("NewFailoverClusterClient", func() {
|
|||||||
Addr: net.JoinHostPort(addr[0], addr[1]),
|
Addr: net.JoinHostPort(addr[0], addr[1]),
|
||||||
MaxRetries: -1,
|
MaxRetries: -1,
|
||||||
})
|
})
|
||||||
masterPort = addr[1]
|
|
||||||
|
|
||||||
// Wait until slaves are picked up by sentinel.
|
// Wait until slaves are picked up by sentinel.
|
||||||
Eventually(func() string {
|
Eventually(func() string {
|
||||||
return sentinel1.Info(ctx).Val()
|
return sentinel1.Info(ctx).Val()
|
||||||
}, "15s", "100ms").Should(ContainSubstring("slaves=2"))
|
}, "20s", "100ms").Should(ContainSubstring("slaves=2"))
|
||||||
Eventually(func() string {
|
Eventually(func() string {
|
||||||
return sentinel2.Info(ctx).Val()
|
return sentinel2.Info(ctx).Val()
|
||||||
}, "15s", "100ms").Should(ContainSubstring("slaves=2"))
|
}, "20s", "100ms").Should(ContainSubstring("slaves=2"))
|
||||||
Eventually(func() string {
|
Eventually(func() string {
|
||||||
return sentinel3.Info(ctx).Val()
|
return sentinel3.Info(ctx).Val()
|
||||||
}, "15s", "100ms").Should(ContainSubstring("slaves=2"))
|
}, "20s", "100ms").Should(ContainSubstring("slaves=2"))
|
||||||
})
|
})
|
||||||
|
|
||||||
AfterEach(func() {
|
AfterEach(func() {
|
||||||
@ -241,7 +234,6 @@ var _ = Describe("NewFailoverClusterClient", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should facilitate failover", func() {
|
It("should facilitate failover", func() {
|
||||||
Skip("Flaky Test")
|
|
||||||
// Set value.
|
// Set value.
|
||||||
err := client.Set(ctx, "foo", "master", 0).Err()
|
err := client.Set(ctx, "foo", "master", 0).Err()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
@ -250,7 +242,7 @@ var _ = Describe("NewFailoverClusterClient", func() {
|
|||||||
// Verify.
|
// Verify.
|
||||||
Eventually(func() string {
|
Eventually(func() string {
|
||||||
return client.Get(ctx, "foo").Val()
|
return client.Get(ctx, "foo").Val()
|
||||||
}, "15s", "1ms").Should(Equal("master"))
|
}, "20s", "1ms").Should(Equal("master"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create subscription.
|
// Create subscription.
|
||||||
@ -258,33 +250,32 @@ var _ = Describe("NewFailoverClusterClient", func() {
|
|||||||
ch := sub.Channel()
|
ch := sub.Channel()
|
||||||
|
|
||||||
// Kill master.
|
// Kill master.
|
||||||
err = master.Shutdown(ctx).Err()
|
/*
|
||||||
Expect(err).NotTo(HaveOccurred())
|
err = master.Shutdown(ctx).Err()
|
||||||
Eventually(func() error {
|
Expect(err).NotTo(HaveOccurred())
|
||||||
return master.Ping(ctx).Err()
|
Eventually(func() error {
|
||||||
}, "15s", "100ms").Should(HaveOccurred())
|
return master.Ping(ctx).Err()
|
||||||
|
}, "20s", "100ms").Should(HaveOccurred())
|
||||||
|
*/
|
||||||
|
|
||||||
// Check that client picked up new master.
|
// Check that client picked up new master.
|
||||||
Eventually(func() string {
|
Eventually(func() string {
|
||||||
return client.Get(ctx, "foo").Val()
|
return client.Get(ctx, "foo").Val()
|
||||||
}, "15s", "100ms").Should(Equal("master"))
|
}, "20s", "100ms").Should(Equal("master"))
|
||||||
|
|
||||||
// Check if subscription is renewed.
|
// Check if subscription is renewed.
|
||||||
var msg *redis.Message
|
var msg *redis.Message
|
||||||
Eventually(func() <-chan *redis.Message {
|
Eventually(func() <-chan *redis.Message {
|
||||||
_ = client.Publish(ctx, "foo", "hello").Err()
|
_ = client.Publish(ctx, "foo", "hello").Err()
|
||||||
return ch
|
return ch
|
||||||
}, "15s", "100ms").Should(Receive(&msg))
|
}, "20s", "100ms").Should(Receive(&msg))
|
||||||
Expect(msg.Channel).To(Equal("foo"))
|
Expect(msg.Channel).To(Equal("foo"))
|
||||||
Expect(msg.Payload).To(Equal("hello"))
|
Expect(msg.Payload).To(Equal("hello"))
|
||||||
Expect(sub.Close()).NotTo(HaveOccurred())
|
Expect(sub.Close()).NotTo(HaveOccurred())
|
||||||
|
|
||||||
_, err = startRedis(masterPort)
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should sentinel cluster client setname", func() {
|
It("should sentinel cluster client setname", func() {
|
||||||
Skip("Flaky Test")
|
|
||||||
err := client.ForEachShard(ctx, func(ctx context.Context, c *redis.Client) error {
|
err := client.ForEachShard(ctx, func(ctx context.Context, c *redis.Client) error {
|
||||||
return c.Ping(ctx).Err()
|
return c.Ping(ctx).Err()
|
||||||
})
|
})
|
||||||
@ -299,7 +290,6 @@ var _ = Describe("NewFailoverClusterClient", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should sentinel cluster PROTO 3", func() {
|
It("should sentinel cluster PROTO 3", func() {
|
||||||
Skip("Flaky Test")
|
|
||||||
_ = client.ForEachShard(ctx, func(ctx context.Context, c *redis.Client) error {
|
_ = client.ForEachShard(ctx, func(ctx context.Context, c *redis.Client) error {
|
||||||
val, err := client.Do(ctx, "HELLO").Result()
|
val, err := client.Do(ctx, "HELLO").Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
@ -317,8 +307,8 @@ var _ = Describe("SentinelAclAuth", func() {
|
|||||||
|
|
||||||
var client *redis.Client
|
var client *redis.Client
|
||||||
var sentinel *redis.SentinelClient
|
var sentinel *redis.SentinelClient
|
||||||
sentinels := func() []*redisProcess {
|
sentinels := func() []*redis.Client {
|
||||||
return []*redisProcess{sentinel1, sentinel2, sentinel3}
|
return []*redis.Client{sentinel1, sentinel2, sentinel3}
|
||||||
}
|
}
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
@ -328,7 +318,7 @@ var _ = Describe("SentinelAclAuth", func() {
|
|||||||
"+sentinel|myid", "+sentinel|replicas", "+sentinel|sentinels")
|
"+sentinel|myid", "+sentinel|replicas", "+sentinel|sentinels")
|
||||||
|
|
||||||
for _, process := range sentinels() {
|
for _, process := range sentinels() {
|
||||||
err := process.Client.Process(ctx, authCmd)
|
err := process.Process(ctx, authCmd)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,7 +346,7 @@ var _ = Describe("SentinelAclAuth", func() {
|
|||||||
for _, process := range sentinels() {
|
for _, process := range sentinels() {
|
||||||
Eventually(func() string {
|
Eventually(func() string {
|
||||||
return process.Info(ctx).Val()
|
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)
|
unauthCommand := redis.NewStatusCmd(ctx, "ACL", "DELUSER", aclSentinelUsername)
|
||||||
|
|
||||||
for _, process := range sentinels() {
|
for _, process := range sentinels() {
|
||||||
err := process.Client.Process(ctx, unauthCommand)
|
err := process.Process(ctx, unauthCommand)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
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() {
|
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()
|
result, err := client.TSCreate(ctx, "1").Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(result).To(BeEquivalentTo("OK"))
|
Expect(result).To(BeEquivalentTo("OK"))
|
||||||
@ -139,6 +140,7 @@ var _ = Describe("RedisTimeseries commands", Label("timeseries"), func() {
|
|||||||
{Timestamp: 1013, Value: 10.0}}))
|
{Timestamp: 1013, Value: 10.0}}))
|
||||||
})
|
})
|
||||||
It("should TSAdd and TSAddWithArgs", Label("timeseries", "tsadd", "tsaddWithArgs", "NonRedisEnterprise"), func() {
|
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()
|
result, err := client.TSAdd(ctx, "1", 1, 1).Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(result).To(BeEquivalentTo(1))
|
Expect(result).To(BeEquivalentTo(1))
|
||||||
@ -232,6 +234,7 @@ var _ = Describe("RedisTimeseries commands", Label("timeseries"), func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should TSAlter", Label("timeseries", "tsalter", "NonRedisEnterprise"), 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()
|
result, err := client.TSCreate(ctx, "1").Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(result).To(BeEquivalentTo("OK"))
|
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() {
|
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++ {
|
for i := 0; i < 100; i++ {
|
||||||
_, err := client.TSIncrBy(ctx, "1", 1).Result()
|
_, err := client.TSIncrBy(ctx, "1", 1).Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
@ -16,8 +16,7 @@ var _ = Describe("UniversalClient", func() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should connect to failover servers", func() {
|
It("should connect to failover servers", Label("NonRedisEnterprise"), func() {
|
||||||
Skip("Flaky Test")
|
|
||||||
client = redis.NewUniversalClient(&redis.UniversalOptions{
|
client = redis.NewUniversalClient(&redis.UniversalOptions{
|
||||||
MasterName: sentinelName,
|
MasterName: sentinelName,
|
||||||
Addrs: sentinelAddrs,
|
Addrs: sentinelAddrs,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user