diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index b3538290ee..e1bb6dcefa 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -33,6 +33,8 @@ Set up test environments with ```make start```, tear down those environments wit * You can import code style file (located to hbase-formatter.xml) to Eclipse, IntelliJ * line break by column count seems not working with IntelliJ * You can run ```make format``` anytime to reformat without IDEs +* DO NOT format the source codes within `io.redis.examples` test package. +* A test class name MUST NOT end with `Example`. ## Adding commands diff --git a/.github/release-drafter-config.yml b/.github/release-drafter-config.yml index edc2911f43..4607da071c 100644 --- a/.github/release-drafter-config.yml +++ b/.github/release-drafter-config.yml @@ -1,5 +1,7 @@ name-template: '$NEXT_MINOR_VERSION' tag-template: 'v$NEXT_MINOR_VERSION' +filter-by-commitish: true +commitish: master autolabeler: - label: 'maintenance' files: @@ -35,6 +37,8 @@ categories: labels: - 'maintenance' - 'dependencies' + - 'documentation' + - 'docs' - 'testing' change-template: '- $TITLE (#$NUMBER)' exclude-labels: diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index fd7c46dc80..3f472ee7cc 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -24,24 +24,20 @@ jobs: analyze: name: Analyze runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - language: [ 'java' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] - # Learn more: - # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed + permissions: + security-events: write + actions: read + contents: read steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v2 with: - languages: ${{ matrix.language }} + languages: java # 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. @@ -50,7 +46,7 @@ jobs: # 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@v1 + uses: github/codeql-action/autobuild@v2 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -64,4 +60,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/doctests.yml b/.github/workflows/doctests.yml new file mode 100644 index 0000000000..daa8858b89 --- /dev/null +++ b/.github/workflows/doctests.yml @@ -0,0 +1,37 @@ +name: Documentation Tests + +on: + push: + tags-ignore: + - '*' + pull_request: + workflow_dispatch: + +jobs: + doctests: + runs-on: ubuntu-latest + services: + redis-stack: + image: redis/redis-stack-server:latest + options: >- + --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5 + ports: + - 6379:6379 + + steps: + - uses: actions/checkout@v3 + - name: Cache dependencies + uses: actions/cache@v2 + with: + path: | + ~/.m2/repository + /var/cache/apt + key: jedis-${{hashFiles('**/pom.xml')}} + - name: Set up Java + uses: actions/setup-java@v2 + with: + java-version: '11' + distribution: 'temurin' + - name: Run doctests + run: | + mvn -Pdoctests test diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 5e047a650f..84da5938f6 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -10,13 +10,16 @@ on: - '**/*.rst' branches: - master - - '[0-9].[0-9]' + - '[0-9].x' + - '[0-9].[0-9].x' pull_request: branches: - master - - '[0-9].[0-9]' + - '[0-9].x' + - '[0-9].[0-9].x' schedule: - cron: '0 1 * * *' # nightly build + workflow_dispatch: jobs: @@ -45,16 +48,33 @@ jobs: - name: Maven offline run: | mvn -q dependency:go-offline + - name: Build docs + run: | + mvn javadoc:jar - name: Run tests run: | TEST="" make test env: JVM_OPTS: -Xmx3200m TERM: dumb - - name: redismod docker - run: docker run -p 52567:6379 -d redislabs/redismod:edge - - name: Run tests + - name: sleep 10s + run: sleep 10s + - name: Make - start + run: | + make start + sleep 2s + - name: Docker - mod or stack + run: docker run -p 52567:6379 -d redis/redis-stack-server:edge + - name: Test commands - default protocol + run: mvn -Dtest="redis.clients.jedis.commands.**" test + - name: Test commands - RESP3 protocol + run: mvn -DjedisProtocol=3 -Dtest="redis.clients.jedis.commands.**" test + - name: Test module commands - default protocol run: mvn -DmodulesDocker="localhost:52567" -Dtest="redis.clients.jedis.modules.**" test + - name: Test module commands - RESP3 protocol + run: mvn -DjedisProtocol=3 -DmodulesDocker="localhost:52567" -Dtest="redis.clients.jedis.modules.**" test + - name: Make - stop + run: make stop - name: Codecov run: | bash <(curl -s https://codecov.io/bash) diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 6c8ad1a962..8a409b8331 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -6,7 +6,8 @@ on: push: branches: - master - - '[0-9].[0-9]' + - '[0-9].x' + workflow_dispatch: jobs: diff --git a/.github/workflows/version-and-release.yml b/.github/workflows/version-and-release.yml index 007d8875e8..7c996e5bd5 100644 --- a/.github/workflows/version-and-release.yml +++ b/.github/workflows/version-and-release.yml @@ -16,7 +16,7 @@ jobs: run: | realversion="${GITHUB_REF/refs\/tags\//}" realversion="${realversion//v/}" - echo "::set-output name=VERSION::$realversion" + echo "VERSION=$realversion" >> $GITHUB_OUTPUT - name: Set up publishing to maven central uses: actions/setup-java@v2 @@ -32,14 +32,14 @@ jobs: - name: Install gpg key run: | - cat <(echo -e "${{ secrets.OSSRH_GPG_SECRET_KEY }}") | gpg --batch --import + cat <(echo -e "${{ secrets.OSSH_GPG_SECRET_KEY }}") | gpg --batch --import gpg --list-secret-keys --keyid-format LONG - name: Publish run: | mvn --no-transfer-progress \ --batch-mode \ - -Dgpg.passphrase='${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }}' \ + -Dgpg.passphrase='${{ secrets.OSSH_GPG_SECRET_KEY_PASSWORD }}' \ -DskipTests deploy -P release env: MAVEN_USERNAME: ${{secrets.OSSH_USERNAME}} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..15c4dd523a --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021-2023, Redis, inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index 7b8b1cee63..0000000000 --- a/LICENSE.txt +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (c) 2010 Jonathan Leibiusky - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/Makefile b/Makefile index 2987ad80dd..6e63f1b6ce 100644 --- a/Makefile +++ b/Makefile @@ -209,7 +209,7 @@ daemonize yes protected-mode no requirepass cluster port 7379 -cluster-node-timeout 50 +cluster-node-timeout 15000 pidfile /tmp/redis_cluster_node1.pid logfile /tmp/redis_cluster_node1.log save "" @@ -223,7 +223,7 @@ daemonize yes protected-mode no requirepass cluster port 7380 -cluster-node-timeout 50 +cluster-node-timeout 15000 pidfile /tmp/redis_cluster_node2.pid logfile /tmp/redis_cluster_node2.log save "" @@ -237,7 +237,7 @@ daemonize yes protected-mode no requirepass cluster port 7381 -cluster-node-timeout 50 +cluster-node-timeout 15000 pidfile /tmp/redis_cluster_node3.pid logfile /tmp/redis_cluster_node3.log save "" @@ -251,7 +251,7 @@ daemonize yes protected-mode no requirepass cluster port 7382 -cluster-node-timeout 50 +cluster-node-timeout 15000 pidfile /tmp/redis_cluster_node4.pid logfile /tmp/redis_cluster_node4.log save "" @@ -265,7 +265,7 @@ daemonize yes protected-mode no requirepass cluster port 7383 -cluster-node-timeout 5000 +cluster-node-timeout 15000 pidfile /tmp/redis_cluster_node5.pid logfile /tmp/redis_cluster_node5.log save "" diff --git a/README.md b/README.md index 3620931c2b..4c7c507d21 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE.txt) [![Integration](https://github.com/redis/jedis/actions/workflows/integration.yml/badge.svg?branch=master)](https://github.com/redis/jedis/actions/workflows/integration.yml) [![codecov](https://codecov.io/gh/redis/jedis/branch/master/graph/badge.svg?token=pAstxAAjYo)](https://codecov.io/gh/redis/jedis) -[![Discord](https://img.shields.io/discord/697882427875393627?style=flat-square)](https://discord.gg/qRhBuY8Z) +[![Discord](https://img.shields.io/discord/697882427875393627?style=flat-square)](https://discord.gg/redis) ## What is Jedis? @@ -14,14 +14,37 @@ Jedis is a Java client for [Redis](https://github.com/redis/redis "Redis") desig Are you looking for a high-level library to handle object mapping? See [redis-om-spring](https://github.com/redis/redis-om-spring)! -## Contributing +## How do I Redis? -We'd love your contributions! +[Learn for free at Redis University](https://university.redis.com/) -**Bug reports** are always welcome! [You can open a bug report on GitHub](https://github.com/redis/jedis/issues/new). +[Build faster with the Redis Launchpad](https://launchpad.redis.com/) -You can also **contribute documentation** -- or anything to improve Jedis. Please see -[contribution guideline](https://github.com/redis/jedis/blob/master/.github/CONTRIBUTING.md) for more details. +[Try the Redis Cloud](https://redis.com/try-free/) + +[Dive in developer tutorials](https://developer.redis.com/) + +[Join the Redis community](https://redis.com/community/) + +[Work at Redis](https://redis.com/company/careers/jobs/) + +## Supported Redis versions + +The most recent version of this library supports redis version +[5.0](https://github.com/redis/redis/blob/5.0/00-RELEASENOTES), +[6.0](https://github.com/redis/redis/blob/6.0/00-RELEASENOTES), +[6.2](https://github.com/redis/redis/blob/6.2/00-RELEASENOTES), +[7.0](https://github.com/redis/redis/blob/7.0/00-RELEASENOTES) and +[7.2](https://github.com/redis/redis/blob/7.2/00-RELEASENOTES). + +The table below highlights version compatibility of the most-recent library versions and Redis versions. Compatibility means communication features, and Redis command capabilities. + + +| Jedis version | Supported Redis versions | JDK Compatibility | +|---------------|--------------------------------|-------------------| +| 3.9+ | 5.0 and 6.2 Family of releases | 8, 11 | +| >= 4.0 | Version 5.0 to current | 8, 11, 17 | +| >= 5.0 | Version 6.0 to current | 8, 11, 17 | ## Getting started @@ -31,7 +54,7 @@ To get started with Jedis, first add it as a dependency in your Java project. If redis.clients jedis - 4.3.0 + 5.0.0 ``` @@ -67,7 +90,7 @@ for the complete list of supported commands. ### Easier way of using connection pool -Using a *try-with-resources* block for each command may be cumbursome, so you may consider using JedisPooled. +Using a *try-with-resources* block for each command may be cumbersome, so you may consider using JedisPooled. ```java JedisPooled jedis = new JedisPooled("localhost", 6379); @@ -104,24 +127,44 @@ Jedis includes support for [Redis modules](https://redis.io/docs/modules/) such See the [RedisJSON Jedis](docs/redisjson.md) or [RediSearch Jedis](docs/redisearch.md) for details. +## Failover + +Jedis supports retry and failover for your Redis deployments. This is useful when: + +1. You have more than one Redis deployment. This might include two independent Redis servers or two or more Redis databases replicated across multiple [active-active Redis Enterprise](https://docs.redis.com/latest/rs/databases/active-active/) clusters. +2. You want your application to connect to one deployment at a time and to fail over to the next available deployment if the first deployment becomes unavailable. + +For the complete failover configuration options and examples, see the [Jedis failover docs](docs/failover.md). + ## Documentation The [Jedis wiki](http://github.com/redis/jedis/wiki) contains several useful articles for using Jedis. You can also check the [latest Jedis Javadocs](https://www.javadoc.io/doc/redis.clients/jedis/latest/index.html). +Some specific use-case examples can be found in [`redis.clients.jedis.examples` +package](src/test/java/redis/clients/jedis/examples/) of the test source codes. + ## Troubleshooting If you run into trouble or have any questions, we're here to help! -Hit us up on the [Redis Discord Server](http://discord.gg/redis) or [open an issue on GitHub](https://github.com/redis/jedis). +Hit us up on the [Redis Discord Server](http://discord.gg/redis) or +[Jedis GitHub Discussions](https://github.com/redis/jedis/discussions) or +[Jedis mailing list](http://groups.google.com/group/jedis_redis). -You can also find help on the [Jedis mailing list](http://groups.google.com/group/jedis_redis) or the -[GitHub Discussions](https://github.com/redis/jedis/discussions). +## Contributing + +We'd love your contributions! + +Bug reports are always welcome! [You can open a bug report on GitHub](https://github.com/redis/jedis/issues/new). + +You can also contribute documentation -- or anything to improve Jedis. Please see +[contribution guideline](https://github.com/redis/jedis/blob/master/.github/CONTRIBUTING.md) for more details. ## License -Jedis is licensed under the [MIT license](https://github.com/redis/jedis/blob/master/LICENSE.txt). +Jedis is licensed under the [MIT license](https://github.com/redis/jedis/blob/master/LICENSE). ## Sponsorship diff --git a/docs/3to4-primitives.md b/docs/3to4-primitives.md index ebda28ee25..76049f34ea 100644 --- a/docs/3to4-primitives.md +++ b/docs/3to4-primitives.md @@ -1,5 +1,5 @@ -## The following methods now return primitive values (`long`/`boolean`/`double` -instead of `Long`/`Boolean`/`Double`): +## The following methods now return primitive values: +\>> `long`/`boolean`/`double` instead of `Long`/`Boolean`/`Double`: - dbSize() - lastsave() diff --git a/docs/3to4.md b/docs/3to4.md index 58a8247531..af1df0158e 100644 --- a/docs/3to4.md +++ b/docs/3to4.md @@ -1,4 +1,4 @@ -# Jedis 3 to Jedis 4 Breaking Changes +# Jedis 4 Breaking Changes - The `BinaryJedis` and `BinaryJedisCluster` classes have been removed. diff --git a/docs/breaking-5.md b/docs/breaking-5.md new file mode 100644 index 0000000000..4a013c3800 --- /dev/null +++ b/docs/breaking-5.md @@ -0,0 +1,161 @@ +# Jedis 5 Breaking Changes + +- All variants of `blmpop` and `bzmpop` methods now take `double timeout` parameter instead of `long timeout` parameter. + This is breaking ONLY IF you are using `Long` for timeout. + +- `Reducer` abstract class is refactored: + - **`Reducer(String field)` constructor is removed; `Reducer(String name, String field)` constructor is added.** + - **`Reducer(String name)` constructor is added; it will cause runtime error with older `Reducer(String field)` constructor.** + - `getName` method is removed. + - `getAlias` method is removed. + - `setAlias` method is removed; use `as` method. + - `setAliasAsField` method is removed. + - `getOwnArgs` method is now abstract. + - `getArgs` method is removed. + +- `quit()` method has been removed from `Connection` and `ServerCommands` interface and implementations. + +- `updatePassword(String password)` method has been removed from `JedisClientConfig` and implementations. + +- `setPassword(String password)` method has been removed from both `JedisFactory` and `ConnectionFactory` classes. + +- Both `bzpopmax(double timeout, String... keys)` and `bzpopmin(double timeout, String... keys)` now return `KeyValue` (instead of `KeyedZSetElement`). + +- Both `bzpopmax(double timeout, byte[]... keys)` and `bzpopmin(double timeout, byte[]... keys)` now return `KeyValue` (instead of `List`). + +- Following methods now return `KeyValue` instead of `KeyedListElement`: + - `blpop(double timeout, String key)` + - `blpop(double timeout, String... keys)` + - `brpop(double timeout, String key)` + - `brpop(double timeout, String... keys)` + +- Following methods now return `KeyValue` instead of `List`: + - `blpop(double timeout, byte[]... keys)` + - `brpop(double timeout, byte[]... keys)` + +- `zdiff(String... keys)` method now returns `List` (instead of `Set`). +- `zdiff(byte[]... keys)` method now returns `List` (instead of `Set`). +- Both `zdiffWithScores(String... keys)` and `zdiffWithScores(byte[]... keys)` methods now return `List` (instead of `Set`). + +- `zinter(ZParams params, String... keys)` method now returns `List` (instead of `Set`). +- `zinter(ZParams params, byte[]... keys)` method now returns `List` (instead of `Set`). +- Both `zinterWithScores(ZParams params, String... keys)` and `zinterWithScores(ZParams params, byte[]... keys)` methods now return `List` (instead of `Set`). + +- `zunion(ZParams params, String... keys)` method now returns `List` (instead of `Set`). +- `zunion(ZParams params, byte[]... keys)` method now returns `List` (instead of `Set`). +- Both `zunionWithScores(ZParams params, String... keys)` and `zunionWithScores(ZParams params, byte[]... keys)` methods now return `List` (instead of `Set`). + +- Both `configGet(String pattern)` and `configGet(String... patterns)` methods now return `Map` instead of `List`. +- Both `configGet(byte[] pattern)` and `configGet(byte[]... patterns)` methods now return `Map` instead of `List`. + +- New `aclDelUser(String... names)` method replaces `aclDelUser(String name)` and `aclDelUser(String name, String... names)` methods. +- New `aclDelUser(byte[]... names)` method replaces `aclDelUser(byte[] name)` and `aclDelUser(byte[] name, byte[]... names)` methods. + +- `tsMGet(TSMGetParams multiGetParams, String... filters)` method now returns `Map` instead of `List>`. + +- Following methods now return `Map` instead of `List`: + - `tsMRange(long fromTimestamp, long toTimestamp, String... filters)` + - `tsMRange(TSMRangeParams multiRangeParams)` + - `tsMRevRange(long fromTimestamp, long toTimestamp, String... filters)` + - `tsMRevRange(TSMRangeParams multiRangeParams)` + +- `jsonNumIncrBy(String key, Path2 path, double value)` method now returns `Object` instead of `JSONArray`. + - The returning object would still be JSONArray for all previous cases. So simple type casting is enough to handle this change. + - The returning object will be `List` when running under RESP3 protocol. + +- `getAgeSeconds()` in `AccessControlLogEntry` now returns `Double` instead of `String`. + +- Both `ftConfigGet(String option)` and `ftConfigGet(String indexName, String option)` methods now return `Map` instead of `Map`. + +- `ftList()` method now returns `Set` instead of `List`. + +- `graphSlowlog(String graphName)` now returns `List>` (instead of `List>`). + +- `CommandListFilterByParams` now throws `IllegalArgumentException` (instead of `JedisDataException`) in case of unfulfilling filter. + +- `FailoverParams` now throws `IllegalArgumentException` (instead of `IllegalStateException`) in case of unfulfilling optional arguments. + +- `XPendingParams` now throws `IllegalArgumentException` (instead of `IllegalStateException`) in case of unfulfilling optional arguments. + +- `get()` option has been removed from `SetParams`. Following methods have been added in Jedis/UnifiedJedis for convenience: + - `setGet(String key, String value)` method has been added in `StringCommands` interface. + - `setGet(byte[] key, byte[] value)` method has been added in `StringBinaryCommands` interface. + +- `xpending(String key, String groupName, StreamEntryID start, StreamEntryID end, int count, String consumerName)` method has been removed from everywhere. + - Use `xpending(java.lang.String, java.lang.String, redis.clients.jedis.params.XPendingParams)` instead. + +- `xpending(byte[] key, byte[] groupName, byte[] start, byte[] end, int count, byte[] consumerName)` method has been removed from everywhere. + - Use `xpending(byte[], byte[], redis.clients.jedis.params.XPendingParams)` instead. + +- `retentionTime(long retentionTime)` method in `TSAlterParams` has been removed. Use `retention(long)` method instead. + +- Following classes have been removed: + - `KeyedZSetElement` + - `KeyedListElement` + - `TSKeyValue` + - `TSKeyedElements` + - `Limit` + +- Following BuilderFactory implementations have been removed: + - `BYTE_ARRAY` (use `BINARY`) + - `BYTE_ARRAY_LIST` (use `BINARY_LIST`) + - `BINARY_MAP_FROM_PAIRS` + - `STRING_ORDERED_SET` + +- All _payload_ related parameters are removed from _search_ related classes; namely `Document`, `IndexDefinition`, `Query`. + +- `topkCount(String key, String... items)` method has been removed from everywhere. + +- Following methods supporting JSON.RESP command have been removed: + - `jsonResp(String key)` + - `jsonResp(String key, Path path)` + - `jsonResp(String key, Path2 path)` + +- `RedisJsonCommands` and `RedisJsonPipelineCommands` interfaces have been moved into `redis.clients.jedis.json.commands` package. + +- `AbortedTransactionException` is removed. + +- `Queable` class is removed. + +- `Params` abstract class is removed. + - `toString()` support used by its sub-classes is now unavailable. + +- `getParams()` method is removed from `SortingParams` class. + +- Both `SEARCH_AGGREGATION_RESULT` and `SEARCH_AGGREGATION_RESULT_WITH_CURSOR` implementations from `SearchBuilderFactory` class have been moved to `AggregationResult` class. + +- All `AggregationResult` constructors have been made `private`. + +- `getArgs()`, `getArgsString()` and `serializeRedisArgs(List redisArgs)` methods have been removed from `AggregationBuilder`. + +- `totalResults` variable in `AggregationResult` has been made private. Use `getTotalResults()` method instead. + +- `getArgs()` and `limit(Limit limit)` methods have been removed from `Group` class. + +- `addCommandEncodedArguments` and `addCommandBinaryArguments` methods have been removed from `FieldName` class. + +- `addObjects(int[] ints)` method has been removed from `CommandArguments`. + +- Following methods have been removed: + - `strAlgoLCSStrings(String strA, String strB, StrAlgoLCSParams params)` + - `strAlgoLCSStrings(byte[] strA, byte[] strB, StrAlgoLCSParams params)` + - `strAlgoLCSKeys(String keyA, String keyB, StrAlgoLCSParams params)` + - `strAlgoLCSKeys(byte[] keyA, byte[] keyB, StrAlgoLCSParams params)` + +- `StrAlgoLCSParams` class has been removed. + +- Following methods have been removed from all Pipeline classes: + - `ftCursorRead(String indexName, long cursorId, int count)` + - `ftCursorDel(String indexName, long cursorId)` + - `ftDropIndex(String indexName)` + - `ftDropIndexDD(String indexName)` + - `ftAliasAdd(String aliasName, String indexName)` + - `ftAliasUpdate(String aliasName, String indexName)` + - `ftAliasDel(String aliasName)` + +- `JedisSentineled(String masterName, Set sentinels, JedisClientConfig masterClientConfig, JedisClientConfig sentinelClientConfig)` and +`JedisSentineled(String masterName, Set sentinels, GenericObjectPoolConfig poolConfig, JedisClientConfig masterClientConfig, JedisClientConfig sentinelClientConfig)` +constructors have been removed. + +- `JedisClusterInfoCache(JedisClientConfig clientConfig)` and `JedisClusterInfoCache(JedisClientConfig clientConfig, GenericObjectPoolConfig poolConfig)` +constructors have been removed. diff --git a/docs/failover.md b/docs/failover.md new file mode 100644 index 0000000000..8414e41376 --- /dev/null +++ b/docs/failover.md @@ -0,0 +1,225 @@ +# Failover with Jedis + +Jedis supports failover for your Redis deployments. This is useful when: +1. You have more than one Redis deployment. This might include two independent Redis servers or two or more Redis databases replicated across multiple [active-active Redis Enterprise](https://docs.redis.com/latest/rs/databases/active-active/) clusters. +2. You want your application to connect to and use one deployment at a time. +3. You want your application to fail over to the next available deployment if the current deployment becomes unavailable. + +Jedis will fail over to a subsequent Redis deployment after reaching a configurable failure threshold. +This failure threshold is implemented using a [circuit breaker pattern](https://en.wikipedia.org/wiki/Circuit_breaker_design_pattern). + +You can also configure Jedis to retry failed calls to Redis. +Once a maximum number of retries have been exhausted, the circuit breaker will record a failure. +When the circuit breaker reaches its failure threshold, a failover will be triggered on the subsequent operation. + +The remainder of this guide describes: + +* A basic failover configuration +* Supported retry and circuit breaker settings +* Failback and the cluster selection API + +We recommend that you read this guide carefully and understand the configuration settings before enabling Jedis failover +in production. + +## Basic usage + +To configure Jedis for failover, you specify an ordered list of Redis databases. +By default, Jedis will connect to the first Redis database in the list. If the first database becomes unavailable, +Jedis will attempt to connect to the next database in the list, and so on. + +Suppose you run two Redis deployments. +We'll call them `redis-east` and `redis-west`. +You want your application to first connect to `redis-east`. +If `redis-east` becomes unavailable, you want your application to connect to `redis-west`. + +Let's look at one way of configuring Jedis for this scenario. + +First, create an array of `ClusterConfig` objects, one for each Redis database. + +```java +JedisClientConfig config = DefaultJedisClientConfig.builder().user("cache").password("secret").build(); + +ClusterConfig[] clientConfigs = new ClusterConfig[2]; +clientConfigs[0] = new ClusterConfig(new HostAndPort("redis-east.example.com", 14000), config); +clientConfigs[1] = new ClusterConfig(new HostAndPort("redis-west.example.com", 14000), config); +``` + +The configuration above represents your two Redis deployments: `redis-east` and `redis-west`. +You'll use this array of configuration objects to create a connection provider that supports failover. + +Use the `MultiClusterClientConfig` builder to set your preferred retry and failover configuration, passing in the client configs you just created. +Then build a `MultiClusterPooledConnectionProvider`. + +```java +MultiClusterClientConfig.Builder builder = new MultiClusterClientConfig.Builder(clientConfigs); +builder.circuitBreakerSlidingWindowSize(10); +builder.circuitBreakerSlidingWindowMinCalls(1); +builder.circuitBreakerFailureRateThreshold(50.0f); + +MultiClusterPooledConnectionProvider provider = new MultiClusterPooledConnectionProvider(builder.build()); +``` + +Internally, the connection provider uses a [highly configurable circuit breaker and retry implementation](https://resilience4j.readme.io/docs/circuitbreaker) to determine when to fail over. +In the configuration here, we've set a sliding window size of 10 and a failure rate threshold of 50%. +This means that a failover will be triggered if 5 out of any 10 calls to Redis fail. + +Once you've configured and created a `MultiClusterPooledConnectionProvider`, instantiate a `UnifiedJedis` instance for your application, passing in the provider you just created: + +```java +UnifiedJedis jedis = new UnifiedJedis(provider); +``` + +You can now use this `UnifiedJedis` instance, and the connection management and failover will be handled transparently. + +## Configuration options + +Under the hood, Jedis' failover support relies on [resilience4j](https://resilience4j.readme.io/docs/getting-started), +a fault-tolerance library that implements [retry](https://resilience4j.readme.io/docs/retry) and [circuit breakers](https://resilience4j.readme.io/docs/circuitbreaker). + +Once you configure Jedis for failover using the `MultiClusterPooledConnectionProvider`, each call to Redis is decorated with a resilience4j retry and circuit breaker. + +By default, any call that throws a `JedisConnectionException` will be retried up to 3 times. +If the call continues to fail after the maximum number of retry attempts, then the circuit breaker will record a failure. + +The circuit breaker maintains a record of failures in a sliding window data structure. +If the failure rate reaches a configured threshold (e.g., when 50% of the last 10 calls have failed), +then the circuit breaker's state transitions from `CLOSED` to `OPEN`. +When this occurs, Jedis will attempt to connect to the next Redis database in its client configuration list. + +The supported retry and circuit breaker settings, and their default values, are described below. +You can configure any of these settings using the `MultiClusterClientConfig.Builder` builder. +Refer the basic usage above for an example of this. + +### Retry configuration + +Jedis uses the following retry settings: + +| Setting | Default value | Description | +|----------------------------------|----------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Max retry attempts | 3 | Maximum number of retry attempts (including the initial call) | +| Retry wait duration | 500 ms | Number of milliseconds to wait between retry attempts | +| Wait duration backoff multiplier | 2 | Exponential backoff factor multiplied against wait duration between retries. For example, with a wait duration of 1 second and a multiplier of 2, the retries would occur after 1s, 2s, 4s, 8s, 16s, and so on. | +| Retry included exception list | `JedisConnectionException` | A list of `Throwable` classes that count as failures and should be retried. | +| Retry ignored exception list | Empty list | A list of `Throwable` classes to explicitly ignore for the purposes of retry. | + +To disable retry, set `maxRetryAttempts` to 1. + +### Circuit breaker configuration + +Jedis uses the following circuit breaker settings: + +| Setting | Default value | Description | +|-----------------------------------------|----------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Sliding window type | `COUNT_BASED` | The type of sliding window used to record the outcome of calls. Options are `COUNT_BASED` and `TIME_BASED`. | +| Sliding window size | 100 | The size of the sliding window. Units depend on sliding window type. When `COUNT_BASED`, the size represents number of calls. When `TIME_BASED`, the size represents seconds. | +| Sliding window min calls | 100 | Minimum number of calls required (per sliding window period) before the CircuitBreaker will start calculating the error rate or slow call rate. | +| Failure rate threshold | `50.0f` | Percentage of calls within the sliding window that must fail before the circuit breaker transitions to the `OPEN` state. | +| Slow call duration threshold | 60000 ms | Duration threshold above which calls are classified as slow and added to the sliding window. | +| Slow call rate threshold | `100.0f` | Percentage of calls within the sliding window that exceed the slow call duration threshold before circuit breaker transitions to the `OPEN` state. | +| Circuit breaker included exception list | `JedisConnectionException` | A list of `Throwable` classes that count as failures and add to the failure rate. | +| Circuit breaker ignored exception list | Empty list | A list of `Throwable` classes to explicitly ignore for failure rate calculations. | | + +### Failover callbacks + +In the event that Jedis fails over, you may wish to take some action. This might include logging a warning, recording +a metric, or externally persisting the cluster connection state, to name just a few examples. For this reason, +`MultiPooledConnectionProvider` lets you register a custom callback that will be called whenever Jedis +fails over to a new cluster. + +To use this feature, you'll need to design a class that implements `java.util.function.Consumer`. +This class must implement the `accept` method, as you can see below. + +```java +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.function.Consumer; + +public class FailoverReporter implements Consumer { + + @Override + public void accept(String clusterName) { + Logger logger = LoggerFactory.getLogger(FailoverReporter.class); + logger.warn("Jedis failover to cluster: " + clusterName); + } +} +``` + +You can then pass an instance of this class to your `MultiPooledConnectionProvider`. + +``` +FailoverReporter reporter = new FailoverReporter(); +provider.setClusterFailoverPostProcessor(reporter); +``` + +The provider will call your `accept` whenever a faoliver occurs. + +## Failing back + +We believe that failback should not be automatic. +If Jedis fails over to a new cluster, Jedis will _not_ automatically fail back to the cluster that it was previously connected to. +This design prevents a scenario in which Jedis fails back to a cluster that may not be entirely healthy yet. + +That said, we do provide an API that you can use to implement automated failback when this is appropriate for your application. + +## Failback scenario + +When a failover is triggered, Jedis will attempt to connect to the next Redis server in the list of server configurations +you provide at setup. + +For example, recall the `redis-east` and `redis-west` deployments from the basic usage example above. +Jedis will attempt to connect to `redis-east` first. +If `redis-east` becomes unavailable (and the circuit breaker transitions), then Jedis will attempt to use `redis-west`. + +Now suppose that `redis-east` eventually comes back online. +You will likely want to fail your application back to `redis-east`. +However, Jedis will not fail back to `redis-east` automatically. + +In this case, we recommend that you first ensure that your `redis-east` deployment is healthy before you fail back your application. + +## Failback behavior and cluster selection API + +Once you've determined that it's safe to fail back to a previously-unavailable cluster, +you need to decide how to trigger the failback. There are two ways to accomplish this: + +1. Use the cluster selection API +2. Restart your application + +### Fail back using the cluster selection API + +`MultiClusterPooledConnectionProvider` exposes a method that you can use to manually select which cluster Jedis should use. +To select a different cluster to use, pass the cluster's numeric index to `setActiveMultiClusterIndex()`. + +The cluster's index is a 1-based index derived from its position in the client configuration. +For example, suppose you configure Jedis with the following client configs: + +``` +ClusterConfig[] clientConfigs = new ClusterConfig[2]; +clientConfigs[0] = new ClusterConfig(new HostAndPort("redis-east.example.com", 14000), config); +clientConfigs[1] = new ClusterConfig(new HostAndPort("redis-west.example.com", 14000), config); +``` + +In this case, `redis-east` will have an index of `1`, and `redis-west` will have an index of `2`. +To select and fail back to `redis-east`, you would call the function like so: + +``` +provider.setActiveMultiClusterIndex(1); +``` + +This method is thread-safe. + +If you decide to implement manual failback, you will need a way for external systems to trigger this method in your +application. For example, if your application exposes a REST API, you might consider creating a REST endpoint +to call `setActiveMultiClusterIndex` and fail back the application. + +### Fail back by restarting the application + +When your application starts, Jedis will attempt to connect to each cluster in the order that the clusters appear +in your client configuration. It's important to understand this, especially in the case where Jedis has failed over. +If Jedis has failed over to a new cluster, then restarting the application may result in an inadvertent failback. +This can happen only if a failed cluster comes back online and the application subsequently restarts. + +If you need to avoid this scenario, consider using a failover callback, as described above, to externally record +the name of the cluster that your application was most recently connected to. You can then check this state on startup +to ensure that you application only connects to the most recently used cluster. For assistance with this technique, +[start a discussion](https://github.com/redis/jedis/discussions/new?category=q-a). diff --git a/docs/jedis-maven.md b/docs/jedis-maven.md index 1c5b0f2598..6466b1ef3a 100644 --- a/docs/jedis-maven.md +++ b/docs/jedis-maven.md @@ -6,7 +6,7 @@ redis.clients jedis - 4.3.0 + 5.0.0 ``` @@ -28,7 +28,7 @@ and redis.clients jedis - 4.4.0-SNAPSHOT + 5.1.0-SNAPSHOT ``` diff --git a/pom.xml b/pom.xml index 836a5ae662..e2d0183a05 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ jar redis.clients jedis - 4.4.0-SNAPSHOT + 5.2.0-SNAPSHOT Jedis Jedis is a blazingly small and sane Redis java client. https://github.com/redis/jedis @@ -19,7 +19,7 @@ Jedis Mailing List jedis_redis@googlegroups.com - http://groups.google.com/group/jedis_redis + https://groups.google.com/group/jedis_redis @@ -27,14 +27,14 @@ MIT - http://github.com/redis/jedis/raw/master/LICENSE.txt + https://github.com/redis/jedis/blob/master/LICENSE repo github - http://github.com/redis/jedis/issues + https://github.com/redis/jedis/issues @@ -46,8 +46,11 @@ github - 1.7.36 redis.clients.jedis + 1.7.36 + 1.7.1 + 2.16.0 + 3.2.3 @@ -59,12 +62,12 @@ org.apache.commons commons-pool2 - 2.11.1 + 2.12.0 org.json json - 20220924 + 20231013 com.google.code.gson @@ -72,6 +75,22 @@ 2.10.1 + + + com.kohlschutter.junixsocket + junixsocket-core + 2.8.3 + pom + test + + + + org.locationtech.jts + jts-core + 1.19.0 + test + + junit junit @@ -80,8 +99,8 @@ org.hamcrest - hamcrest-library - 1.3 + hamcrest + 2.2 test @@ -91,18 +110,43 @@ test - com.kohlschutter.junixsocket - junixsocket-core - 2.6.1 - pom + org.mockito + mockito-inline + 4.11.0 test - org.mockito - mockito-inline - 3.12.4 + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} test + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson.version} + test + + + + + io.github.resilience4j + resilience4j-all + ${resilience4j.version} + true + + + io.github.resilience4j + resilience4j-circuitbreaker + ${resilience4j.version} + true + + + io.github.resilience4j + resilience4j-retry + ${resilience4j.version} + true + @@ -117,11 +161,17 @@ + + + src/main/resources + true + + org.jacoco jacoco-maven-plugin - 0.8.5 + 0.8.11 @@ -139,7 +189,7 @@ maven-compiler-plugin - 3.10.1 + 3.11.0 1.8 1.8 @@ -147,17 +197,20 @@ maven-surefire-plugin - 2.22.2 + ${maven.surefire.version} ${redis-hosts} + + **/examples/*Example.java + maven-source-plugin - 3.2.1 + 3.3.0 true @@ -172,7 +225,7 @@ maven-javadoc-plugin - 3.4.1 + 3.6.3 8 false @@ -190,7 +243,7 @@ maven-release-plugin - 2.5.3 + 3.0.1 org.sonatype.plugins @@ -226,7 +279,7 @@ org.apache.felix maven-bundle-plugin - 5.1.8 + 5.1.9 bundle-manifest @@ -247,7 +300,7 @@ maven-gpg-plugin - 3.0.1 + 3.1.0 --pinentry-mode @@ -267,5 +320,19 @@ + + doctests + + + + maven-surefire-plugin + ${maven.surefire.version} + + **/examples/*Example.java + + + + + diff --git a/src/main/java/redis/clients/jedis/AbstractPipeline.java b/src/main/java/redis/clients/jedis/AbstractPipeline.java new file mode 100644 index 0000000000..f4eb0335dc --- /dev/null +++ b/src/main/java/redis/clients/jedis/AbstractPipeline.java @@ -0,0 +1,26 @@ +package redis.clients.jedis; + +import java.io.Closeable; + +public abstract class AbstractPipeline extends PipeliningBase implements Closeable { + + protected AbstractPipeline(CommandObjects commandObjects) { + super(commandObjects); + } + + @Override + public abstract void close(); + + /** + * Synchronize pipeline by reading all responses. + */ + public abstract void sync(); + + public Response publish(String channel, String message) { + return appendCommand(commandObjects.publish(channel, message)); + } + + public Response publish(byte[] channel, byte[] message) { + return appendCommand(commandObjects.publish(channel, message)); + } +} diff --git a/src/main/java/redis/clients/jedis/AbstractTransaction.java b/src/main/java/redis/clients/jedis/AbstractTransaction.java new file mode 100644 index 0000000000..ed6f397caa --- /dev/null +++ b/src/main/java/redis/clients/jedis/AbstractTransaction.java @@ -0,0 +1,35 @@ +package redis.clients.jedis; + +import java.io.Closeable; +import java.util.List; + +public abstract class AbstractTransaction extends PipeliningBase implements Closeable { + + protected AbstractTransaction() { + super(new CommandObjects()); + } + + public abstract void multi(); + + /** + * Must be called before {@link AbstractTransaction#multi() MULTI}. + */ + public abstract String watch(final String... keys); + + /** + * Must be called before {@link AbstractTransaction#multi() MULTI}. + */ + public abstract String watch(final byte[]... keys); + + public abstract String unwatch(); + + @Override public abstract void close(); + + public abstract List exec(); + + public abstract String discard(); + + public Response waitReplicas(int replicas, long timeout) { + return appendCommand(commandObjects.waitReplicas(replicas, timeout)); + } +} diff --git a/src/main/java/redis/clients/jedis/BinaryJedisPubSub.java b/src/main/java/redis/clients/jedis/BinaryJedisPubSub.java index e7c8f9f1b4..96123256c6 100644 --- a/src/main/java/redis/clients/jedis/BinaryJedisPubSub.java +++ b/src/main/java/redis/clients/jedis/BinaryJedisPubSub.java @@ -1,147 +1,9 @@ package redis.clients.jedis; -import static redis.clients.jedis.Protocol.ResponseKeyword.*; +public abstract class BinaryJedisPubSub extends JedisPubSubBase { -import java.util.Arrays; -import java.util.List; - -import redis.clients.jedis.Protocol.Command; -import redis.clients.jedis.exceptions.JedisException; - -public abstract class BinaryJedisPubSub { - private int subscribedChannels = 0; - private Connection client; - - public void onMessage(byte[] channel, byte[] message) { - } - - public void onPMessage(byte[] pattern, byte[] channel, byte[] message) { - } - - public void onSubscribe(byte[] channel, int subscribedChannels) { - } - - public void onUnsubscribe(byte[] channel, int subscribedChannels) { - } - - public void onPUnsubscribe(byte[] pattern, int subscribedChannels) { - } - - public void onPSubscribe(byte[] pattern, int subscribedChannels) { - } - - public void onPong(byte[] pattern) { - } - - public void unsubscribe() { - client.sendCommand(Command.UNSUBSCRIBE); - client.flush(); - } - - public void unsubscribe(byte[]... channels) { - client.sendCommand(Command.UNSUBSCRIBE, channels); - client.flush(); - } - - public void subscribe(byte[]... channels) { - client.sendCommand(Command.SUBSCRIBE, channels); - client.flush(); - } - - public void psubscribe(byte[]... patterns) { - client.sendCommand(Command.PSUBSCRIBE, patterns); - client.flush(); - } - - public void punsubscribe() { - client.sendCommand(Command.PUNSUBSCRIBE); - client.flush(); - } - - public void punsubscribe(byte[]... patterns) { - client.sendCommand(Command.PUNSUBSCRIBE, patterns); - client.flush(); - } - - public void ping() { - client.sendCommand(Command.PING); - client.flush(); - } - - public void ping(byte[] argument) { - client.sendCommand(Command.PING, argument); - client.flush(); - } - - public boolean isSubscribed() { - return subscribedChannels > 0; - } - - public void proceedWithPatterns(Connection client, byte[]... patterns) { - this.client = client; - this.client.setTimeoutInfinite(); - try { - psubscribe(patterns); - process(); - } finally { - this.client.rollbackTimeout(); - } - } - - public void proceed(Connection client, byte[]... channels) { - this.client = client; - this.client.setTimeoutInfinite(); - try { - subscribe(channels); - process(); - } finally { - this.client.rollbackTimeout(); - } - } - - private void process() { - do { - List reply = client.getUnflushedObjectMultiBulkReply(); - final Object firstObj = reply.get(0); - if (!(firstObj instanceof byte[])) { - throw new JedisException("Unknown message type: " + firstObj); - } - final byte[] resp = (byte[]) firstObj; - if (Arrays.equals(SUBSCRIBE.getRaw(), resp)) { - subscribedChannels = ((Long) reply.get(2)).intValue(); - final byte[] bchannel = (byte[]) reply.get(1); - onSubscribe(bchannel, subscribedChannels); - } else if (Arrays.equals(UNSUBSCRIBE.getRaw(), resp)) { - subscribedChannels = ((Long) reply.get(2)).intValue(); - final byte[] bchannel = (byte[]) reply.get(1); - onUnsubscribe(bchannel, subscribedChannels); - } else if (Arrays.equals(MESSAGE.getRaw(), resp)) { - final byte[] bchannel = (byte[]) reply.get(1); - final byte[] bmesg = (byte[]) reply.get(2); - onMessage(bchannel, bmesg); - } else if (Arrays.equals(PMESSAGE.getRaw(), resp)) { - final byte[] bpattern = (byte[]) reply.get(1); - final byte[] bchannel = (byte[]) reply.get(2); - final byte[] bmesg = (byte[]) reply.get(3); - onPMessage(bpattern, bchannel, bmesg); - } else if (Arrays.equals(PSUBSCRIBE.getRaw(), resp)) { - subscribedChannels = ((Long) reply.get(2)).intValue(); - final byte[] bpattern = (byte[]) reply.get(1); - onPSubscribe(bpattern, subscribedChannels); - } else if (Arrays.equals(PUNSUBSCRIBE.getRaw(), resp)) { - subscribedChannels = ((Long) reply.get(2)).intValue(); - final byte[] bpattern = (byte[]) reply.get(1); - onPUnsubscribe(bpattern, subscribedChannels); - } else if (Arrays.equals(PONG.getRaw(), resp)) { - final byte[] bpattern = (byte[]) reply.get(1); - onPong(bpattern); - } else { - throw new JedisException("Unknown message type: " + firstObj); - } - } while (isSubscribed()); - } - - public int getSubscribedChannels() { - return subscribedChannels; + @Override + protected final byte[] encode(byte[] raw) { + return raw; } } diff --git a/src/main/java/redis/clients/jedis/BinaryJedisShardedPubSub.java b/src/main/java/redis/clients/jedis/BinaryJedisShardedPubSub.java new file mode 100644 index 0000000000..2d67974914 --- /dev/null +++ b/src/main/java/redis/clients/jedis/BinaryJedisShardedPubSub.java @@ -0,0 +1,9 @@ +package redis.clients.jedis; + +public abstract class BinaryJedisShardedPubSub extends JedisShardedPubSubBase { + + @Override + protected final byte[] encode(byte[] raw) { + return raw; + } +} diff --git a/src/main/java/redis/clients/jedis/BroadcastResponse.java b/src/main/java/redis/clients/jedis/BroadcastResponse.java deleted file mode 100644 index 481d7fa63c..0000000000 --- a/src/main/java/redis/clients/jedis/BroadcastResponse.java +++ /dev/null @@ -1,28 +0,0 @@ -package redis.clients.jedis; - -import java.util.function.Supplier; - -/** - * Represents the response from a single node in broadcast mode. - */ -public class BroadcastResponse implements Supplier { - - private T response = null; - private RuntimeException exception = null; - - public BroadcastResponse(T response) { - this.response = response; - } - - public BroadcastResponse(RuntimeException exception) { - this.exception = exception; - } - - @Override - public T get() { - if (exception != null) { - throw exception; - } - return response; - } -} diff --git a/src/main/java/redis/clients/jedis/BuilderFactory.java b/src/main/java/redis/clients/jedis/BuilderFactory.java index 1f62f4bd26..c7349f3e89 100644 --- a/src/main/java/redis/clients/jedis/BuilderFactory.java +++ b/src/main/java/redis/clients/jedis/BuilderFactory.java @@ -4,17 +4,10 @@ import java.util.*; import java.util.stream.Collectors; -import redis.clients.jedis.exceptions.JedisException; -import redis.clients.jedis.resps.StreamConsumerFullInfo; -import redis.clients.jedis.resps.StreamFullInfo; -import redis.clients.jedis.resps.StreamGroupFullInfo; +import redis.clients.jedis.exceptions.JedisDataException; +import redis.clients.jedis.resps.*; import redis.clients.jedis.resps.LCSMatchResult.MatchedPosition; import redis.clients.jedis.resps.LCSMatchResult.Position; -import redis.clients.jedis.resps.*; -import redis.clients.jedis.search.aggr.AggregationResult; -import redis.clients.jedis.timeseries.TSKeyedElements; -import redis.clients.jedis.timeseries.TSElement; -import redis.clients.jedis.timeseries.TSKeyValue; import redis.clients.jedis.util.DoublePrecision; import redis.clients.jedis.util.JedisByteHashMap; import redis.clients.jedis.util.KeyValue; @@ -70,19 +63,6 @@ public String toString() { } }; - public static final Builder> ENCODED_OBJECT_MAP = new Builder>() { - @Override - public Map build(Object data) { - final List list = (List) data; - final Map map = new HashMap<>(list.size() / 2, 1f); - final Iterator iterator = list.iterator(); - while (iterator.hasNext()) { - map.put(STRING.build(iterator.next()), ENCODED_OBJECT.build(iterator.next())); - } - return map; - } - }; - public static final Builder LONG = new Builder() { @Override public Long build(Object data) { @@ -116,7 +96,9 @@ public String toString() { public static final Builder DOUBLE = new Builder() { @Override public Double build(Object data) { - return DoublePrecision.parseFloatingPointNumber(STRING.build(data)); + if (data == null) return null; + else if (data instanceof Double) return (Double) data; + else return DoublePrecision.parseFloatingPointNumber(STRING.build(data)); } @Override @@ -129,15 +111,8 @@ public String toString() { @Override @SuppressWarnings("unchecked") public List build(Object data) { - if (null == data) { - return null; - } - List values = (List) data; - List doubles = new ArrayList<>(values.size()); - for (byte[] value : values) { - doubles.add(DOUBLE.build(value)); - } - return doubles; + if (null == data) return null; + return ((List) data).stream().map(DOUBLE::build).collect(Collectors.toList()); } @Override @@ -150,6 +125,7 @@ public String toString() { @Override public Boolean build(Object data) { if (data == null) return null; + else if (data instanceof Boolean) return (Boolean) data; return ((Long) data) == 1L; } @@ -163,15 +139,8 @@ public String toString() { @Override @SuppressWarnings("unchecked") public List build(Object data) { - if (null == data) { - return null; - } - List longs = (List) data; - List booleans = new ArrayList<>(longs.size()); - for (Long value : longs) { - booleans.add(value == null ? null : value == 1L); - } - return booleans; + if (null == data) return null; + return ((List) data).stream().map(BOOLEAN::build).collect(Collectors.toList()); } @Override @@ -184,24 +153,11 @@ public String toString() { @Override @SuppressWarnings("unchecked") public List build(Object data) { - if (null == data) { - return null; - } - List longs = (List) data; - List booleans = new ArrayList<>(longs.size()); - for (Object value : longs) { - Boolean bool = null; - if (value != null && value instanceof Long) { - long longValue = (Long) value; - if (longValue == 1L) { - bool = Boolean.TRUE; - } else if (longValue == 0L) { - bool = Boolean.FALSE; - } - } - booleans.add(bool); - } - return booleans; + if (null == data) return null; + return ((List) data).stream() + //.map((val) -> (val instanceof JedisDataException) ? val : BOOLEAN.build(val)) + .map((val) -> (val instanceof JedisDataException) ? null : BOOLEAN.build(val)) + .collect(Collectors.toList()); } @Override @@ -210,34 +166,6 @@ public String toString() { } }; - public static final Builder BYTE_ARRAY = new Builder() { - @Override - public byte[] build(Object data) { - return ((byte[]) data); - } - - @Override - public String toString() { - return "byte[]"; - } - }; - - public static final Builder> BYTE_ARRAY_LIST = new Builder>() { - @Override - @SuppressWarnings("unchecked") - public List build(Object data) { - if (null == data) { - return null; - } - return (List) data; - } - - @Override - public String toString() { - return "List"; - } - }; - public static final Builder BINARY = new Builder() { @Override public byte[] build(Object data) { @@ -280,23 +208,45 @@ public String toString() { } }; - public static final Builder> BINARY_MAP = new Builder>() { + public static final Builder>> BINARY_PAIR_LIST + = new Builder>>() { @Override @SuppressWarnings("unchecked") - public Map build(Object data) { + public List> build(Object data) { final List flatHash = (List) data; - final Map hash = new JedisByteHashMap(); + final List> pairList = new ArrayList<>(); final Iterator iterator = flatHash.iterator(); while (iterator.hasNext()) { - hash.put(iterator.next(), iterator.next()); + pairList.add(new AbstractMap.SimpleEntry<>(iterator.next(), iterator.next())); } - return hash; + return pairList; } @Override public String toString() { - return "Map"; + return "List>"; + } + }; + + public static final Builder>> BINARY_PAIR_LIST_FROM_PAIRS + = new Builder>>() { + @Override + @SuppressWarnings("unchecked") + public List> build(Object data) { + final List list = (List) data; + final List> pairList = new ArrayList<>(); + for (Object object : list) { + final List flat = (List) object; + pairList.add(new AbstractMap.SimpleEntry<>(flat.get(0), flat.get(1))); + } + + return pairList; + } + + @Override + public String toString() { + return "List>"; } }; @@ -340,17 +290,34 @@ public String toString() { } }; - public static final Builder> STRING_ORDERED_SET = new Builder>() { + public static final Builder> BINARY_MAP = new Builder>() { @Override @SuppressWarnings("unchecked") - public Set build(Object data) { - if (null == data) return null; - return ((List) data).stream().map(STRING::build).collect(Collectors.toCollection(LinkedHashSet::new)); + public Map build(Object data) { + final List list = (List) data; + if (list.isEmpty()) return Collections.emptyMap(); + + if (list.get(0) instanceof KeyValue) { + final Map map = new JedisByteHashMap(); + final Iterator iterator = list.iterator(); + while (iterator.hasNext()) { + KeyValue kv = (KeyValue) iterator.next(); + map.put(BINARY.build(kv.getKey()), BINARY.build(kv.getValue())); + } + return map; + } else { + final Map map = new JedisByteHashMap(); + final Iterator iterator = list.iterator(); + while (iterator.hasNext()) { + map.put(BINARY.build(iterator.next()), BINARY.build(iterator.next())); + } + return map; + } } @Override public String toString() { - return "Set"; + return "Map"; } }; @@ -358,34 +325,201 @@ public String toString() { @Override @SuppressWarnings("unchecked") public Map build(Object data) { + final List list = (List) data; + if (list.isEmpty()) return Collections.emptyMap(); + + if (list.get(0) instanceof KeyValue) { + final Map map = new HashMap<>(list.size(), 1f); + final Iterator iterator = list.iterator(); + while (iterator.hasNext()) { + KeyValue kv = (KeyValue) iterator.next(); + map.put(STRING.build(kv.getKey()), STRING.build(kv.getValue())); + } + return map; + } else { + final Map map = new HashMap<>(list.size() / 2, 1f); + final Iterator iterator = list.iterator(); + while (iterator.hasNext()) { + map.put(STRING.build(iterator.next()), STRING.build(iterator.next())); + } + return map; + } + } + + @Override + public String toString() { + return "Map"; + } + }; + + public static final Builder> ENCODED_OBJECT_MAP = new Builder>() { + @Override + public Map build(Object data) { + if (data == null) return null; + final List list = (List) data; + if (list.isEmpty()) return Collections.emptyMap(); + + if (list.get(0) instanceof KeyValue) { + final Map map = new HashMap<>(list.size(), 1f); + final Iterator iterator = list.iterator(); + while (iterator.hasNext()) { + KeyValue kv = (KeyValue) iterator.next(); + map.put(STRING.build(kv.getKey()), ENCODED_OBJECT.build(kv.getValue())); + } + return map; + } else { + final Map map = new HashMap<>(list.size() / 2, 1f); + final Iterator iterator = list.iterator(); + while (iterator.hasNext()) { + map.put(STRING.build(iterator.next()), ENCODED_OBJECT.build(iterator.next())); + } + return map; + } + } + }; + + public static final Builder AGGRESSIVE_ENCODED_OBJECT = new Builder() { + @Override + public Object build(Object data) { + if (data == null) return null; + + if (data instanceof List) { + final List list = (List) data; + if (list.isEmpty()) return Collections.emptyMap(); + + if (list.get(0) instanceof KeyValue) { + return ((List) data).stream() + .filter(kv -> kv != null && kv.getKey() != null && kv.getValue() != null) + .collect(Collectors.toMap(kv -> STRING.build(kv.getKey()), + kv -> this.build(kv.getValue()))); + } else { + return list.stream().map(this::build).collect(Collectors.toList()); + } + } else if (data instanceof byte[]) { + return STRING.build(data); + } + return data; + } + }; + + public static final Builder> AGGRESSIVE_ENCODED_OBJECT_MAP = new Builder>() { + @Override + public Map build(Object data) { + return (Map) AGGRESSIVE_ENCODED_OBJECT.build(data); + } + }; + + public static final Builder>> STRING_PAIR_LIST + = new Builder>>() { + @Override + @SuppressWarnings("unchecked") + public List> build(Object data) { final List flatHash = (List) data; - final Map hash = new HashMap<>(flatHash.size() / 2, 1f); + final List> pairList = new ArrayList<>(flatHash.size() / 2); final Iterator iterator = flatHash.iterator(); while (iterator.hasNext()) { - hash.put(SafeEncoder.encode(iterator.next()), SafeEncoder.encode(iterator.next())); + pairList.add(KeyValue.of(STRING.build(iterator.next()), STRING.build(iterator.next()))); } - return hash; + return pairList; } @Override public String toString() { - return "Map"; + return "List>"; + } + }; + + public static final Builder>> STRING_PAIR_LIST_FROM_PAIRS + = new Builder>>() { + @Override + @SuppressWarnings("unchecked") + public List> build(Object data) { + return ((List) data).stream().map(o -> (List) o) + .map(l -> KeyValue.of(STRING.build(l.get(0)), STRING.build(l.get(1)))) + .collect(Collectors.toList()); + } + + @Override + public String toString() { + return "List>"; } }; - public static final Builder KEYED_LIST_ELEMENT = new Builder() { + public static final Builder> STRING_LONG_MAP = new Builder>() { @Override @SuppressWarnings("unchecked") - public KeyedListElement build(Object data) { + public Map build(Object data) { + final List list = (List) data; + if (list.isEmpty()) return Collections.emptyMap(); + + if (list.get(0) instanceof KeyValue) { + final Map map = new LinkedHashMap<>(list.size(), 1f); + final Iterator iterator = list.iterator(); + while (iterator.hasNext()) { + KeyValue kv = (KeyValue) iterator.next(); + map.put(STRING.build(kv.getKey()), LONG.build(kv.getValue())); + } + return map; + } else { + final Map map = new LinkedHashMap<>(list.size() / 2, 1f); + final Iterator iterator = list.iterator(); + while (iterator.hasNext()) { + map.put(STRING.build(iterator.next()), LONG.build(iterator.next())); + } + return map; + } + } + + @Override + public String toString() { + return "Map"; + } + }; + + public static final Builder> KEYED_ELEMENT = new Builder>() { + @Override + @SuppressWarnings("unchecked") + public KeyValue build(Object data) { if (data == null) return null; - List l = (List) data; - return new KeyedListElement(l.get(0), l.get(1)); + List l = (List) data; + return KeyValue.of(STRING.build(l.get(0)), STRING.build(l.get(1))); } @Override public String toString() { - return "KeyedListElement"; + return "KeyValue"; + } + }; + + public static final Builder> BINARY_KEYED_ELEMENT = new Builder>() { + @Override + @SuppressWarnings("unchecked") + public KeyValue build(Object data) { + if (data == null) return null; + List l = (List) data; + return KeyValue.of(BINARY.build(l.get(0)), BINARY.build(l.get(1))); + } + + @Override + public String toString() { + return "KeyValue"; + } + }; + + public static final Builder> ZRANK_WITHSCORE_PAIR = new Builder>() { + @Override + public KeyValue build(Object data) { + if (data == null) { + return null; + } + List l = (List) data; + return new KeyValue<>(LONG.build(l.get(0)), DOUBLE.build(l.get(1))); + } + + @Override + public String toString() { + return "KeyValue"; } }; @@ -405,6 +539,16 @@ public String toString() { } }; + public static final Builder> LONG_LONG_PAIR = new Builder>() { + @Override + @SuppressWarnings("unchecked") + public KeyValue build(Object data) { + if (data == null) return null; + List dataList = (List) data; + return new KeyValue<>(LONG.build(dataList.get(0)), LONG.build(dataList.get(1))); + } + }; + public static final Builder>>> KEYED_STRING_LIST_LIST = new Builder>>>() { @Override @@ -445,23 +589,39 @@ public Tuple build(Object data) { public String toString() { return "Tuple"; } + }; + public static final Builder> KEYED_TUPLE = new Builder>() { + @Override + @SuppressWarnings("unchecked") + public KeyValue build(Object data) { + List l = (List) data; // never null + if (l.isEmpty()) { + return null; + } + return KeyValue.of(STRING.build(l.get(0)), new Tuple(BINARY.build(l.get(1)), DOUBLE.build(l.get(2)))); + } + + @Override + public String toString() { + return "KeyValue"; + } }; - public static final Builder KEYED_ZSET_ELEMENT = new Builder() { + public static final Builder> BINARY_KEYED_TUPLE = new Builder>() { @Override @SuppressWarnings("unchecked") - public KeyedZSetElement build(Object data) { - List l = (List) data; // never null + public KeyValue build(Object data) { + List l = (List) data; // never null if (l.isEmpty()) { return null; } - return new KeyedZSetElement(l.get(0), l.get(1), DOUBLE.build(l.get(2))); + return KeyValue.of(BINARY.build(l.get(0)), new Tuple(BINARY.build(l.get(1)), DOUBLE.build(l.get(2)))); } @Override public String toString() { - return "KeyedZSetElement"; + return "KeyValue"; } }; @@ -487,6 +647,20 @@ public String toString() { } }; + public static final Builder> TUPLE_LIST_RESP3 = new Builder>() { + @Override + @SuppressWarnings("unchecked") + public List build(Object data) { + if (null == data) return null; + return ((List) data).stream().map(TUPLE::build).collect(Collectors.toList()); + } + + @Override + public String toString() { + return "List"; + } + }; + public static final Builder> TUPLE_ZSET = new Builder>() { @Override @SuppressWarnings("unchecked") @@ -509,14 +683,26 @@ public String toString() { } }; + public static final Builder> TUPLE_ZSET_RESP3 = new Builder>() { + @Override + @SuppressWarnings("unchecked") + public Set build(Object data) { + if (null == data) return null; + return ((List) data).stream().map(TUPLE::build).collect(Collectors.toCollection(LinkedHashSet::new)); + } + + @Override + public String toString() { + return "ZSet"; + } + }; + private static final Builder> TUPLE_LIST_FROM_PAIRS = new Builder>() { @Override @SuppressWarnings("unchecked") public List build(Object data) { if (data == null) return null; - return ((List) data).stream() - .map(o -> (List) o).map(p -> TUPLE.build(p)) - .collect(Collectors.toList()); + return ((List>) data).stream().map(TUPLE::build).collect(Collectors.toList()); } @Override @@ -763,20 +949,26 @@ public String toString() { public static final Builder> COMMAND_DOCS_RESPONSE = new Builder>() { @Override public Map build(Object data) { - if (data == null) { - return null; - } - + if (data == null) return null; List list = (List) data; - Map map = new HashMap<>(list.size() / 2, 1f); - - for (int i = 0; i < list.size();) { - String name = STRING.build(list.get(i++)); - CommandDocument doc = CommandDocument.COMMAND_DOCUMENT_BUILDER.build(list.get(i++)); - map.put(name, doc); + if (list.isEmpty()) return Collections.emptyMap(); + + if (list.get(0) instanceof KeyValue) { + final Map map = new HashMap<>(list.size(), 1f); + final Iterator iterator = list.iterator(); + while (iterator.hasNext()) { + KeyValue kv = (KeyValue) iterator.next(); + map.put(STRING.build(kv.getKey()), new CommandDocument(ENCODED_OBJECT_MAP.build(kv.getValue()))); + } + return map; + } else { + final Map map = new HashMap<>(list.size() / 2, 1f); + final Iterator iterator = list.iterator(); + while (iterator.hasNext()) { + map.put(STRING.build(iterator.next()), new CommandDocument(ENCODED_OBJECT_MAP.build(iterator.next()))); + } + return map; } - - return map; } }; @@ -805,6 +997,108 @@ public Map build(Object data) { } }; + private static final Builder>> CLUSTER_SHARD_SLOTS_RANGES = new Builder>>() { + + @Override + public List> build(Object data) { + if (null == data) { + return null; + } + + List rawSlots = (List) data; + List> slotsRanges = new ArrayList<>(); + for (int i = 0; i < rawSlots.size(); i += 2) { + slotsRanges.add(Arrays.asList(rawSlots.get(i), rawSlots.get(i + 1))); + } + return slotsRanges; + } + }; + + private static final Builder> CLUSTER_SHARD_NODE_INFO_LIST + = new Builder>() { + + final Map mappingFunctions = createDecoderMap(); + + private Map createDecoderMap() { + + Map tempMappingFunctions = new HashMap<>(); + tempMappingFunctions.put(ClusterShardNodeInfo.ID, STRING); + tempMappingFunctions.put(ClusterShardNodeInfo.ENDPOINT, STRING); + tempMappingFunctions.put(ClusterShardNodeInfo.IP, STRING); + tempMappingFunctions.put(ClusterShardNodeInfo.HOSTNAME, STRING); + tempMappingFunctions.put(ClusterShardNodeInfo.PORT, LONG); + tempMappingFunctions.put(ClusterShardNodeInfo.TLS_PORT, LONG); + tempMappingFunctions.put(ClusterShardNodeInfo.ROLE, STRING); + tempMappingFunctions.put(ClusterShardNodeInfo.REPLICATION_OFFSET, LONG); + tempMappingFunctions.put(ClusterShardNodeInfo.HEALTH, STRING); + + return tempMappingFunctions; + } + + @Override + @SuppressWarnings("unchecked") + public List build(Object data) { + if (null == data) { + return null; + } + + List response = new ArrayList<>(); + + List clusterShardNodeInfos = (List) data; + for (Object clusterShardNodeInfoObject : clusterShardNodeInfos) { + List clusterShardNodeInfo = (List) clusterShardNodeInfoObject; + Iterator iterator = clusterShardNodeInfo.iterator(); + response.add(new ClusterShardNodeInfo(createMapFromDecodingFunctions(iterator, mappingFunctions))); + } + + return response; + } + + @Override + public String toString() { + return "List"; + } + }; + + public static final Builder> CLUSTER_SHARD_INFO_LIST + = new Builder>() { + + final Map mappingFunctions = createDecoderMap(); + + private Map createDecoderMap() { + + Map tempMappingFunctions = new HashMap<>(); + tempMappingFunctions.put(ClusterShardInfo.SLOTS, CLUSTER_SHARD_SLOTS_RANGES); + tempMappingFunctions.put(ClusterShardInfo.NODES, CLUSTER_SHARD_NODE_INFO_LIST); + + return tempMappingFunctions; + } + + @Override + @SuppressWarnings("unchecked") + public List build(Object data) { + if (null == data) { + return null; + } + + List response = new ArrayList<>(); + + List clusterShardInfos = (List) data; + for (Object clusterShardInfoObject : clusterShardInfos) { + List clusterShardInfo = (List) clusterShardInfoObject; + Iterator iterator = clusterShardInfo.iterator(); + response.add(new ClusterShardInfo(createMapFromDecodingFunctions(iterator, mappingFunctions))); + } + + return response; + } + + @Override + public String toString() { + return "List"; + } + }; + public static final Builder> MODULE_LIST = new Builder>() { @Override public List build(Object data) { @@ -820,6 +1114,11 @@ public List build(Object data) { } for (List moduleResp : objectList) { + if (moduleResp.get(0) instanceof KeyValue) { + responses.add(new Module(STRING.build(((KeyValue) moduleResp.get(0)).getValue()), + LONG.build(((KeyValue) moduleResp.get(1)).getValue()).intValue())); + continue; + } Module m = new Module(SafeEncoder.encode((byte[]) moduleResp.get(1)), ((Long) moduleResp.get(3)).intValue()); responses.add(m); @@ -838,80 +1137,24 @@ public String toString() { * Create a AccessControlUser object from the ACL GETUSER reply. */ public static final Builder ACCESS_CONTROL_USER = new Builder() { - @SuppressWarnings("unchecked") @Override public AccessControlUser build(Object data) { - if (data == null) { - return null; - } - - List objectList = (List) data; - if (objectList.isEmpty()) { - return null; - } - - AccessControlUser accessControlUser = new AccessControlUser(); - - // flags - List flags = (List) objectList.get(1); - for (Object f : flags) { - accessControlUser.addFlag(SafeEncoder.encode((byte[]) f)); - } - - // passwords - List passwords = (List) objectList.get(3); - for (Object p : passwords) { - accessControlUser.addPassword(SafeEncoder.encode((byte[]) p)); - } - - // commands - accessControlUser.setCommands(SafeEncoder.encode((byte[]) objectList.get(5))); - - // Redis 7 --> - boolean withSelectors = objectList.size() >= 12; - if (!withSelectors) { - - // keys - List keys = (List) objectList.get(7); - for (Object k : keys) { - accessControlUser.addKey(SafeEncoder.encode((byte[]) k)); - } - - // Redis 6.2 --> - // channels - if (objectList.size() >= 10) { - List channels = (List) objectList.get(9); - for (Object channel : channels) { - accessControlUser.addChannel(SafeEncoder.encode((byte[]) channel)); - } - } - - } else { - // TODO: Proper implementation of ACL V2. - - // keys - accessControlUser.addKeys(SafeEncoder.encode((byte[]) objectList.get(7))); - - // channels - accessControlUser.addChannels(SafeEncoder.encode((byte[]) objectList.get(9))); - } - - // selectors - // TODO: Proper implementation of ACL V2. - return accessControlUser; + Map map = ENCODED_OBJECT_MAP.build(data); + if (map == null) return null; + return new AccessControlUser(map); } @Override public String toString() { return "AccessControlUser"; } - }; /** * Create an Access Control Log Entry Result of ACL LOG command */ - public static final Builder> ACCESS_CONTROL_LOG_ENTRY_LIST = new Builder>() { + public static final Builder> ACCESS_CONTROL_LOG_ENTRY_LIST + = new Builder>() { private final Map mappingFunctions = createDecoderMap(); @@ -923,8 +1166,11 @@ private Map createDecoderMap() { tempMappingFunctions.put(AccessControlLogEntry.CONTEXT, STRING); tempMappingFunctions.put(AccessControlLogEntry.OBJECT, STRING); tempMappingFunctions.put(AccessControlLogEntry.USERNAME, STRING); - tempMappingFunctions.put(AccessControlLogEntry.AGE_SECONDS, STRING); + tempMappingFunctions.put(AccessControlLogEntry.AGE_SECONDS, DOUBLE); tempMappingFunctions.put(AccessControlLogEntry.CLIENT_INFO, STRING); + tempMappingFunctions.put(AccessControlLogEntry.ENTRY_ID, LONG); + tempMappingFunctions.put(AccessControlLogEntry.TIMESTAMP_CREATED, LONG); + tempMappingFunctions.put(AccessControlLogEntry.TIMESTAMP_LAST_UPDATED, LONG); return tempMappingFunctions; } @@ -941,7 +1187,8 @@ public List build(Object data) { for (List logEntryData : logEntries) { Iterator logEntryDataIterator = logEntryData.iterator(); AccessControlLogEntry accessControlLogEntry = new AccessControlLogEntry( - createMapFromDecodingFunctions(logEntryDataIterator, mappingFunctions)); + createMapFromDecodingFunctions(logEntryDataIterator, mappingFunctions, + BACKUP_BUILDERS_FOR_DECODING_FUNCTIONS)); list.add(accessControlLogEntry); } return list; @@ -1084,7 +1331,7 @@ public String toString() { } }; - public static final Builder>> STREAM_AUTO_CLAIM_ID_RESPONSE + public static final Builder>> STREAM_AUTO_CLAIM_JUSTID_RESPONSE = new Builder>>() { @Override @SuppressWarnings("unchecked") @@ -1104,24 +1351,36 @@ public String toString() { } }; + /** + * @deprecated Use {@link BuilderFactory#STREAM_AUTO_CLAIM_JUSTID_RESPONSE}. + */ + @Deprecated + public static final Builder>> STREAM_AUTO_CLAIM_ID_RESPONSE + = STREAM_AUTO_CLAIM_JUSTID_RESPONSE; + public static final Builder>>> STREAM_READ_RESPONSE = new Builder>>>() { @Override public List>> build(Object data) { - if (data == null) { - return null; - } - List streams = (List) data; - - List>> result = new ArrayList<>(streams.size()); - for (Object streamObj : streams) { - List stream = (List) streamObj; - String streamId = SafeEncoder.encode((byte[]) stream.get(0)); - List streamEntries = BuilderFactory.STREAM_ENTRY_LIST.build(stream.get(1)); - result.add(new AbstractMap.SimpleEntry<>(streamId, streamEntries)); + if (data == null) return null; + List list = (List) data; + if (list.isEmpty()) return Collections.emptyList(); + + if (list.get(0) instanceof KeyValue) { + return ((List) list).stream() + .map(kv -> new KeyValue<>(STRING.build(kv.getKey()), + STREAM_ENTRY_LIST.build(kv.getValue()))) + .collect(Collectors.toList()); + } else { + List>> result = new ArrayList<>(list.size()); + for (Object streamObj : list) { + List stream = (List) streamObj; + String streamKey = STRING.build(stream.get(0)); + List streamEntries = STREAM_ENTRY_LIST.build(stream.get(1)); + result.add(KeyValue.of(streamKey, streamEntries)); + } + return result; } - - return result; } @Override @@ -1242,7 +1501,12 @@ public String toString() { } }; - public static final Builder> STREAM_CONSUMERS_INFO_LIST = new Builder>() { + /** + * @deprecated Use {@link BuilderFactory#STREAM_CONSUMER_INFO_LIST}. + */ + @Deprecated + public static final Builder> STREAM_CONSUMERS_INFO_LIST + = new Builder>() { Map mappingFunctions = createDecoderMap(); @@ -1250,8 +1514,7 @@ private Map createDecoderMap() { Map tempMappingFunctions = new HashMap<>(); tempMappingFunctions.put(StreamConsumersInfo.NAME, STRING); tempMappingFunctions.put(StreamConsumersInfo.IDLE, LONG); - tempMappingFunctions.put(StreamGroupInfo.PENDING, LONG); - tempMappingFunctions.put(StreamGroupInfo.LAST_DELIVERED, STRING); + tempMappingFunctions.put(StreamConsumersInfo.PENDING, LONG); return tempMappingFunctions; } @@ -1288,7 +1551,53 @@ public String toString() { } }; - private static final Builder> STREAM_CONSUMER_FULL_INFO_LIST = new Builder>() { + public static final Builder> STREAM_CONSUMER_INFO_LIST + = new Builder>() { + + Map mappingFunctions = createDecoderMap(); + + private Map createDecoderMap() { + Map tempMappingFunctions = new HashMap<>(); + tempMappingFunctions.put(StreamConsumerInfo.NAME, STRING); + tempMappingFunctions.put(StreamConsumerInfo.IDLE, LONG); + tempMappingFunctions.put(StreamConsumerInfo.PENDING, LONG); + return tempMappingFunctions; + + } + + @Override + @SuppressWarnings("unchecked") + public List build(Object data) { + if (null == data) { + return null; + } + + List list = new ArrayList<>(); + List streamsEntries = (List) data; + Iterator groupsArray = streamsEntries.iterator(); + + while (groupsArray.hasNext()) { + + List groupInfo = (List) groupsArray.next(); + + Iterator consumerInfoIterator = groupInfo.iterator(); + + StreamConsumerInfo streamConsumerInfo = new StreamConsumerInfo( + createMapFromDecodingFunctions(consumerInfoIterator, mappingFunctions)); + list.add(streamConsumerInfo); + } + + return list; + } + + @Override + public String toString() { + return "List"; + } + }; + + private static final Builder> STREAM_CONSUMER_FULL_INFO_LIST + = new Builder>() { final Map mappingFunctions = createDecoderMap(); @@ -1316,7 +1625,8 @@ public List build(Object data) { for (Object streamsEntry : streamsEntries) { List consumerInfoList = (List) streamsEntry; Iterator consumerInfoIterator = consumerInfoList.iterator(); - StreamConsumerFullInfo consumerInfo = new StreamConsumerFullInfo(createMapFromDecodingFunctions(consumerInfoIterator, mappingFunctions)); + StreamConsumerFullInfo consumerInfo = new StreamConsumerFullInfo( + createMapFromDecodingFunctions(consumerInfoIterator, mappingFunctions)); list.add(consumerInfo); } return list; @@ -1328,7 +1638,8 @@ public String toString() { } }; - private static final Builder> STREAM_GROUP_FULL_INFO_LIST = new Builder>() { + private static final Builder> STREAM_GROUP_FULL_INFO_LIST + = new Builder>() { final Map mappingFunctions = createDecoderMap(); @@ -1360,8 +1671,8 @@ public List build(Object data) { Iterator groupInfoIterator = groupInfo.iterator(); - StreamGroupFullInfo groupFullInfo = new StreamGroupFullInfo(createMapFromDecodingFunctions( - groupInfoIterator, mappingFunctions)); + StreamGroupFullInfo groupFullInfo = new StreamGroupFullInfo( + createMapFromDecodingFunctions(groupInfoIterator, mappingFunctions)); list.add(groupFullInfo); } @@ -1374,7 +1685,7 @@ public String toString() { } }; - public static final Builder STREAM_INFO_FULL = new Builder() { + public static final Builder STREAM_FULL_INFO = new Builder() { final Map mappingFunctions = createDecoderMap(); @@ -1410,6 +1721,12 @@ public String toString() { } }; + /** + * @deprecated Use {@link BuilderFactory#STREAM_FULL_INFO}. + */ + @Deprecated + public static final Builder STREAM_INFO_FULL = STREAM_FULL_INFO; + public static final Builder STREAM_PENDING_SUMMARY = new Builder() { @Override @SuppressWarnings("unchecked") @@ -1436,24 +1753,46 @@ public String toString() { } }; + private static final List BACKUP_BUILDERS_FOR_DECODING_FUNCTIONS + = Arrays.asList(STRING, LONG, DOUBLE); + private static Map createMapFromDecodingFunctions(Iterator iterator, Map mappingFunctions) { + return createMapFromDecodingFunctions(iterator, mappingFunctions, null); + } + + private static Map createMapFromDecodingFunctions(Iterator iterator, + Map mappingFunctions, Collection backupBuilders) { + + if (!iterator.hasNext()) { + return Collections.emptyMap(); + } Map resultMap = new HashMap<>(); while (iterator.hasNext()) { + final Object tempObject = iterator.next(); + final String mapKey; + final Object rawValue; + + if (tempObject instanceof KeyValue) { + KeyValue kv = (KeyValue) tempObject; + mapKey = STRING.build(kv.getKey()); + rawValue = kv.getValue(); + } else { + mapKey = STRING.build(tempObject); + rawValue = iterator.next(); + } - String mapKey = STRING.build(iterator.next()); if (mappingFunctions.containsKey(mapKey)) { - resultMap.put(mapKey, mappingFunctions.get(mapKey).build(iterator.next())); + resultMap.put(mapKey, mappingFunctions.get(mapKey).build(rawValue)); } else { // For future - if we don't find an element in our builder map - Object unknownData = iterator.next(); - for (Builder b : mappingFunctions.values()) { + Collection builders = backupBuilders != null ? backupBuilders : mappingFunctions.values(); + for (Builder b : builders) { try { - resultMap.put(mapKey, b.build(unknownData)); + resultMap.put(mapKey, b.build(rawValue)); break; } catch (ClassCastException e) { // We continue with next builder - } } } @@ -1479,47 +1818,73 @@ public LCSMatchResult build(Object data) { List matchedPositions = new ArrayList<>(); List objectList = (List) data; - if ("matches".equalsIgnoreCase(STRING.build(objectList.get(0)))) { - List matches = (List)objectList.get(1); - for (Object obj : matches) { - if (obj instanceof List) { - List positions = (List) obj; - Position a = new Position( - LONG.build(((List) positions.get(0)).get(0)), - LONG.build(((List) positions.get(0)).get(1)) - ); - Position b = new Position( - LONG.build(((List) positions.get(1)).get(0)), - LONG.build(((List) positions.get(1)).get(1)) - ); - long matchLen = 0; - if (positions.size() >= 3) { - matchLen = LONG.build(positions.get(2)); - } - matchedPositions.add(new MatchedPosition(a, b, matchLen)); + if (objectList.get(0) instanceof KeyValue) { + Iterator iterator = objectList.iterator(); + while (iterator.hasNext()) { + KeyValue kv = (KeyValue) iterator.next(); + if ("matches".equalsIgnoreCase(STRING.build(kv.getKey()))) { + addMatchedPosition(matchedPositions, kv.getValue()); + } else if ("len".equalsIgnoreCase(STRING.build(kv.getKey()))) { + len = LONG.build(kv.getValue()); + } + } + } else { + for (int i = 0; i < objectList.size(); i += 2) { + if ("matches".equalsIgnoreCase(STRING.build(objectList.get(i)))) { + addMatchedPosition(matchedPositions, objectList.get(i + 1)); + } else if ("len".equalsIgnoreCase(STRING.build(objectList.get(i)))) { + len = LONG.build(objectList.get(i + 1)); } } } - if ("len".equalsIgnoreCase(STRING.build(objectList.get(2)))) { - len = LONG.build(objectList.get(3)); - } return new LCSMatchResult(matchedPositions, len); } } + + private void addMatchedPosition(List matchedPositions, Object o) { + List matches = (List) o; + for (Object obj : matches) { + if (obj instanceof List) { + List positions = (List) obj; + Position a = new Position( + LONG.build(((List) positions.get(0)).get(0)), + LONG.build(((List) positions.get(0)).get(1)) + ); + Position b = new Position( + LONG.build(((List) positions.get(1)).get(0)), + LONG.build(((List) positions.get(1)).get(1)) + ); + long matchLen = 0; + if (positions.size() >= 3) { + matchLen = LONG.build(positions.get(2)); + } + matchedPositions.add(new MatchedPosition(a, b, matchLen)); + } + } + } }; public static final Builder> STRING_MAP_FROM_PAIRS = new Builder>() { @Override @SuppressWarnings("unchecked") public Map build(Object data) { - final List list = (List) data; + final List list = (List) data; + if (list.isEmpty()) return Collections.emptyMap(); + + if (list.get(0) instanceof KeyValue) { + return ((List) list).stream() + .collect(Collectors.toMap(kv -> STRING.build(kv.getKey()), + kv -> STRING.build(kv.getValue()))); + } + final Map map = new HashMap<>(list.size()); for (Object object : list) { - final List flat = (List) object; - map.put(SafeEncoder.encode(flat.get(0)), flat.get(1) != null ? SafeEncoder.encode(flat.get(1)) : null); + if (object == null) continue; + final List flat = (List) object; + if (flat.isEmpty()) continue; + map.put(STRING.build(flat.get(0)), STRING.build(flat.get(1))); } - return map; } @@ -1529,14 +1894,41 @@ public String toString() { } }; - public static final Builder> LIBRARY_LIST = new Builder>() { + public static final Builder> ENCODED_OBJECT_MAP_FROM_PAIRS = new Builder>() { @Override - public List build(Object data) { - List list = (List) data; - return list.stream().map(o -> LibraryInfo.LIBRARY_BUILDER.build(o)).collect(Collectors.toList()); + @SuppressWarnings("unchecked") + public Map build(Object data) { + final List list = (List) data; + if (list.isEmpty()) return Collections.emptyMap(); + + if (list.get(0) instanceof KeyValue) { + return ((List) list).stream() + .collect(Collectors.toMap(kv -> STRING.build(kv.getKey()), + kv -> ENCODED_OBJECT.build(kv.getValue()))); + } + + final Map map = new HashMap<>(list.size()); + for (Object object : list) { + if (object == null) continue; + final List flat = (List) object; + if (flat.isEmpty()) continue; + map.put(STRING.build(flat.get(0)), STRING.build(flat.get(1))); + } + return map; + } + + @Override + public String toString() { + return "Map"; } }; + /** + * @deprecated Use {@link LibraryInfo#LIBRARY_INFO_LIST}. + */ + @Deprecated + public static final Builder> LIBRARY_LIST = LibraryInfo.LIBRARY_INFO_LIST; + public static final Builder>> STRING_LIST_LIST = new Builder>>() { @Override @SuppressWarnings("unchecked") @@ -1674,5 +2066,4 @@ protected static SetFromList of(List list) { private BuilderFactory() { throw new InstantiationError("Must not instantiate this class"); } - } diff --git a/src/main/java/redis/clients/jedis/ClientSetInfoConfig.java b/src/main/java/redis/clients/jedis/ClientSetInfoConfig.java new file mode 100644 index 0000000000..c1d804b28a --- /dev/null +++ b/src/main/java/redis/clients/jedis/ClientSetInfoConfig.java @@ -0,0 +1,70 @@ +package redis.clients.jedis; + +import java.util.Arrays; +import java.util.HashSet; +import redis.clients.jedis.exceptions.JedisValidationException; + +public final class ClientSetInfoConfig { + + private final boolean disabled; + + private final String libNameSuffix; + + public ClientSetInfoConfig() { + this(false, null); + } + + public ClientSetInfoConfig(boolean disabled) { + this(disabled, null); + } + + /** + * @param libNameSuffix must not have braces ({@code ()[]{}}) and spaces will be replaced with hyphens + */ + public ClientSetInfoConfig(String libNameSuffix) { + this(false, libNameSuffix); + } + + private ClientSetInfoConfig(boolean disabled, String libNameSuffix) { + this.disabled = disabled; + this.libNameSuffix = validateLibNameSuffix(libNameSuffix); + } + + private static final HashSet BRACES = new HashSet<>(Arrays.asList('(', ')', '[', ']', '{', '}')); + + private static String validateLibNameSuffix(String suffix) { + if (suffix == null || suffix.trim().isEmpty()) { + return null; + } + + for (int i = 0; i < suffix.length(); i++) { + char c = suffix.charAt(i); + if (c < ' ' || c > '~' || BRACES.contains(c)) { + throw new JedisValidationException("lib-name suffix cannot contain braces, newlines or " + + "special characters."); + } + } + + return suffix.replaceAll("\\s", "-"); + } + + public final boolean isDisabled() { + return disabled; + } + + public final String getLibNameSuffix() { + return libNameSuffix; + } + + public static final ClientSetInfoConfig DEFAULT = new ClientSetInfoConfig(); + + public static final ClientSetInfoConfig DISABLED = new ClientSetInfoConfig(true); + + /** + * @param suffix must not have braces ({@code ()[]{}}) and spaces will be replaced with hyphens + * @return config + */ + public static ClientSetInfoConfig withLibNameSuffix(String suffix) { + return new ClientSetInfoConfig(suffix); + } +} diff --git a/src/main/java/redis/clients/jedis/ClusterCommandObjects.java b/src/main/java/redis/clients/jedis/ClusterCommandObjects.java index 7e2e026c79..02cec4c3fd 100644 --- a/src/main/java/redis/clients/jedis/ClusterCommandObjects.java +++ b/src/main/java/redis/clients/jedis/ClusterCommandObjects.java @@ -4,20 +4,13 @@ import static redis.clients.jedis.Protocol.Command.SCAN; import static redis.clients.jedis.Protocol.Keyword.TYPE; -import java.util.List; -import java.util.Map; import java.util.Set; import redis.clients.jedis.commands.ProtocolCommand; import redis.clients.jedis.params.ScanParams; import redis.clients.jedis.resps.ScanResult; -import redis.clients.jedis.search.IndexOptions; -import redis.clients.jedis.search.Query; -import redis.clients.jedis.search.Schema; -import redis.clients.jedis.search.SearchResult; -import redis.clients.jedis.search.aggr.AggregationBuilder; -import redis.clients.jedis.search.aggr.AggregationResult; import redis.clients.jedis.util.JedisClusterHashTag; +import redis.clients.jedis.util.KeyValue; public class ClusterCommandObjects extends CommandObjects { @@ -106,126 +99,9 @@ public final CommandObject waitReplicas(int replicas, long timeout) { throw new UnsupportedOperationException(CLUSTER_UNSUPPORTED_MESSAGE); } - // RediSearch commands - // TODO: Send RediSearch command to random 'master' node or random hashslot. -// boolean searchLite = false; - - private CommandObject processSearchCommand(String indexName, CommandObject command) { -// if (searchLite) command.getArguments().processKey(indexName); - command.getArguments().processKey(indexName); - return command; - } - - @Override - public final CommandObject ftCreate(String indexName, IndexOptions indexOptions, Schema schema) { - return processSearchCommand(indexName, super.ftCreate(indexName, indexOptions, schema)); - } - - @Override - public final CommandObject ftAlter(String indexName, Schema schema) { - return processSearchCommand(indexName, super.ftAlter(indexName, schema)); - } - - @Override - public final CommandObject ftSearch(String indexName, Query query) { - return processSearchCommand(indexName, super.ftSearch(indexName, query)); - } - - @Override - public final CommandObject ftSearch(byte[] indexName, Query query) { - CommandObject command = super.ftSearch(indexName, query); -// if (searchLite) command.getArguments().processKey(indexName); - command.getArguments().processKey(indexName); - return command; - } - - @Override - public CommandObject ftExplain(String indexName, Query query) { - return processSearchCommand(indexName, super.ftExplain(indexName, query)); - } - - @Override - public CommandObject> ftExplainCLI(String indexName, Query query) { - return processSearchCommand(indexName, super.ftExplainCLI(indexName, query)); - } - - @Override - public CommandObject ftAggregate(String indexName, AggregationBuilder aggr) { - return processSearchCommand(indexName, super.ftAggregate(indexName, aggr)); - } - - @Override - public CommandObject ftCursorRead(String indexName, long cursorId, int count) { - return processSearchCommand(indexName, super.ftCursorRead(indexName, cursorId, count)); - } - - @Override - public CommandObject ftCursorDel(String indexName, long cursorId) { - return processSearchCommand(indexName, super.ftCursorDel(indexName, cursorId)); - } - @Override - public CommandObject ftDropIndex(String indexName) { - return processSearchCommand(indexName, super.ftDropIndex(indexName)); - } - - @Override - public CommandObject ftDropIndexDD(String indexName) { - return processSearchCommand(indexName, super.ftDropIndexDD(indexName)); - } - - @Override - public CommandObject ftSynUpdate(String indexName, String synonymGroupId, String... terms) { - return processSearchCommand(indexName, super.ftSynUpdate(indexName, synonymGroupId, terms)); - } - - @Override - public CommandObject>> ftSynDump(String indexName) { - return processSearchCommand(indexName, super.ftSynDump(indexName)); - } - - @Override - public CommandObject> ftInfo(String indexName) { - return processSearchCommand(indexName, super.ftInfo(indexName)); - } - - @Override - public CommandObject> ftTagVals(String indexName, String fieldName) { - return processSearchCommand(indexName, super.ftTagVals(indexName, fieldName)); - } - - @Override - public CommandObject ftAliasAdd(String aliasName, String indexName) { -// CommandObject command = super.ftAliasAdd(aliasName, indexName); -// if (searchLite) command.getArguments().processKey(aliasName).processKey(indexName); -// return command; - return processSearchCommand(indexName, super.ftAliasAdd(aliasName, indexName)); - } - - @Override - public CommandObject ftAliasUpdate(String aliasName, String indexName) { -// CommandObject command = super.ftAliasUpdate(aliasName, indexName); -// if (searchLite) command.getArguments().processKey(aliasName).processKey(indexName); -// return command; - return processSearchCommand(indexName, super.ftAliasUpdate(aliasName, indexName)); - } - - @Override - public CommandObject ftAliasDel(String aliasName) { -// CommandObject command = super.ftAliasDel(aliasName); -// if (searchLite) command.getArguments().processKey(aliasName); -// return command; - return processSearchCommand(aliasName, super.ftAliasDel(aliasName)); - } - - @Override - public CommandObject> ftConfigGet(String indexName, String option) { - return processSearchCommand(indexName, super.ftConfigGet(indexName, option)); + public CommandObject> waitAOF(long numLocal, long numReplicas, long timeout) { + throw new UnsupportedOperationException(CLUSTER_UNSUPPORTED_MESSAGE); } - @Override - public CommandObject ftConfigSet(String indexName, String option, String value) { - return processSearchCommand(indexName, super.ftConfigSet(indexName, option, value)); - } - // RediSearch commands } diff --git a/src/main/java/redis/clients/jedis/ClusterPipeline.java b/src/main/java/redis/clients/jedis/ClusterPipeline.java index 90194f0c18..0c850c8ed8 100644 --- a/src/main/java/redis/clients/jedis/ClusterPipeline.java +++ b/src/main/java/redis/clients/jedis/ClusterPipeline.java @@ -1,5 +1,6 @@ package redis.clients.jedis; +import java.time.Duration; import java.util.Set; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import redis.clients.jedis.providers.ClusterConnectionProvider; @@ -11,21 +12,40 @@ public class ClusterPipeline extends MultiNodePipelineBase { private AutoCloseable closeable = null; public ClusterPipeline(Set clusterNodes, JedisClientConfig clientConfig) { - this(new ClusterConnectionProvider(clusterNodes, clientConfig)); + this(new ClusterConnectionProvider(clusterNodes, clientConfig), + createClusterCommandObjects(clientConfig.getRedisProtocol())); this.closeable = this.provider; } public ClusterPipeline(Set clusterNodes, JedisClientConfig clientConfig, GenericObjectPoolConfig poolConfig) { - this(new ClusterConnectionProvider(clusterNodes, clientConfig, poolConfig)); + this(new ClusterConnectionProvider(clusterNodes, clientConfig, poolConfig), + createClusterCommandObjects(clientConfig.getRedisProtocol())); + this.closeable = this.provider; + } + + public ClusterPipeline(Set clusterNodes, JedisClientConfig clientConfig, + GenericObjectPoolConfig poolConfig, Duration topologyRefreshPeriod) { + this(new ClusterConnectionProvider(clusterNodes, clientConfig, poolConfig, topologyRefreshPeriod), + createClusterCommandObjects(clientConfig.getRedisProtocol())); this.closeable = this.provider; } public ClusterPipeline(ClusterConnectionProvider provider) { - super(new ClusterCommandObjects()); + this(provider, new ClusterCommandObjects()); + } + + public ClusterPipeline(ClusterConnectionProvider provider, ClusterCommandObjects commandObjects) { + super(commandObjects); this.provider = provider; } + private static ClusterCommandObjects createClusterCommandObjects(RedisProtocol protocol) { + ClusterCommandObjects cco = new ClusterCommandObjects(); + if (protocol == RedisProtocol.RESP3) cco.setProtocol(protocol); + return cco; + } + @Override public void close() { try { diff --git a/src/main/java/redis/clients/jedis/CommandArguments.java b/src/main/java/redis/clients/jedis/CommandArguments.java index f8d1b6ab44..b9190245ce 100644 --- a/src/main/java/redis/clients/jedis/CommandArguments.java +++ b/src/main/java/redis/clients/jedis/CommandArguments.java @@ -3,10 +3,12 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; + import redis.clients.jedis.args.Rawable; import redis.clients.jedis.args.RawableFactory; import redis.clients.jedis.commands.ProtocolCommand; import redis.clients.jedis.params.IParams; +import redis.clients.jedis.search.RediSearchUtil; public class CommandArguments implements Iterable { @@ -28,18 +30,26 @@ public ProtocolCommand getCommand() { } public CommandArguments add(Object arg) { - if (arg instanceof Rawable) { + if (arg == null) { + throw new IllegalArgumentException("null is not a valid argument."); + } else if (arg instanceof Rawable) { args.add((Rawable) arg); } else if (arg instanceof byte[]) { args.add(RawableFactory.from((byte[]) arg)); + } else if (arg instanceof Integer) { + args.add(RawableFactory.from((Integer) arg)); + } else if (arg instanceof Double) { + args.add(RawableFactory.from((Double) arg)); + } else if (arg instanceof Boolean) { + args.add(RawableFactory.from((Boolean) arg ? 1 : 0)); + } else if (arg instanceof float[]) { + args.add(RawableFactory.from(RediSearchUtil.toByteArray((float[]) arg))); } else if (arg instanceof String) { args.add(RawableFactory.from((String) arg)); - } else if (arg instanceof Boolean) { - args.add(RawableFactory.from(Integer.toString((Boolean) arg ? 1 : 0))); + } else if (arg instanceof GeoCoordinate) { + GeoCoordinate geo = (GeoCoordinate) arg; + args.add(RawableFactory.from(geo.getLongitude() + "," + geo.getLatitude())); } else { - if (arg == null) { - throw new IllegalArgumentException("null is not a valid argument."); - } args.add(RawableFactory.from(String.valueOf(arg))); } return this; @@ -57,14 +67,6 @@ public CommandArguments addObjects(Collection args) { return this; } - @Deprecated - public CommandArguments addObjects(int[] ints) { - for (int i : ints) { - add(i); - } - return this; - } - public CommandArguments key(Object key) { if (key instanceof Rawable) { Rawable raw = (Rawable) key; @@ -91,6 +93,11 @@ public final CommandArguments keys(Object... keys) { return this; } + public final CommandArguments keys(Collection keys) { + keys.forEach(key -> key(key)); + return this; + } + public final CommandArguments addParams(IParams params) { params.addParams(this); return this; diff --git a/src/main/java/redis/clients/jedis/CommandObjects.java b/src/main/java/redis/clients/jedis/CommandObjects.java index c24d97724a..da773d5782 100644 --- a/src/main/java/redis/clients/jedis/CommandObjects.java +++ b/src/main/java/redis/clients/jedis/CommandObjects.java @@ -3,10 +3,9 @@ import static redis.clients.jedis.Protocol.Command.*; import static redis.clients.jedis.Protocol.Keyword.*; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Supplier; import java.util.stream.Collectors; import org.json.JSONArray; import org.json.JSONObject; @@ -17,9 +16,14 @@ import redis.clients.jedis.bloom.*; import redis.clients.jedis.bloom.RedisBloomProtocol.*; import redis.clients.jedis.commands.ProtocolCommand; +import redis.clients.jedis.gears.*; +import redis.clients.jedis.gears.RedisGearsProtocol.*; +import redis.clients.jedis.gears.resps.GearsLibraryInfo; import redis.clients.jedis.graph.GraphProtocol.*; import redis.clients.jedis.json.*; import redis.clients.jedis.json.JsonProtocol.JsonCommand; +import redis.clients.jedis.json.DefaultGsonObjectMapper; +import redis.clients.jedis.json.JsonObjectMapper; import redis.clients.jedis.params.*; import redis.clients.jedis.resps.*; import redis.clients.jedis.search.*; @@ -34,10 +38,53 @@ public class CommandObjects { + private RedisProtocol protocol; + + // TODO: restrict? + public final void setProtocol(RedisProtocol proto) { + this.protocol = proto; + } + + // TODO: remove? + protected RedisProtocol getProtocol() { + return protocol; + } + + private volatile JsonObjectMapper jsonObjectMapper; + private final AtomicInteger searchDialect = new AtomicInteger(0); + + private JedisBroadcastAndRoundRobinConfig broadcastAndRoundRobinConfig = null; + + void setBroadcastAndRoundRobinConfig(JedisBroadcastAndRoundRobinConfig config) { + this.broadcastAndRoundRobinConfig = config; + } + protected CommandArguments commandArguments(ProtocolCommand command) { return new CommandArguments(command); } + private final CommandObject PING_COMMAND_OBJECT = new CommandObject<>(commandArguments(PING), BuilderFactory.STRING); + + public final CommandObject ping() { + return PING_COMMAND_OBJECT; + } + + private final CommandObject FLUSHALL_COMMAND_OBJECT = new CommandObject<>(commandArguments(FLUSHALL), BuilderFactory.STRING); + + public final CommandObject flushAll() { + return FLUSHALL_COMMAND_OBJECT; + } + + private final CommandObject FLUSHDB_COMMAND_OBJECT = new CommandObject<>(commandArguments(FLUSHDB), BuilderFactory.STRING); + + public final CommandObject flushDB() { + return FLUSHDB_COMMAND_OBJECT; + } + + public final CommandObject configSet(String parameter, String value) { + return new CommandObject<>(commandArguments(Command.CONFIG).add(Keyword.SET).add(parameter).add(value), BuilderFactory.STRING); + } + // Key commands public final CommandObject exists(String key) { return new CommandObject<>(commandArguments(Command.EXISTS).key(key), BuilderFactory.BOOLEAN); @@ -56,11 +103,11 @@ public final CommandObject exists(byte[]... keys) { } public final CommandObject persist(String key) { - return new CommandObject<>(commandArguments(PERSIST).key(key), BuilderFactory.LONG); + return new CommandObject<>(commandArguments(Command.PERSIST).key(key), BuilderFactory.LONG); } public final CommandObject persist(byte[] key) { - return new CommandObject<>(commandArguments(PERSIST).key(key), BuilderFactory.LONG); + return new CommandObject<>(commandArguments(Command.PERSIST).key(key), BuilderFactory.LONG); } public final CommandObject type(String key) { @@ -395,6 +442,10 @@ public final CommandObject get(String key) { return new CommandObject<>(commandArguments(Command.GET).key(key), BuilderFactory.STRING); } + public final CommandObject setGet(String key, String value) { + return new CommandObject<>(commandArguments(Command.SET).key(key).add(value).add(Keyword.GET), BuilderFactory.STRING); + } + public final CommandObject setGet(String key, String value, SetParams params) { return new CommandObject<>(commandArguments(Command.SET).key(key).add(value).addParams(params) .add(Keyword.GET), BuilderFactory.STRING); @@ -412,6 +463,10 @@ public final CommandObject get(byte[] key) { return new CommandObject<>(commandArguments(Command.GET).key(key), BuilderFactory.BINARY); } + public final CommandObject setGet(byte[] key, byte[] value) { + return new CommandObject<>(commandArguments(Command.SET).key(key).add(value).add(Keyword.GET), BuilderFactory.BINARY); + } + public final CommandObject setGet(byte[] key, byte[] value, SetParams params) { return new CommandObject<>(commandArguments(Command.SET).key(key).add(value).addParams(params) .add(Keyword.GET), BuilderFactory.BINARY); @@ -641,34 +696,6 @@ public final CommandObject bitop(BitOP op, byte[] destKey, byte[]... srcKe return new CommandObject<>(commandArguments(BITOP).add(op).key(destKey).keys((Object[]) srcKeys), BuilderFactory.LONG); } - /** - * @param keyA - * @param keyB - * @param params - * @return - * @deprecated STRALGO LCS command will be removed from Redis 7. - * LCS can be used instead of this method. - */ - @Deprecated - public final CommandObject strAlgoLCSKeys(String keyA, String keyB, StrAlgoLCSParams params) { - return new CommandObject<>(commandArguments(STRALGO).add(Keyword.LCS).add(Keyword.KEYS) - .key(keyA).key(keyB).addParams(params), BuilderFactory.STR_ALGO_LCS_RESULT_BUILDER); - } - - /** - * @param keyA - * @param keyB - * @param params - * @return - * @deprecated STRALGO LCS command will be removed from Redis 7. - * LCS can be used instead of this method. - */ - @Deprecated - public final CommandObject strAlgoLCSKeys(byte[] keyA, byte[] keyB, StrAlgoLCSParams params) { - return new CommandObject<>(commandArguments(STRALGO).add(Keyword.LCS).add(Keyword.KEYS) - .key(keyA).key(keyB).addParams(params), BuilderFactory.STR_ALGO_LCS_RESULT_BUILDER); - } - public final CommandObject lcs(String keyA, String keyB, LCSParams params) { return new CommandObject<>(commandArguments(Command.LCS).key(keyA).key(keyB) .addParams(params), BuilderFactory.STR_ALGO_LCS_RESULT_BUILDER); @@ -837,20 +864,20 @@ public final CommandObject> blpop(int timeout, String... keys) { return new CommandObject<>(commandArguments(BLPOP).blocking().keys((Object[]) keys).add(timeout), BuilderFactory.STRING_LIST); } - public final CommandObject blpop(double timeout, String key) { - return new CommandObject<>(commandArguments(BLPOP).blocking().key(key).add(timeout), BuilderFactory.KEYED_LIST_ELEMENT); + public final CommandObject> blpop(double timeout, String key) { + return new CommandObject<>(commandArguments(BLPOP).blocking().key(key).add(timeout), BuilderFactory.KEYED_ELEMENT); } - public final CommandObject blpop(double timeout, String... keys) { - return new CommandObject<>(commandArguments(BLPOP).blocking().keys((Object[]) keys).add(timeout), BuilderFactory.KEYED_LIST_ELEMENT); + public final CommandObject> blpop(double timeout, String... keys) { + return new CommandObject<>(commandArguments(BLPOP).blocking().keys((Object[]) keys).add(timeout), BuilderFactory.KEYED_ELEMENT); } public final CommandObject> blpop(int timeout, byte[]... keys) { return new CommandObject<>(commandArguments(BLPOP).blocking().keys((Object[]) keys).add(timeout), BuilderFactory.BINARY_LIST); } - public final CommandObject> blpop(double timeout, byte[]... keys) { - return new CommandObject<>(commandArguments(BLPOP).blocking().keys((Object[]) keys).add(timeout), BuilderFactory.BINARY_LIST); + public final CommandObject> blpop(double timeout, byte[]... keys) { + return new CommandObject<>(commandArguments(BLPOP).blocking().keys((Object[]) keys).add(timeout), BuilderFactory.BINARY_KEYED_ELEMENT); } public final CommandObject> brpop(int timeout, String key) { @@ -861,20 +888,20 @@ public final CommandObject> brpop(int timeout, String... keys) { return new CommandObject<>(commandArguments(BRPOP).blocking().keys((Object[]) keys).add(timeout), BuilderFactory.STRING_LIST); } - public final CommandObject brpop(double timeout, String key) { - return new CommandObject<>(commandArguments(BRPOP).blocking().key(key).add(timeout), BuilderFactory.KEYED_LIST_ELEMENT); + public final CommandObject> brpop(double timeout, String key) { + return new CommandObject<>(commandArguments(BRPOP).blocking().key(key).add(timeout), BuilderFactory.KEYED_ELEMENT); } - public final CommandObject brpop(double timeout, String... keys) { - return new CommandObject<>(commandArguments(BRPOP).blocking().keys((Object[]) keys).add(timeout), BuilderFactory.KEYED_LIST_ELEMENT); + public final CommandObject> brpop(double timeout, String... keys) { + return new CommandObject<>(commandArguments(BRPOP).blocking().keys((Object[]) keys).add(timeout), BuilderFactory.KEYED_ELEMENT); } public final CommandObject> brpop(int timeout, byte[]... keys) { return new CommandObject<>(commandArguments(BRPOP).blocking().keys((Object[]) keys).add(timeout), BuilderFactory.BINARY_LIST); } - public final CommandObject> brpop(double timeout, byte[]... keys) { - return new CommandObject<>(commandArguments(BRPOP).blocking().keys((Object[]) keys).add(timeout), BuilderFactory.BINARY_LIST); + public final CommandObject> brpop(double timeout, byte[]... keys) { + return new CommandObject<>(commandArguments(BRPOP).blocking().keys((Object[]) keys).add(timeout), BuilderFactory.BINARY_KEYED_ELEMENT); } public final CommandObject rpoplpush(String srckey, String dstkey) { @@ -925,12 +952,12 @@ public final CommandObject>> lmpop(ListDirection d .add(direction).add(COUNT).add(count), BuilderFactory.KEYED_STRING_LIST); } - public final CommandObject>> blmpop(long timeout, ListDirection direction, String... keys) { + public final CommandObject>> blmpop(double timeout, ListDirection direction, String... keys) { return new CommandObject<>(commandArguments(BLMPOP).blocking().add(timeout) .add(keys.length).keys((Object[]) keys).add(direction), BuilderFactory.KEYED_STRING_LIST); } - public final CommandObject>> blmpop(long timeout, ListDirection direction, int count, String... keys) { + public final CommandObject>> blmpop(double timeout, ListDirection direction, int count, String... keys) { return new CommandObject<>(commandArguments(BLMPOP).blocking().add(timeout) .add(keys.length).keys((Object[]) keys).add(direction).add(COUNT).add(count), BuilderFactory.KEYED_STRING_LIST); @@ -946,12 +973,12 @@ public final CommandObject>> lmpop(ListDirection d .add(direction).add(COUNT).add(count), BuilderFactory.KEYED_BINARY_LIST); } - public final CommandObject>> blmpop(long timeout, ListDirection direction, byte[]... keys) { + public final CommandObject>> blmpop(double timeout, ListDirection direction, byte[]... keys) { return new CommandObject<>(commandArguments(BLMPOP).blocking().add(timeout) .add(keys.length).keys((Object[]) keys).add(direction), BuilderFactory.KEYED_BINARY_LIST); } - public final CommandObject>> blmpop(long timeout, ListDirection direction, int count, byte[]... keys) { + public final CommandObject>> blmpop(double timeout, ListDirection direction, int count, byte[]... keys) { return new CommandObject<>(commandArguments(BLMPOP).blocking().add(timeout) .add(keys.length).keys((Object[]) keys).add(direction).add(COUNT).add(count), BuilderFactory.KEYED_BINARY_LIST); @@ -1075,8 +1102,9 @@ public final CommandObject> hrandfield(String key, long count) { return new CommandObject<>(commandArguments(HRANDFIELD).key(key).add(count), BuilderFactory.STRING_LIST); } - public final CommandObject> hrandfieldWithValues(String key, long count) { - return new CommandObject<>(commandArguments(HRANDFIELD).key(key).add(count).add(WITHVALUES), BuilderFactory.STRING_MAP); + public final CommandObject>> hrandfieldWithValues(String key, long count) { + return new CommandObject<>(commandArguments(HRANDFIELD).key(key).add(count).add(WITHVALUES), + protocol != RedisProtocol.RESP3 ? BuilderFactory.STRING_PAIR_LIST : BuilderFactory.STRING_PAIR_LIST_FROM_PAIRS); } public final CommandObject> hgetAll(byte[] key) { @@ -1091,8 +1119,9 @@ public final CommandObject> hrandfield(byte[] key, long count) { return new CommandObject<>(commandArguments(HRANDFIELD).key(key).add(count), BuilderFactory.BINARY_LIST); } - public final CommandObject> hrandfieldWithValues(byte[] key, long count) { - return new CommandObject<>(commandArguments(HRANDFIELD).key(key).add(count).add(WITHVALUES), BuilderFactory.BINARY_MAP); + public final CommandObject>> hrandfieldWithValues(byte[] key, long count) { + return new CommandObject<>(commandArguments(HRANDFIELD).key(key).add(count).add(WITHVALUES), + protocol != RedisProtocol.RESP3 ? BuilderFactory.BINARY_PAIR_LIST : BuilderFactory.BINARY_PAIR_LIST_FROM_PAIRS); } public final CommandObject>> hscan(String key, String cursor, ScanParams params) { @@ -1351,6 +1380,14 @@ public final CommandObject zrevrank(String key, String member) { return new CommandObject<>(commandArguments(ZREVRANK).key(key).add(member), BuilderFactory.LONG); } + public final CommandObject> zrankWithScore(String key, String member) { + return new CommandObject<>(commandArguments(ZRANK).key(key).add(member).add(WITHSCORE), BuilderFactory.ZRANK_WITHSCORE_PAIR); + } + + public final CommandObject> zrevrankWithScore(String key, String member) { + return new CommandObject<>(commandArguments(ZREVRANK).key(key).add(member).add(WITHSCORE), BuilderFactory.ZRANK_WITHSCORE_PAIR); + } + public final CommandObject zrank(byte[] key, byte[] member) { return new CommandObject<>(commandArguments(ZRANK).key(key).add(member), BuilderFactory.LONG); } @@ -1359,6 +1396,14 @@ public final CommandObject zrevrank(byte[] key, byte[] member) { return new CommandObject<>(commandArguments(ZREVRANK).key(key).add(member), BuilderFactory.LONG); } + public final CommandObject> zrankWithScore(byte[] key, byte[] member) { + return new CommandObject<>(commandArguments(ZRANK).key(key).add(member).add(WITHSCORE), BuilderFactory.ZRANK_WITHSCORE_PAIR); + } + + public final CommandObject> zrevrankWithScore(byte[] key, byte[] member) { + return new CommandObject<>(commandArguments(ZREVRANK).key(key).add(member).add(WITHSCORE), BuilderFactory.ZRANK_WITHSCORE_PAIR); + } + public final CommandObject zrandmember(String key) { return new CommandObject<>(commandArguments(ZRANDMEMBER).key(key), BuilderFactory.STRING); } @@ -1368,7 +1413,7 @@ public final CommandObject> zrandmember(String key, long count) { } public final CommandObject> zrandmemberWithScores(String key, long count) { - return new CommandObject<>(commandArguments(ZRANDMEMBER).key(key).add(count).add(WITHSCORES), BuilderFactory.TUPLE_LIST); + return new CommandObject<>(commandArguments(ZRANDMEMBER).key(key).add(count).add(WITHSCORES), getTupleListBuilder()); } public final CommandObject zrandmember(byte[] key) { @@ -1380,7 +1425,7 @@ public final CommandObject> zrandmember(byte[] key, long count) { } public final CommandObject> zrandmemberWithScores(byte[] key, long count) { - return new CommandObject<>(commandArguments(ZRANDMEMBER).key(key).add(count).add(WITHSCORES), BuilderFactory.TUPLE_LIST); + return new CommandObject<>(commandArguments(ZRANDMEMBER).key(key).add(count).add(WITHSCORES), getTupleListBuilder()); } public final CommandObject zcard(String key) { @@ -1412,7 +1457,7 @@ public final CommandObject zpopmax(String key) { } public final CommandObject> zpopmax(String key, int count) { - return new CommandObject<>(commandArguments(ZPOPMAX).key(key).add(count), BuilderFactory.TUPLE_LIST); + return new CommandObject<>(commandArguments(ZPOPMAX).key(key).add(count), getTupleListBuilder()); } public final CommandObject zpopmin(String key) { @@ -1420,7 +1465,7 @@ public final CommandObject zpopmin(String key) { } public final CommandObject> zpopmin(String key, int count) { - return new CommandObject<>(commandArguments(ZPOPMIN).key(key).add(count), BuilderFactory.TUPLE_LIST); + return new CommandObject<>(commandArguments(ZPOPMIN).key(key).add(count), getTupleListBuilder()); } public final CommandObject zpopmax(byte[] key) { @@ -1428,7 +1473,7 @@ public final CommandObject zpopmax(byte[] key) { } public final CommandObject> zpopmax(byte[] key, int count) { - return new CommandObject<>(commandArguments(ZPOPMAX).key(key).add(count), BuilderFactory.TUPLE_LIST); + return new CommandObject<>(commandArguments(ZPOPMAX).key(key).add(count), getTupleListBuilder()); } public final CommandObject zpopmin(byte[] key) { @@ -1436,23 +1481,27 @@ public final CommandObject zpopmin(byte[] key) { } public final CommandObject> zpopmin(byte[] key, int count) { - return new CommandObject<>(commandArguments(ZPOPMIN).key(key).add(count), BuilderFactory.TUPLE_LIST); + return new CommandObject<>(commandArguments(ZPOPMIN).key(key).add(count), getTupleListBuilder()); } - public final CommandObject bzpopmax(double timeout, String... keys) { - return new CommandObject<>(commandArguments(BZPOPMAX).blocking().keys((Object[]) keys).add(timeout), BuilderFactory.KEYED_ZSET_ELEMENT); + public final CommandObject> bzpopmax(double timeout, String... keys) { + return new CommandObject<>(commandArguments(BZPOPMAX).blocking().keys((Object[]) keys).add(timeout), + BuilderFactory.KEYED_TUPLE); } - public final CommandObject bzpopmin(double timeout, String... keys) { - return new CommandObject<>(commandArguments(BZPOPMIN).blocking().keys((Object[]) keys).add(timeout), BuilderFactory.KEYED_ZSET_ELEMENT); + public final CommandObject> bzpopmin(double timeout, String... keys) { + return new CommandObject<>(commandArguments(BZPOPMIN).blocking().keys((Object[]) keys).add(timeout), + BuilderFactory.KEYED_TUPLE); } - public final CommandObject> bzpopmax(double timeout, byte[]... keys) { - return new CommandObject<>(commandArguments(BZPOPMAX).blocking().keys((Object[]) keys).add(timeout), BuilderFactory.BINARY_LIST); + public final CommandObject> bzpopmax(double timeout, byte[]... keys) { + return new CommandObject<>(commandArguments(BZPOPMAX).blocking().keys((Object[]) keys) + .add(timeout), BuilderFactory.BINARY_KEYED_TUPLE); } - public final CommandObject> bzpopmin(double timeout, byte[]... keys) { - return new CommandObject<>(commandArguments(BZPOPMIN).blocking().keys((Object[]) keys).add(timeout), BuilderFactory.BINARY_LIST); + public final CommandObject> bzpopmin(double timeout, byte[]... keys) { + return new CommandObject<>(commandArguments(BZPOPMIN).blocking().keys((Object[]) keys) + .add(timeout), BuilderFactory.BINARY_KEYED_TUPLE); } public final CommandObject zcount(String key, double min, double max) { @@ -1481,12 +1530,12 @@ public final CommandObject> zrevrange(String key, long start, long public final CommandObject> zrangeWithScores(String key, long start, long stop) { return new CommandObject<>(commandArguments(ZRANGE).key(key) - .add(start).add(stop).add(WITHSCORES), BuilderFactory.TUPLE_LIST); + .add(start).add(stop).add(WITHSCORES), getTupleListBuilder()); } public final CommandObject> zrevrangeWithScores(String key, long start, long stop) { return new CommandObject<>(commandArguments(ZREVRANGE).key(key) - .add(start).add(stop).add(WITHSCORES), BuilderFactory.TUPLE_LIST); + .add(start).add(stop).add(WITHSCORES), getTupleListBuilder()); } public final CommandObject> zrange(String key, ZRangeParams zRangeParams) { @@ -1494,7 +1543,7 @@ public final CommandObject> zrange(String key, ZRangeParams zRangeP } public final CommandObject> zrangeWithScores(String key, ZRangeParams zRangeParams) { - return new CommandObject<>(commandArguments(ZRANGE).key(key).addParams(zRangeParams).add(WITHSCORES), BuilderFactory.TUPLE_LIST); + return new CommandObject<>(commandArguments(ZRANGE).key(key).addParams(zRangeParams).add(WITHSCORES), getTupleListBuilder()); } public final CommandObject zrangestore(String dest, String src, ZRangeParams zRangeParams) { @@ -1539,42 +1588,42 @@ public final CommandObject> zrevrangeByScore(String key, String max public final CommandObject> zrangeByScoreWithScores(String key, double min, double max) { return new CommandObject<>(commandArguments(ZRANGEBYSCORE).key(key).add(min).add(max) - .add(WITHSCORES), BuilderFactory.TUPLE_LIST); + .add(WITHSCORES), getTupleListBuilder()); } public final CommandObject> zrangeByScoreWithScores(String key, String min, String max) { return new CommandObject<>(commandArguments(ZRANGEBYSCORE).key(key).add(min).add(max) - .add(WITHSCORES), BuilderFactory.TUPLE_LIST); + .add(WITHSCORES), getTupleListBuilder()); } public final CommandObject> zrevrangeByScoreWithScores(String key, double max, double min) { return new CommandObject<>(commandArguments(ZREVRANGEBYSCORE).key(key).add(max).add(min) - .add(WITHSCORES), BuilderFactory.TUPLE_LIST); + .add(WITHSCORES), getTupleListBuilder()); } public final CommandObject> zrevrangeByScoreWithScores(String key, String max, String min) { return new CommandObject<>(commandArguments(ZREVRANGEBYSCORE).key(key).add(max).add(min) - .add(WITHSCORES), BuilderFactory.TUPLE_LIST); + .add(WITHSCORES), getTupleListBuilder()); } public final CommandObject> zrangeByScoreWithScores(String key, double min, double max, int offset, int count) { return new CommandObject<>(commandArguments(ZRANGEBYSCORE).key(key).add(min).add(max) - .add(LIMIT).add(offset).add(count).add(WITHSCORES), BuilderFactory.TUPLE_LIST); + .add(LIMIT).add(offset).add(count).add(WITHSCORES), getTupleListBuilder()); } public final CommandObject> zrangeByScoreWithScores(String key, String min, String max, int offset, int count) { return new CommandObject<>(commandArguments(ZRANGEBYSCORE).key(key).add(min).add(max) - .add(LIMIT).add(offset).add(count).add(WITHSCORES), BuilderFactory.TUPLE_LIST); + .add(LIMIT).add(offset).add(count).add(WITHSCORES), getTupleListBuilder()); } public final CommandObject> zrevrangeByScoreWithScores(String key, double max, double min, int offset, int count) { return new CommandObject<>(commandArguments(ZREVRANGEBYSCORE).key(key).add(max).add(min) - .add(LIMIT).add(offset).add(count).add(WITHSCORES), BuilderFactory.TUPLE_LIST); + .add(LIMIT).add(offset).add(count).add(WITHSCORES), getTupleListBuilder()); } public final CommandObject> zrevrangeByScoreWithScores(String key, String max, String min, int offset, int count) { return new CommandObject<>(commandArguments(ZREVRANGEBYSCORE).key(key).add(max).add(min) - .add(LIMIT).add(offset).add(count).add(WITHSCORES), BuilderFactory.TUPLE_LIST); + .add(LIMIT).add(offset).add(count).add(WITHSCORES), getTupleListBuilder()); } public final CommandObject> zrange(byte[] key, long start, long stop) { @@ -1587,12 +1636,12 @@ public final CommandObject> zrevrange(byte[] key, long start, long public final CommandObject> zrangeWithScores(byte[] key, long start, long stop) { return new CommandObject<>(commandArguments(ZRANGE).key(key) - .add(start).add(stop).add(WITHSCORES), BuilderFactory.TUPLE_LIST); + .add(start).add(stop).add(WITHSCORES), getTupleListBuilder()); } public final CommandObject> zrevrangeWithScores(byte[] key, long start, long stop) { return new CommandObject<>(commandArguments(ZREVRANGE).key(key) - .add(start).add(stop).add(WITHSCORES), BuilderFactory.TUPLE_LIST); + .add(start).add(stop).add(WITHSCORES), getTupleListBuilder()); } public final CommandObject> zrange(byte[] key, ZRangeParams zRangeParams) { @@ -1600,7 +1649,7 @@ public final CommandObject> zrange(byte[] key, ZRangeParams zRangeP } public final CommandObject> zrangeWithScores(byte[] key, ZRangeParams zRangeParams) { - return new CommandObject<>(commandArguments(ZRANGE).key(key).addParams(zRangeParams).add(WITHSCORES), BuilderFactory.TUPLE_LIST); + return new CommandObject<>(commandArguments(ZRANGE).key(key).addParams(zRangeParams).add(WITHSCORES), getTupleListBuilder()); } public final CommandObject zrangestore(byte[] dest, byte[] src, ZRangeParams zRangeParams) { @@ -1645,42 +1694,42 @@ public final CommandObject> zrevrangeByScore(byte[] key, byte[] max public final CommandObject> zrangeByScoreWithScores(byte[] key, double min, double max) { return new CommandObject<>(commandArguments(ZRANGEBYSCORE).key(key).add(min).add(max) - .add(WITHSCORES), BuilderFactory.TUPLE_LIST); + .add(WITHSCORES), getTupleListBuilder()); } public final CommandObject> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max) { return new CommandObject<>(commandArguments(ZRANGEBYSCORE).key(key).add(min).add(max) - .add(WITHSCORES), BuilderFactory.TUPLE_LIST); + .add(WITHSCORES), getTupleListBuilder()); } public final CommandObject> zrevrangeByScoreWithScores(byte[] key, double max, double min) { return new CommandObject<>(commandArguments(ZREVRANGEBYSCORE).key(key).add(max).add(min) - .add(WITHSCORES), BuilderFactory.TUPLE_LIST); + .add(WITHSCORES), getTupleListBuilder()); } public final CommandObject> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min) { return new CommandObject<>(commandArguments(ZREVRANGEBYSCORE).key(key).add(max).add(min) - .add(WITHSCORES), BuilderFactory.TUPLE_LIST); + .add(WITHSCORES), getTupleListBuilder()); } public final CommandObject> zrangeByScoreWithScores(byte[] key, double min, double max, int offset, int count) { return new CommandObject<>(commandArguments(ZRANGEBYSCORE).key(key).add(min).add(max) - .add(LIMIT).add(offset).add(count).add(WITHSCORES), BuilderFactory.TUPLE_LIST); + .add(LIMIT).add(offset).add(count).add(WITHSCORES), getTupleListBuilder()); } public final CommandObject> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max, int offset, int count) { return new CommandObject<>(commandArguments(ZRANGEBYSCORE).key(key).add(min).add(max) - .add(LIMIT).add(offset).add(count).add(WITHSCORES), BuilderFactory.TUPLE_LIST); + .add(LIMIT).add(offset).add(count).add(WITHSCORES), getTupleListBuilder()); } public final CommandObject> zrevrangeByScoreWithScores(byte[] key, double max, double min, int offset, int count) { return new CommandObject<>(commandArguments(ZREVRANGEBYSCORE).key(key).add(max).add(min) - .add(LIMIT).add(offset).add(count).add(WITHSCORES), BuilderFactory.TUPLE_LIST); + .add(LIMIT).add(offset).add(count).add(WITHSCORES), getTupleListBuilder()); } public final CommandObject> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min, int offset, int count) { return new CommandObject<>(commandArguments(ZREVRANGEBYSCORE).key(key).add(max).add(min) - .add(LIMIT).add(offset).add(count).add(WITHSCORES), BuilderFactory.TUPLE_LIST); + .add(LIMIT).add(offset).add(count).add(WITHSCORES), getTupleListBuilder()); } public final CommandObject zremrangeByRank(String key, long start, long stop) { @@ -1767,51 +1816,69 @@ public final CommandObject> zscan(byte[] key, byte[] cursor, S return new CommandObject<>(commandArguments(ZSCAN).key(key).add(cursor).addParams(params), BuilderFactory.ZSCAN_RESPONSE); } - public final CommandObject> zdiff(String... keys) { - return new CommandObject<>(commandArguments(ZDIFF).add(keys.length).keys((Object[]) keys), BuilderFactory.STRING_ORDERED_SET); + public final CommandObject> zdiff(String... keys) { + return new CommandObject<>(commandArguments(ZDIFF).add(keys.length).keys((Object[]) keys), + BuilderFactory.STRING_LIST); } - public final CommandObject> zdiffWithScores(String... keys) { + public final CommandObject> zdiffWithScores(String... keys) { return new CommandObject<>(commandArguments(ZDIFF).add(keys.length).keys((Object[]) keys) - .add(WITHSCORES), BuilderFactory.TUPLE_ZSET); + .add(WITHSCORES), getTupleListBuilder()); } + /** + * @deprecated Use {@link #zdiffstore(java.lang.String, java.lang.String...)}. + */ + @Deprecated public final CommandObject zdiffStore(String dstkey, String... keys) { - return new CommandObject<>(commandArguments(ZDIFFSTORE).key(dstkey).add(keys.length).keys((Object[]) keys), BuilderFactory.LONG); + return zdiffstore(dstkey, keys); + } + + public final CommandObject zdiffstore(String dstkey, String... keys) { + return new CommandObject<>(commandArguments(ZDIFFSTORE).key(dstkey) + .add(keys.length).keys((Object[]) keys), BuilderFactory.LONG); } - public final CommandObject> zdiff(byte[]... keys) { - return new CommandObject<>(commandArguments(ZDIFF).add(keys.length).keys((Object[]) keys), BuilderFactory.BINARY_SET); + public final CommandObject> zdiff(byte[]... keys) { + return new CommandObject<>(commandArguments(ZDIFF).add(keys.length).keys((Object[]) keys), BuilderFactory.BINARY_LIST); } - public final CommandObject> zdiffWithScores(byte[]... keys) { + public final CommandObject> zdiffWithScores(byte[]... keys) { return new CommandObject<>(commandArguments(ZDIFF).add(keys.length).keys((Object[]) keys) - .add(WITHSCORES), BuilderFactory.TUPLE_ZSET); + .add(WITHSCORES), getTupleListBuilder()); } + /** + * @deprecated Use {@link #zdiffstore(byte..., byte[]...)}. + */ + @Deprecated public final CommandObject zdiffStore(byte[] dstkey, byte[]... keys) { + return zdiffstore(dstkey, keys); + } + + public final CommandObject zdiffstore(byte[] dstkey, byte[]... keys) { return new CommandObject<>(commandArguments(ZDIFFSTORE).key(dstkey) .add(keys.length).keys((Object[]) keys), BuilderFactory.LONG); } - public final CommandObject zinterstore(String dstkey, String... sets) { - return new CommandObject<>(commandArguments(ZINTERSTORE).key(dstkey) - .add(sets.length).keys((Object[]) sets), BuilderFactory.LONG); + public final CommandObject> zinter(ZParams params, String... keys) { + return new CommandObject<>(commandArguments(ZINTER).add(keys.length).keys((Object[]) keys) + .addParams(params), BuilderFactory.STRING_LIST); } - public final CommandObject zinterstore(String dstkey, ZParams params, String... sets) { - return new CommandObject<>(commandArguments(ZINTERSTORE).key(dstkey) - .add(sets.length).keys((Object[]) sets).addParams(params), BuilderFactory.LONG); + public final CommandObject> zinterWithScores(ZParams params, String... keys) { + return new CommandObject<>(commandArguments(ZINTER).add(keys.length).keys((Object[]) keys) + .addParams(params).add(WITHSCORES), getTupleListBuilder()); } - public final CommandObject> zinter(ZParams params, String... keys) { - return new CommandObject<>(commandArguments(ZINTER).add(keys.length).keys((Object[]) keys) - .addParams(params), BuilderFactory.STRING_ORDERED_SET); + public final CommandObject zinterstore(String dstkey, String... keys) { + return new CommandObject<>(commandArguments(ZINTERSTORE).key(dstkey) + .add(keys.length).keys((Object[]) keys), BuilderFactory.LONG); } - public final CommandObject> zinterWithScores(ZParams params, String... keys) { - return new CommandObject<>(commandArguments(ZINTER).add(keys.length).keys((Object[]) keys) - .addParams(params).add(WITHSCORES), BuilderFactory.TUPLE_ZSET); + public final CommandObject zinterstore(String dstkey, ZParams params, String... keys) { + return new CommandObject<>(commandArguments(ZINTERSTORE).key(dstkey) + .add(keys.length).keys((Object[]) keys).addParams(params), BuilderFactory.LONG); } public final CommandObject zintercard(String... keys) { @@ -1844,14 +1911,14 @@ public final CommandObject zintercard(long limit, byte[]... keys) { .keys((Object[]) keys).add(LIMIT).add(limit), BuilderFactory.LONG); } - public final CommandObject> zinter(ZParams params, byte[]... keys) { + public final CommandObject> zinter(ZParams params, byte[]... keys) { return new CommandObject<>(commandArguments(ZINTER).add(keys.length).keys((Object[]) keys) - .addParams(params), BuilderFactory.BINARY_SET); + .addParams(params), BuilderFactory.BINARY_LIST); } - public final CommandObject> zinterWithScores(ZParams params, byte[]... keys) { + public final CommandObject> zinterWithScores(ZParams params, byte[]... keys) { return new CommandObject<>(commandArguments(ZINTER).add(keys.length).keys((Object[]) keys) - .addParams(params).add(WITHSCORES), BuilderFactory.TUPLE_ZSET); + .addParams(params).add(WITHSCORES), getTupleListBuilder()); } public final CommandObject zunionstore(String dstkey, String... sets) { @@ -1864,14 +1931,14 @@ public final CommandObject zunionstore(String dstkey, ZParams params, Stri .add(sets.length).keys((Object[]) sets).addParams(params), BuilderFactory.LONG); } - public final CommandObject> zunion(ZParams params, String... keys) { + public final CommandObject> zunion(ZParams params, String... keys) { return new CommandObject<>(commandArguments(ZUNION).add(keys.length).keys((Object[]) keys) - .addParams(params), BuilderFactory.STRING_ORDERED_SET); + .addParams(params), BuilderFactory.STRING_LIST); } - public final CommandObject> zunionWithScores(ZParams params, String... keys) { + public final CommandObject> zunionWithScores(ZParams params, String... keys) { return new CommandObject<>(commandArguments(ZUNION).add(keys.length).keys((Object[]) keys) - .addParams(params).add(WITHSCORES), BuilderFactory.TUPLE_ZSET); + .addParams(params).add(WITHSCORES), getTupleListBuilder()); } public final CommandObject zunionstore(byte[] dstkey, byte[]... sets) { @@ -1884,14 +1951,14 @@ public final CommandObject zunionstore(byte[] dstkey, ZParams params, byte .add(sets.length).keys((Object[]) sets).addParams(params), BuilderFactory.LONG); } - public final CommandObject> zunion(ZParams params, byte[]... keys) { + public final CommandObject> zunion(ZParams params, byte[]... keys) { return new CommandObject<>(commandArguments(ZUNION).add(keys.length).keys((Object[]) keys) - .addParams(params), BuilderFactory.BINARY_SET); + .addParams(params), BuilderFactory.BINARY_LIST); } - public final CommandObject> zunionWithScores(ZParams params, byte[]... keys) { + public final CommandObject> zunionWithScores(ZParams params, byte[]... keys) { return new CommandObject<>(commandArguments(ZUNION).add(keys.length).keys((Object[]) keys) - .addParams(params).add(WITHSCORES), BuilderFactory.TUPLE_ZSET); + .addParams(params).add(WITHSCORES), getTupleListBuilder()); } public final CommandObject>> zmpop(SortedSetOption option, String... keys) { @@ -1904,12 +1971,12 @@ public final CommandObject>> zmpop(SortedSetOption .add(option).add(COUNT).add(count), BuilderFactory.KEYED_TUPLE_LIST); } - public final CommandObject>> bzmpop(long timeout, SortedSetOption option, String... keys) { + public final CommandObject>> bzmpop(double timeout, SortedSetOption option, String... keys) { return new CommandObject<>(commandArguments(BZMPOP).blocking().add(timeout).add(keys.length) .keys((Object[]) keys).add(option), BuilderFactory.KEYED_TUPLE_LIST); } - public final CommandObject>> bzmpop(long timeout, SortedSetOption option, int count, String... keys) { + public final CommandObject>> bzmpop(double timeout, SortedSetOption option, int count, String... keys) { return new CommandObject<>(commandArguments(BZMPOP).blocking().add(timeout).add(keys.length) .keys((Object[]) keys).add(option).add(COUNT).add(count), BuilderFactory.KEYED_TUPLE_LIST); } @@ -1924,15 +1991,23 @@ public final CommandObject>> zmpop(SortedSetOption .add(option).add(COUNT).add(count), BuilderFactory.BINARY_KEYED_TUPLE_LIST); } - public final CommandObject>> bzmpop(long timeout, SortedSetOption option, byte[]... keys) { + public final CommandObject>> bzmpop(double timeout, SortedSetOption option, byte[]... keys) { return new CommandObject<>(commandArguments(BZMPOP).blocking().add(timeout).add(keys.length) .keys((Object[]) keys).add(option), BuilderFactory.BINARY_KEYED_TUPLE_LIST); } - public final CommandObject>> bzmpop(long timeout, SortedSetOption option, int count, byte[]... keys) { + public final CommandObject>> bzmpop(double timeout, SortedSetOption option, int count, byte[]... keys) { return new CommandObject<>(commandArguments(BZMPOP).blocking().add(timeout).add(keys.length) .keys((Object[]) keys).add(option).add(COUNT).add(count), BuilderFactory.BINARY_KEYED_TUPLE_LIST); } + + private Builder> getTupleListBuilder() { + return protocol == RedisProtocol.RESP3 ? BuilderFactory.TUPLE_LIST_RESP3 : BuilderFactory.TUPLE_LIST; + } + + private Builder> getTupleSetBuilder() { + return protocol == RedisProtocol.RESP3 ? BuilderFactory.TUPLE_ZSET_RESP3 : BuilderFactory.TUPLE_ZSET; + } // Sorted Set commands // Geo commands @@ -1961,7 +2036,8 @@ public final CommandObject> geohash(String key, String... members) } public final CommandObject> geopos(String key, String... members) { - return new CommandObject<>(commandArguments(GEOPOS).key(key).addObjects((Object[]) members), BuilderFactory.GEO_COORDINATE_LIST); + return new CommandObject<>(commandArguments(GEOPOS).key(key).addObjects((Object[]) members), + BuilderFactory.GEO_COORDINATE_LIST); } public final CommandObject geoadd(byte[] key, double longitude, double latitude, byte[] member) { @@ -1989,7 +2065,8 @@ public final CommandObject> geohash(byte[] key, byte[]... members) } public final CommandObject> geopos(byte[] key, byte[]... members) { - return new CommandObject<>(commandArguments(GEOPOS).key(key).addObjects((Object[]) members), BuilderFactory.GEO_COORDINATE_LIST); + return new CommandObject<>(commandArguments(GEOPOS).key(key).addObjects((Object[]) members), + BuilderFactory.GEO_COORDINATE_LIST); } public final CommandObject> georadius(String key, double longitude, double latitude, double radius, GeoUnit unit) { @@ -2327,24 +2404,24 @@ public final CommandObject> xrevrange(String key, String end, return new CommandObject<>(commandArguments(XREVRANGE).key(key).add(end).add(start).add(COUNT).add(count), BuilderFactory.STREAM_ENTRY_LIST); } - public final CommandObject> xrange(byte[] key, byte[] start, byte[] end) { + public final CommandObject> xrange(byte[] key, byte[] start, byte[] end) { return new CommandObject<>(commandArguments(XRANGE).key(key).add(start == null ? "-" : start).add(end == null ? "+" : end), - BuilderFactory.BINARY_LIST); + BuilderFactory.RAW_OBJECT_LIST); } - public final CommandObject> xrange(byte[] key, byte[] start, byte[] end, int count) { + public final CommandObject> xrange(byte[] key, byte[] start, byte[] end, int count) { return new CommandObject<>(commandArguments(XRANGE).key(key).add(start == null ? "-" : start).add(end == null ? "+" : end) - .add(COUNT).add(count), BuilderFactory.BINARY_LIST); + .add(COUNT).add(count), BuilderFactory.RAW_OBJECT_LIST); } - public final CommandObject> xrevrange(byte[] key, byte[] end, byte[] start) { + public final CommandObject> xrevrange(byte[] key, byte[] end, byte[] start) { return new CommandObject<>(commandArguments(XREVRANGE).key(key).add(end == null ? "+" : end).add(start == null ? "-" : start), - BuilderFactory.BINARY_LIST); + BuilderFactory.RAW_OBJECT_LIST); } - public final CommandObject> xrevrange(byte[] key, byte[] end, byte[] start, int count) { + public final CommandObject> xrevrange(byte[] key, byte[] end, byte[] start, int count) { return new CommandObject<>(commandArguments(XREVRANGE).key(key).add(end == null ? "+" : end).add(start == null ? "-" : start) - .add(COUNT).add(count), BuilderFactory.BINARY_LIST); + .add(COUNT).add(count), BuilderFactory.RAW_OBJECT_LIST); } public final CommandObject xack(String key, String group, StreamEntryID... ids) { @@ -2443,25 +2520,6 @@ public final CommandObject xpending(String key, String gro BuilderFactory.STREAM_PENDING_SUMMARY); } - /** - * @param key - * @param groupName - * @param start - * @param end - * @param count - * @param consumerName - * @return - * @deprecated Use {@link CommandObjects#xpending(java.lang.String, java.lang.String, redis.clients.jedis.params.XPendingParams)}. - */ - @Deprecated - public final CommandObject> xpending(String key, String groupName, - StreamEntryID start, StreamEntryID end, int count, String consumerName) { - CommandArguments args = commandArguments(XPENDING).key(key).add(groupName) - .add(start == null ? "-" : start).add(end == null ? "+" : end).add(count); - if (consumerName != null) args.add(consumerName); - return new CommandObject<>(args, BuilderFactory.STREAM_PENDING_ENTRY_LIST); - } - public final CommandObject> xpending(String key, String groupName, XPendingParams params) { return new CommandObject<>(commandArguments(XPENDING).key(key).add(groupName) .addParams(params), BuilderFactory.STREAM_PENDING_ENTRY_LIST); @@ -2472,18 +2530,6 @@ public final CommandObject xpending(byte[] key, byte[] groupName) { BuilderFactory.RAW_OBJECT); } - /** - * @deprecated Use {@link CommandObjects#xpending(byte[], byte[], redis.clients.jedis.params.XPendingParams)}. - */ - @Deprecated - public final CommandObject> xpending(byte[] key, byte[] groupName, - byte[] start, byte[] end, int count, byte[] consumerName) { - CommandArguments args = commandArguments(XPENDING).key(key).add(groupName) - .add(start == null ? "-" : start).add(end == null ? "+" : end).add(count); - if (consumerName != null) args.add(consumerName); - return new CommandObject<>(args, BuilderFactory.RAW_OBJECT_LIST); - } - public final CommandObject> xpending(byte[] key, byte[] groupName, XPendingParams params) { return new CommandObject<>(commandArguments(XPENDING).key(key).add(groupName) .addParams(params), BuilderFactory.RAW_OBJECT_LIST); @@ -2516,7 +2562,7 @@ public final CommandObject>> xautoc XAutoClaimParams params) { return new CommandObject<>(commandArguments(XAUTOCLAIM).key(key).add(group) .add(consumerName).add(minIdleTime).add(start).addParams(params) - .add(JUSTID), BuilderFactory.STREAM_AUTO_CLAIM_ID_RESPONSE); + .add(JUSTID), BuilderFactory.STREAM_AUTO_CLAIM_JUSTID_RESPONSE); } public final CommandObject> xclaim(byte[] key, byte[] group, @@ -2556,11 +2602,11 @@ public final CommandObject xinfoStream(byte[] key) { } public final CommandObject xinfoStreamFull(String key) { - return new CommandObject<>(commandArguments(XINFO).add(STREAM).key(key).add(FULL), BuilderFactory.STREAM_INFO_FULL); + return new CommandObject<>(commandArguments(XINFO).add(STREAM).key(key).add(FULL), BuilderFactory.STREAM_FULL_INFO); } public final CommandObject xinfoStreamFull(String key, int count) { - return new CommandObject<>(commandArguments(XINFO).add(STREAM).key(key).add(FULL).add(COUNT).add(count), BuilderFactory.STREAM_INFO_FULL); + return new CommandObject<>(commandArguments(XINFO).add(STREAM).key(key).add(FULL).add(COUNT).add(count), BuilderFactory.STREAM_FULL_INFO); } public final CommandObject xinfoStreamFull(byte[] key, int count) { @@ -2571,28 +2617,26 @@ public final CommandObject xinfoStreamFull(byte[] key) { return new CommandObject<>(commandArguments(XINFO).add(STREAM).key(key).add(FULL), BuilderFactory.RAW_OBJECT); } - @Deprecated - public final CommandObject> xinfoGroup(String key) { - return new CommandObject<>(commandArguments(XINFO).add(GROUPS).key(key), BuilderFactory.STREAM_GROUP_INFO_LIST); - } - public final CommandObject> xinfoGroups(String key) { return new CommandObject<>(commandArguments(XINFO).add(GROUPS).key(key), BuilderFactory.STREAM_GROUP_INFO_LIST); } - @Deprecated - public final CommandObject> xinfoGroup(byte[] key) { - return new CommandObject<>(commandArguments(XINFO).add(GROUPS).key(key), BuilderFactory.RAW_OBJECT_LIST); - } - public final CommandObject> xinfoGroups(byte[] key) { return new CommandObject<>(commandArguments(XINFO).add(GROUPS).key(key), BuilderFactory.RAW_OBJECT_LIST); } + /** + * @deprecated Use {@link #xinfoConsumers2(java.lang.String, java.lang.String)}. + */ + @Deprecated public final CommandObject> xinfoConsumers(String key, String group) { return new CommandObject<>(commandArguments(XINFO).add(CONSUMERS).key(key).add(group), BuilderFactory.STREAM_CONSUMERS_INFO_LIST); } + public final CommandObject> xinfoConsumers2(String key, String group) { + return new CommandObject<>(commandArguments(XINFO).add(CONSUMERS).key(key).add(group), BuilderFactory.STREAM_CONSUMER_INFO_LIST); + } + public final CommandObject> xinfoConsumers(byte[] key, byte[] group) { return new CommandObject<>(commandArguments(XINFO).add(CONSUMERS).key(key).add(group), BuilderFactory.RAW_OBJECT_LIST); } @@ -2618,7 +2662,7 @@ public final CommandObject>>> xreadGrou return new CommandObject<>(args, BuilderFactory.STREAM_READ_RESPONSE); } - public final CommandObject> xread(XReadParams xReadParams, Map.Entry... streams) { + public final CommandObject> xread(XReadParams xReadParams, Map.Entry... streams) { CommandArguments args = commandArguments(XREAD).addParams(xReadParams).add(STREAMS); for (Map.Entry entry : streams) { args.key(entry.getKey()); @@ -2626,10 +2670,10 @@ public final CommandObject> xread(XReadParams xReadParams, Map.Entr for (Map.Entry entry : streams) { args.add(entry.getValue()); } - return new CommandObject<>(args, BuilderFactory.BINARY_LIST); + return new CommandObject<>(args, BuilderFactory.RAW_OBJECT_LIST); } - public final CommandObject> xreadGroup(byte[] groupName, byte[] consumer, + public final CommandObject> xreadGroup(byte[] groupName, byte[] consumer, XReadGroupParams xReadGroupParams, Map.Entry... streams) { CommandArguments args = commandArguments(XREADGROUP) .add(GROUP).add(groupName).add(consumer) @@ -2640,39 +2684,33 @@ public final CommandObject> xreadGroup(byte[] groupName, byte[] con for (Map.Entry entry : streams) { args.add(entry.getValue()); } - return new CommandObject<>(args, BuilderFactory.BINARY_LIST); + return new CommandObject<>(args, BuilderFactory.RAW_OBJECT_LIST); } // Stream commands // Scripting commands public final CommandObject eval(String script) { - return new CommandObject<>(commandArguments(EVAL).add(script).add(0), BuilderFactory.ENCODED_OBJECT); + return new CommandObject<>(commandArguments(EVAL).add(script).add(0), BuilderFactory.AGGRESSIVE_ENCODED_OBJECT); } public final CommandObject eval(String script, String sampleKey) { - return new CommandObject<>(commandArguments(EVAL).add(script).add(0).processKey(sampleKey), BuilderFactory.ENCODED_OBJECT); + return new CommandObject<>(commandArguments(EVAL).add(script).add(0).processKey(sampleKey), BuilderFactory.AGGRESSIVE_ENCODED_OBJECT); } public final CommandObject eval(String script, int keyCount, String... params) { return new CommandObject<>(commandArguments(EVAL).add(script).add(keyCount) .addObjects((Object[]) params).processKeys(Arrays.copyOf(params, keyCount)), - BuilderFactory.ENCODED_OBJECT); + BuilderFactory.AGGRESSIVE_ENCODED_OBJECT); } public final CommandObject eval(String script, List keys, List args) { - String[] keysArray = keys.toArray(new String[keys.size()]); - String[] argsArray = args.toArray(new String[args.size()]); - return new CommandObject<>(commandArguments(EVAL).add(script).add(keysArray.length) - .keys((Object[]) keysArray).addObjects((Object[]) argsArray), - BuilderFactory.ENCODED_OBJECT); + return new CommandObject<>(commandArguments(EVAL).add(script).add(keys.size()) + .keys(keys).addObjects(args), BuilderFactory.AGGRESSIVE_ENCODED_OBJECT); } public final CommandObject evalReadonly(String script, List keys, List args) { - String[] keysArray = keys.toArray(new String[keys.size()]); - String[] argsArray = args.toArray(new String[args.size()]); - return new CommandObject<>(commandArguments(EVAL_RO).add(script).add(keysArray.length) - .keys((Object[]) keysArray).addObjects((Object[]) argsArray), - BuilderFactory.ENCODED_OBJECT); + return new CommandObject<>(commandArguments(EVAL_RO).add(script).add(keys.size()) + .keys(keys).addObjects(args), BuilderFactory.AGGRESSIVE_ENCODED_OBJECT); } public final CommandObject eval(byte[] script) { @@ -2690,49 +2728,37 @@ public final CommandObject eval(byte[] script, int keyCount, byte[]... p } public final CommandObject eval(byte[] script, List keys, List args) { - byte[][] keysArray = keys.toArray(new byte[keys.size()][]); - byte[][] argsArray = args.toArray(new byte[args.size()][]); - return new CommandObject<>(commandArguments(EVAL).add(script).add(keysArray.length) - .keys((Object[]) keysArray).addObjects((Object[]) argsArray), - BuilderFactory.RAW_OBJECT); + return new CommandObject<>(commandArguments(EVAL).add(script).add(keys.size()) + .keys(keys).addObjects(args), BuilderFactory.RAW_OBJECT); } public final CommandObject evalReadonly(byte[] script, List keys, List args) { - byte[][] keysArray = keys.toArray(new byte[keys.size()][]); - byte[][] argsArray = args.toArray(new byte[args.size()][]); - return new CommandObject<>(commandArguments(EVAL_RO).add(script).add(keysArray.length) - .keys((Object[]) keysArray).addObjects((Object[]) argsArray), - BuilderFactory.RAW_OBJECT); + return new CommandObject<>(commandArguments(EVAL_RO).add(script).add(keys.size()) + .keys(keys).addObjects(args), BuilderFactory.RAW_OBJECT); } public final CommandObject evalsha(String sha1) { - return new CommandObject<>(commandArguments(EVALSHA).add(sha1).add(0), BuilderFactory.ENCODED_OBJECT); + return new CommandObject<>(commandArguments(EVALSHA).add(sha1).add(0), BuilderFactory.AGGRESSIVE_ENCODED_OBJECT); } public final CommandObject evalsha(String sha1, String sampleKey) { - return new CommandObject<>(commandArguments(EVALSHA).add(sha1).add(0).processKey(sampleKey), BuilderFactory.ENCODED_OBJECT); + return new CommandObject<>(commandArguments(EVALSHA).add(sha1).add(0).processKey(sampleKey), BuilderFactory.AGGRESSIVE_ENCODED_OBJECT); } public final CommandObject evalsha(String sha1, int keyCount, String... params) { return new CommandObject<>(commandArguments(EVALSHA).add(sha1).add(keyCount) .addObjects((Object[]) params).processKeys(Arrays.copyOf(params, keyCount)), - BuilderFactory.ENCODED_OBJECT); + BuilderFactory.AGGRESSIVE_ENCODED_OBJECT); } public final CommandObject evalsha(String sha1, List keys, List args) { - String[] keysArray = keys.toArray(new String[keys.size()]); - String[] argsArray = args.toArray(new String[args.size()]); - return new CommandObject<>(commandArguments(EVALSHA).add(sha1).add(keysArray.length) - .keys((Object[]) keysArray).addObjects((Object[]) argsArray), - BuilderFactory.ENCODED_OBJECT); + return new CommandObject<>(commandArguments(EVALSHA).add(sha1).add(keys.size()) + .keys(keys).addObjects(args), BuilderFactory.AGGRESSIVE_ENCODED_OBJECT); } public final CommandObject evalshaReadonly(String sha1, List keys, List args) { - String[] keysArray = keys.toArray(new String[keys.size()]); - String[] argsArray = args.toArray(new String[args.size()]); - return new CommandObject<>(commandArguments(EVALSHA_RO).add(sha1).add(keysArray.length) - .keys((Object[]) keysArray).addObjects((Object[]) argsArray), - BuilderFactory.ENCODED_OBJECT); + return new CommandObject<>(commandArguments(EVALSHA_RO).add(sha1).add(keys.size()) + .keys(keys).addObjects(args), BuilderFactory.AGGRESSIVE_ENCODED_OBJECT); } public final CommandObject evalsha(byte[] sha1) { @@ -2750,19 +2776,17 @@ public final CommandObject evalsha(byte[] sha1, int keyCount, byte[]... } public final CommandObject evalsha(byte[] sha1, List keys, List args) { - byte[][] keysArray = keys.toArray(new byte[keys.size()][]); - byte[][] argsArray = args.toArray(new byte[args.size()][]); - return new CommandObject<>(commandArguments(EVALSHA).add(sha1).add(keysArray.length) - .keys((Object[]) keysArray).addObjects((Object[]) argsArray), - BuilderFactory.RAW_OBJECT); + return new CommandObject<>(commandArguments(EVALSHA).add(sha1).add(keys.size()) + .keys(keys).addObjects(args), BuilderFactory.RAW_OBJECT); } public final CommandObject evalshaReadonly(byte[] sha1, List keys, List args) { - byte[][] keysArray = keys.toArray(new byte[keys.size()][]); - byte[][] argsArray = args.toArray(new byte[args.size()][]); - return new CommandObject<>(commandArguments(EVALSHA_RO).add(sha1).add(keysArray.length) - .keys((Object[]) keysArray).addObjects((Object[]) argsArray), - BuilderFactory.RAW_OBJECT); + return new CommandObject<>(commandArguments(EVALSHA_RO).add(sha1).add(keys.size()) + .keys(keys).addObjects(args), BuilderFactory.RAW_OBJECT); + } + + public final CommandObject> scriptExists(List sha1s) { + return new CommandObject<>(commandArguments(SCRIPT).add(Keyword.EXISTS).addObjects(sha1s), BuilderFactory.BOOLEAN_LIST); } public final CommandObject> scriptExists(String sampleKey, String... sha1s) { @@ -2770,10 +2794,20 @@ public final CommandObject> scriptExists(String sampleKey, String. .processKey(sampleKey), BuilderFactory.BOOLEAN_LIST); } + public final CommandObject scriptLoad(String script) { + return new CommandObject<>(commandArguments(SCRIPT).add(LOAD).add(script), BuilderFactory.STRING); + } + public final CommandObject scriptLoad(String script, String sampleKey) { return new CommandObject<>(commandArguments(SCRIPT).add(LOAD).add(script).processKey(sampleKey), BuilderFactory.STRING); } + private final CommandObject SCRIPT_FLUSH_COMMAND_OBJECT = new CommandObject<>(commandArguments(SCRIPT).add(FLUSH), BuilderFactory.STRING); + + public final CommandObject scriptFlush() { + return SCRIPT_FLUSH_COMMAND_OBJECT; + } + public final CommandObject scriptFlush(String sampleKey) { return new CommandObject<>(commandArguments(SCRIPT).add(FLUSH).processKey(sampleKey), BuilderFactory.STRING); } @@ -2782,6 +2816,12 @@ public final CommandObject scriptFlush(String sampleKey, FlushMode flush return new CommandObject<>(commandArguments(SCRIPT).add(FLUSH).add(flushMode).processKey(sampleKey), BuilderFactory.STRING); } + private final CommandObject SCRIPT_KILL_COMMAND_OBJECT = new CommandObject<>(commandArguments(SCRIPT).add(KILL), BuilderFactory.STRING); + + public final CommandObject scriptKill() { + return SCRIPT_KILL_COMMAND_OBJECT; + } + public final CommandObject scriptKill(String sampleKey) { return new CommandObject<>(commandArguments(SCRIPT).add(KILL).processKey(sampleKey), BuilderFactory.STRING); } @@ -2807,20 +2847,21 @@ public final CommandObject scriptKill(byte[] sampleKey) { return new CommandObject<>(commandArguments(SCRIPT).add(KILL).processKey(sampleKey), BuilderFactory.STRING); } + private final CommandObject SLOWLOG_RESET_COMMAND_OBJECT + = new CommandObject<>(commandArguments(SLOWLOG).add(Keyword.RESET), BuilderFactory.STRING); + + public final CommandObject slowlogReset() { + return SLOWLOG_RESET_COMMAND_OBJECT; + } + public final CommandObject fcall(String name, List keys, List args) { - String[] keysArray = keys.toArray(new String[keys.size()]); - String[] argsArray = args.toArray(new String[args.size()]); - return new CommandObject<>(commandArguments(FCALL).add(name).add(keysArray.length) - .keys((Object[]) keysArray).addObjects((Object[]) argsArray), - BuilderFactory.ENCODED_OBJECT); + return new CommandObject<>(commandArguments(FCALL).add(name).add(keys.size()) + .keys(keys).addObjects(args), BuilderFactory.AGGRESSIVE_ENCODED_OBJECT); } public final CommandObject fcallReadonly(String name, List keys, List args) { - String[] keysArray = keys.toArray(new String[keys.size()]); - String[] argsArray = args.toArray(new String[args.size()]); - return new CommandObject<>(commandArguments(FCALL_RO).add(name).add(keysArray.length) - .keys((Object[]) keysArray).addObjects((Object[]) argsArray), - BuilderFactory.ENCODED_OBJECT); + return new CommandObject<>(commandArguments(FCALL_RO).add(name).add(keys.size()) + .keys(keys).addObjects(args), BuilderFactory.AGGRESSIVE_ENCODED_OBJECT); } public final CommandObject functionDelete(String libraryName) { @@ -2828,21 +2869,21 @@ public final CommandObject functionDelete(String libraryName) { } public final CommandObject> functionList() { - return new CommandObject<>(commandArguments(FUNCTION).add(LIST), BuilderFactory.LIBRARY_LIST); + return new CommandObject<>(commandArguments(FUNCTION).add(LIST), LibraryInfo.LIBRARY_INFO_LIST); } public final CommandObject> functionList(String libraryNamePattern) { return new CommandObject<>(commandArguments(FUNCTION).add(LIST).add(LIBRARYNAME) - .add(libraryNamePattern), BuilderFactory.LIBRARY_LIST); + .add(libraryNamePattern), LibraryInfo.LIBRARY_INFO_LIST); } public final CommandObject> functionListWithCode() { - return new CommandObject<>(commandArguments(FUNCTION).add(LIST).add(WITHCODE), BuilderFactory.LIBRARY_LIST); + return new CommandObject<>(commandArguments(FUNCTION).add(LIST).add(WITHCODE), LibraryInfo.LIBRARY_INFO_LIST); } public final CommandObject> functionListWithCode(String libraryNamePattern) { return new CommandObject<>(commandArguments(FUNCTION).add(LIST).add(LIBRARYNAME) - .add(libraryNamePattern).add(WITHCODE), BuilderFactory.LIBRARY_LIST); + .add(libraryNamePattern).add(WITHCODE), LibraryInfo.LIBRARY_INFO_LIST); } public final CommandObject functionLoad(String functionCode) { @@ -2874,19 +2915,13 @@ public final CommandObject functionKill() { } public final CommandObject fcall(byte[] name, List keys, List args) { - byte[][] keysArray = keys.toArray(new byte[keys.size()][]); - byte[][] argsArray = args.toArray(new byte[args.size()][]); - return new CommandObject<>(commandArguments(FCALL).add(name).add(keysArray.length) - .keys((Object[]) keysArray).addObjects((Object[]) argsArray), - BuilderFactory.RAW_OBJECT); + return new CommandObject<>(commandArguments(FCALL).add(name).add(keys.size()) + .keys(keys).addObjects(args), BuilderFactory.RAW_OBJECT); } public final CommandObject fcallReadonly(byte[] name, List keys, List args) { - byte[][] keysArray = keys.toArray(new byte[keys.size()][]); - byte[][] argsArray = args.toArray(new byte[args.size()][]); - return new CommandObject<>(commandArguments(FCALL_RO).add(name).add(keysArray.length) - .keys((Object[]) keysArray).addObjects((Object[]) argsArray), - BuilderFactory.RAW_OBJECT); + return new CommandObject<>(commandArguments(FCALL_RO).add(name).add(keys.size()) + .keys(keys).addObjects(args), BuilderFactory.RAW_OBJECT); } public final CommandObject functionDelete(byte[] libraryName) { @@ -2935,20 +2970,6 @@ public final CommandObject functionRestore(byte[] serializedValue, Funct // Scripting commands // Miscellaneous commands - @Deprecated - public final CommandObject strAlgoLCSStrings(String strA, String strB, StrAlgoLCSParams params) { - return new CommandObject<>(commandArguments(STRALGO).add(Keyword.LCS).add(STRINGS) - .add(strA).add(strB).addParams(params), - BuilderFactory.STR_ALGO_LCS_RESULT_BUILDER); - } - - @Deprecated - public final CommandObject strAlgoLCSStrings(byte[] strA, byte[] strB, StrAlgoLCSParams params) { - return new CommandObject<>(commandArguments(STRALGO).add(Keyword.LCS).add(STRINGS) - .add(strA).add(strB).addParams(params), - BuilderFactory.STR_ALGO_LCS_RESULT_BUILDER); - } - public final CommandObject copy(String srcKey, String dstKey, int dstDB, boolean replace) { CommandArguments args = commandArguments(Command.COPY).key(srcKey).key(dstKey).add(DB).add(dstDB); if (replace) args.add(REPLACE); @@ -3061,6 +3082,18 @@ public final CommandObject waitReplicas(byte[] sampleKey, int replicas, lo return new CommandObject<>(commandArguments(WAIT).add(replicas).add(timeout).processKey(sampleKey), BuilderFactory.LONG); } + public CommandObject> waitAOF(long numLocal, long numReplicas, long timeout) { + return new CommandObject<>(commandArguments(WAITAOF).add(numLocal).add(numReplicas).add(timeout), BuilderFactory.LONG_LONG_PAIR); + } + + public CommandObject> waitAOF(byte[] sampleKey, long numLocal, long numReplicas, long timeout) { + return new CommandObject<>(commandArguments(WAITAOF).add(numLocal).add(numReplicas).add(timeout).processKey(sampleKey), BuilderFactory.LONG_LONG_PAIR); + } + + public CommandObject> waitAOF(String sampleKey, long numLocal, long numReplicas, long timeout) { + return new CommandObject<>(commandArguments(WAITAOF).add(numLocal).add(numReplicas).add(timeout).processKey(sampleKey), BuilderFactory.LONG_LONG_PAIR); + } + public final CommandObject publish(String channel, String message) { return new CommandObject<>(commandArguments(PUBLISH).add(channel).add(message), BuilderFactory.LONG); } @@ -3068,129 +3101,215 @@ public final CommandObject publish(String channel, String message) { public final CommandObject publish(byte[] channel, byte[] message) { return new CommandObject<>(commandArguments(PUBLISH).add(channel).add(message), BuilderFactory.LONG); } + + public final CommandObject spublish(String channel, String message) { + return new CommandObject<>(commandArguments(SPUBLISH).key(channel).add(message), BuilderFactory.LONG); + } + + public final CommandObject spublish(byte[] channel, byte[] message) { + return new CommandObject<>(commandArguments(SPUBLISH).key(channel).add(message), BuilderFactory.LONG); + } // Miscellaneous commands // RediSearch commands - public CommandObject ftCreate(String indexName, IndexOptions indexOptions, Schema schema) { - CommandArguments args = commandArguments(SearchCommand.CREATE).add(indexName) + public final CommandObject hsetObject(String key, String field, Object value) { + return new CommandObject<>(commandArguments(HSET).key(key).add(field).add(value), BuilderFactory.LONG); + } + + public final CommandObject hsetObject(String key, Map hash) { + return new CommandObject<>(addFlatMapArgs(commandArguments(HSET).key(key), hash), BuilderFactory.LONG); + } + + private boolean isRoundRobinSearchCommand() { + if (broadcastAndRoundRobinConfig == null) { + return true; + } else if (broadcastAndRoundRobinConfig.getRediSearchModeInCluster() == JedisBroadcastAndRoundRobinConfig.RediSearchMode.LIGHT) { + return false; + } + return true; + } + + private CommandArguments checkAndRoundRobinSearchCommand(SearchCommand sc, String idx) { + CommandArguments ca = commandArguments(sc); + if (isRoundRobinSearchCommand()) { + ca.add(idx); + } else { + ca.key(idx); + } + return ca; + } + + private CommandArguments checkAndRoundRobinSearchCommand(SearchCommand sc, String idx1, String idx2) { + CommandArguments ca = commandArguments(sc); + if (isRoundRobinSearchCommand()) { + ca.add(idx1).add(idx2); + } else { + ca.key(idx1).key(idx2); + } + return ca; + } + + private CommandArguments checkAndRoundRobinSearchCommand(CommandArguments commandArguments, byte[] indexName) { + return isRoundRobinSearchCommand() ? commandArguments.add(indexName) : commandArguments.key(indexName); + } + + private CommandObject directSearchCommand(CommandObject object, String indexName) { + object.getArguments().processKey(indexName); + return object; + } + + public final CommandObject ftCreate(String indexName, IndexOptions indexOptions, Schema schema) { + CommandArguments args = checkAndRoundRobinSearchCommand(SearchCommand.CREATE, indexName) .addParams(indexOptions).add(SearchKeyword.SCHEMA); schema.fields.forEach(field -> args.addParams(field)); return new CommandObject<>(args, BuilderFactory.STRING); } - public CommandObject ftCreate(String indexName, FTCreateParams createParams, + public final CommandObject ftCreate(String indexName, FTCreateParams createParams, Iterable schemaFields) { - CommandArguments args = commandArguments(SearchCommand.CREATE).add(indexName) + CommandArguments args = checkAndRoundRobinSearchCommand(SearchCommand.CREATE, indexName) .addParams(createParams).add(SearchKeyword.SCHEMA); schemaFields.forEach(field -> args.addParams(field)); return new CommandObject<>(args, BuilderFactory.STRING); } - public CommandObject ftAlter(String indexName, Schema schema) { - CommandArguments args = commandArguments(SearchCommand.ALTER).add(indexName) + public final CommandObject ftAlter(String indexName, Schema schema) { + CommandArguments args = checkAndRoundRobinSearchCommand(SearchCommand.ALTER, indexName) .add(SearchKeyword.SCHEMA).add(SearchKeyword.ADD); schema.fields.forEach(field -> args.addParams(field)); return new CommandObject<>(args, BuilderFactory.STRING); } - public CommandObject ftAlter(String indexName, Iterable schemaFields) { - CommandArguments args = commandArguments(SearchCommand.ALTER).add(indexName) + public final CommandObject ftAlter(String indexName, Iterable schemaFields) { + CommandArguments args = checkAndRoundRobinSearchCommand(SearchCommand.ALTER, indexName) .add(SearchKeyword.SCHEMA).add(SearchKeyword.ADD); schemaFields.forEach(field -> args.addParams(field)); return new CommandObject<>(args, BuilderFactory.STRING); } - public CommandObject ftSearch(String indexName, String query) { - return new CommandObject<>(commandArguments(SearchCommand.SEARCH).add(indexName).add(query), - new SearchResultBuilder(true, false, false, true)); + public final CommandObject ftAliasAdd(String aliasName, String indexName) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.ALIASADD, aliasName, indexName), BuilderFactory.STRING); } - public CommandObject ftSearch(String indexName, String query, FTSearchParams params) { - return new CommandObject<>(commandArguments(SearchCommand.SEARCH).add(indexName).add(query).addParams(params), - new SearchResultBuilder(!params.getNoContent(), params.getWithScores(), false, true)); + public final CommandObject ftAliasUpdate(String aliasName, String indexName) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.ALIASUPDATE, aliasName, indexName), BuilderFactory.STRING); } - public CommandObject ftSearch(String indexName, Query query) { - return new CommandObject<>(commandArguments(SearchCommand.SEARCH).add(indexName).addParams(query), - new SearchResultBuilder(!query.getNoContent(), query.getWithScores(), query.getWithPayloads(), true)); + public final CommandObject ftAliasDel(String aliasName) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.ALIASDEL, aliasName), BuilderFactory.STRING); } - public CommandObject ftSearch(byte[] indexName, Query query) { - return new CommandObject<>(commandArguments(SearchCommand.SEARCH).add(indexName).addParams(query), - new SearchResultBuilder(!query.getNoContent(), query.getWithScores(), query.getWithPayloads(), false)); + public final CommandObject ftDropIndex(String indexName) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.DROPINDEX, indexName), BuilderFactory.STRING); } - public CommandObject ftExplain(String indexName, Query query) { - return new CommandObject<>(commandArguments(SearchCommand.EXPLAIN).add(indexName).addParams(query), BuilderFactory.STRING); + public final CommandObject ftDropIndexDD(String indexName) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.DROPINDEX, indexName).add(SearchKeyword.DD), + BuilderFactory.STRING); } - public CommandObject> ftExplainCLI(String indexName, Query query) { - return new CommandObject<>(commandArguments(SearchCommand.EXPLAINCLI).add(indexName).addParams(query), BuilderFactory.STRING_LIST); + public final CommandObject ftSearch(String indexName, String query) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.SEARCH, indexName).add(query), + getSearchResultBuilder(() -> new SearchResultBuilder(true, false, true))); } - public CommandObject ftAggregate(String indexName, AggregationBuilder aggr) { - return new CommandObject<>(commandArguments(SearchCommand.AGGREGATE).add(indexName).addObjects(aggr.getArgs()), - !aggr.isWithCursor() ? SearchBuilderFactory.SEARCH_AGGREGATION_RESULT : SearchBuilderFactory.SEARCH_AGGREGATION_RESULT_WITH_CURSOR); + public final CommandObject ftSearch(String indexName, String query, FTSearchParams params) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.SEARCH, indexName) + .add(query).addParams(params.dialectOptional(searchDialect.get())), + getSearchResultBuilder(() -> new SearchResultBuilder(!params.getNoContent(), params.getWithScores(), true))); } - public CommandObject ftCursorRead(String indexName, long cursorId, int count) { + public final CommandObject ftSearch(String indexName, Query query) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.SEARCH, indexName) + .addParams(query.dialectOptional(searchDialect.get())), getSearchResultBuilder(() -> + new SearchResultBuilder(!query.getNoContent(), query.getWithScores(), true))); + } + + @Deprecated + public final CommandObject ftSearch(byte[] indexName, Query query) { + if (protocol == RedisProtocol.RESP3) { + throw new UnsupportedOperationException("binary ft.search is not implemented with resp3."); + } + return new CommandObject<>(checkAndRoundRobinSearchCommand(commandArguments(SearchCommand.SEARCH), indexName) + .addParams(query.dialectOptional(searchDialect.get())), getSearchResultBuilder(() -> + new SearchResultBuilder(!query.getNoContent(), query.getWithScores(), false))); + } + + public final CommandObject ftExplain(String indexName, Query query) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.EXPLAIN, indexName) + .addParams(query.dialectOptional(searchDialect.get())), BuilderFactory.STRING); + } + + public final CommandObject> ftExplainCLI(String indexName, Query query) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.EXPLAINCLI, indexName) + .addParams(query.dialectOptional(searchDialect.get())), BuilderFactory.STRING_LIST); + } + + public final CommandObject ftAggregate(String indexName, AggregationBuilder aggr) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.AGGREGATE, indexName) + .addParams(aggr.dialectOptional(searchDialect.get())), !aggr.isWithCursor() ? AggregationResult.SEARCH_AGGREGATION_RESULT + : AggregationResult.SEARCH_AGGREGATION_RESULT_WITH_CURSOR); + } + + public final CommandObject ftCursorRead(String indexName, long cursorId, int count) { return new CommandObject<>(commandArguments(SearchCommand.CURSOR).add(SearchKeyword.READ) - .add(indexName).add(cursorId).add(count), SearchBuilderFactory.SEARCH_AGGREGATION_RESULT_WITH_CURSOR); + .key(indexName).add(cursorId).add(SearchKeyword.COUNT).add(count), + AggregationResult.SEARCH_AGGREGATION_RESULT_WITH_CURSOR); } - public CommandObject ftCursorDel(String indexName, long cursorId) { + public final CommandObject ftCursorDel(String indexName, long cursorId) { return new CommandObject<>(commandArguments(SearchCommand.CURSOR).add(SearchKeyword.DEL) - .add(indexName).add(cursorId), BuilderFactory.STRING); + .key(indexName).add(cursorId), BuilderFactory.STRING); } - public CommandObject>> ftProfileAggregate( + public final CommandObject>> ftProfileAggregate( String indexName, FTProfileParams profileParams, AggregationBuilder aggr) { - return new CommandObject<>(commandArguments(SearchCommand.PROFILE).add(indexName) + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.PROFILE, indexName) .add(SearchKeyword.AGGREGATE).addParams(profileParams).add(SearchKeyword.QUERY) - .addObjects(aggr.getArgs()), new SearchProfileResponseBuilder<>(!aggr.isWithCursor() - ? SearchBuilderFactory.SEARCH_AGGREGATION_RESULT - : SearchBuilderFactory.SEARCH_AGGREGATION_RESULT_WITH_CURSOR)); + .addParams(aggr.dialectOptional(searchDialect.get())), new SearchProfileResponseBuilder<>( + !aggr.isWithCursor() ? AggregationResult.SEARCH_AGGREGATION_RESULT + : AggregationResult.SEARCH_AGGREGATION_RESULT_WITH_CURSOR)); } - public CommandObject>> ftProfileSearch( + public final CommandObject>> ftProfileSearch( String indexName, FTProfileParams profileParams, Query query) { - return new CommandObject<>(commandArguments(SearchCommand.PROFILE).add(indexName) + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.PROFILE, indexName) .add(SearchKeyword.SEARCH).addParams(profileParams).add(SearchKeyword.QUERY) - .addParams(query), new SearchProfileResponseBuilder<>(new SearchResultBuilder( - !query.getNoContent(), query.getWithScores(), query.getWithPayloads(), true))); + .addParams(query.dialectOptional(searchDialect.get())), new SearchProfileResponseBuilder<>( + getSearchResultBuilder(() -> new SearchResultBuilder(!query.getNoContent(), query.getWithScores(), true)))); } - public CommandObject>> ftProfileSearch( + public final CommandObject>> ftProfileSearch( String indexName, FTProfileParams profileParams, String query, FTSearchParams searchParams) { - return new CommandObject<>(commandArguments(SearchCommand.PROFILE).add(indexName) + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.PROFILE, indexName) .add(SearchKeyword.SEARCH).addParams(profileParams).add(SearchKeyword.QUERY).add(query) - .addParams(searchParams), new SearchProfileResponseBuilder<>(new SearchResultBuilder( - !searchParams.getNoContent(), searchParams.getWithScores(), false, true))); - } - - public CommandObject ftDropIndex(String indexName) { - return new CommandObject<>(commandArguments(SearchCommand.DROPINDEX).add(indexName), BuilderFactory.STRING); + .addParams(searchParams.dialectOptional(searchDialect.get())), new SearchProfileResponseBuilder<>( + getSearchResultBuilder(() -> new SearchResultBuilder(!searchParams.getNoContent(), searchParams.getWithScores(), true)))); } - public CommandObject ftDropIndexDD(String indexName) { - return new CommandObject<>(commandArguments(SearchCommand.DROPINDEX).add(indexName).add(SearchKeyword.DD), BuilderFactory.STRING); + private Builder getSearchResultBuilder(Supplier> resp2) { + if (protocol == RedisProtocol.RESP3) return SearchResult.SEARCH_RESULT_BUILDER; + return resp2.get(); } - public CommandObject ftSynUpdate(String indexName, String synonymGroupId, String... terms) { - return new CommandObject<>(commandArguments(SearchCommand.SYNUPDATE).add(indexName) + public final CommandObject ftSynUpdate(String indexName, String synonymGroupId, String... terms) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.SYNUPDATE, indexName) .add(synonymGroupId).addObjects((Object[]) terms), BuilderFactory.STRING); } - public CommandObject>> ftSynDump(String indexName) { - return new CommandObject<>(commandArguments(SearchCommand.SYNDUMP).add(indexName), SearchBuilderFactory.SEARCH_SYNONYM_GROUPS); + public final CommandObject>> ftSynDump(String indexName) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.SYNDUMP, indexName), + SearchBuilderFactory.SEARCH_SYNONYM_GROUPS); } public final CommandObject ftDictAdd(String dictionary, String... terms) { - return new CommandObject<>(commandArguments(SearchCommand.DICTADD).add(dictionary).addObjects((Object[]) terms), BuilderFactory.LONG); + return new CommandObject<>(commandArguments(SearchCommand.DICTADD).add(dictionary).addObjects((Object[]) terms), + BuilderFactory.LONG); } public final CommandObject ftDictDel(String dictionary, String... terms) { - return new CommandObject<>(commandArguments(SearchCommand.DICTDEL).add(dictionary).addObjects((Object[]) terms), BuilderFactory.LONG); + return new CommandObject<>(commandArguments(SearchCommand.DICTDEL).add(dictionary).addObjects((Object[]) terms), + BuilderFactory.LONG); } public final CommandObject> ftDictDump(String dictionary) { @@ -3198,62 +3317,53 @@ public final CommandObject> ftDictDump(String dictionary) { } public final CommandObject ftDictAddBySampleKey(String indexName, String dictionary, String... terms) { - return addProcessKey(ftDictAdd(dictionary, terms), indexName); + return directSearchCommand(ftDictAdd(dictionary, terms), indexName); } public final CommandObject ftDictDelBySampleKey(String indexName, String dictionary, String... terms) { - return addProcessKey(ftDictDel(dictionary, terms), indexName); + return directSearchCommand(ftDictDel(dictionary, terms), indexName); } public final CommandObject> ftDictDumpBySampleKey(String indexName, String dictionary) { - return addProcessKey(ftDictDump(dictionary), indexName); + return directSearchCommand(ftDictDump(dictionary), indexName); } public final CommandObject>> ftSpellCheck(String index, String query) { - return new CommandObject<>(commandArguments(SearchCommand.SPELLCHECK).key(index).add(query), + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.SPELLCHECK, index).add(query), SearchBuilderFactory.SEARCH_SPELLCHECK_RESPONSE); } public final CommandObject>> ftSpellCheck(String index, String query, FTSpellCheckParams spellCheckParams) { - return new CommandObject<>(commandArguments(SearchCommand.SPELLCHECK).key(index).add(query) - .addParams(spellCheckParams), SearchBuilderFactory.SEARCH_SPELLCHECK_RESPONSE); - } - - public CommandObject> ftInfo(String indexName) { - return new CommandObject<>(commandArguments(SearchCommand.INFO).add(indexName), BuilderFactory.ENCODED_OBJECT_MAP); - } - - public CommandObject> ftTagVals(String indexName, String fieldName) { - return new CommandObject<>(commandArguments(SearchCommand.TAGVALS).add(indexName).add(fieldName), BuilderFactory.STRING_SET); - } - - public CommandObject ftAliasAdd(String aliasName, String indexName) { - return new CommandObject<>(commandArguments(SearchCommand.ALIASADD).add(aliasName).add(indexName), BuilderFactory.STRING); + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.SPELLCHECK, index).add(query) + .addParams(spellCheckParams.dialectOptional(searchDialect.get())), SearchBuilderFactory.SEARCH_SPELLCHECK_RESPONSE); } - public CommandObject ftAliasUpdate(String aliasName, String indexName) { - return new CommandObject<>(commandArguments(SearchCommand.ALIASUPDATE).add(aliasName).add(indexName), BuilderFactory.STRING); + public final CommandObject> ftInfo(String indexName) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.INFO, indexName), + protocol == RedisProtocol.RESP3 ? BuilderFactory.AGGRESSIVE_ENCODED_OBJECT_MAP : BuilderFactory.ENCODED_OBJECT_MAP); } - public CommandObject ftAliasDel(String aliasName) { - return new CommandObject<>(commandArguments(SearchCommand.ALIASDEL).add(aliasName), BuilderFactory.STRING); + public final CommandObject> ftTagVals(String indexName, String fieldName) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.TAGVALS, indexName) + .add(fieldName), BuilderFactory.STRING_SET); } - public final CommandObject> ftConfigGet(String option) { - return new CommandObject<>(commandArguments(SearchCommand.CONFIG).add(SearchKeyword.GET).add(option), BuilderFactory.STRING_MAP_FROM_PAIRS); + public final CommandObject> ftConfigGet(String option) { + return new CommandObject<>(commandArguments(SearchCommand.CONFIG).add(SearchKeyword.GET).add(option), + protocol == RedisProtocol.RESP3 ? BuilderFactory.AGGRESSIVE_ENCODED_OBJECT_MAP : BuilderFactory.ENCODED_OBJECT_MAP_FROM_PAIRS); } - public CommandObject> ftConfigGet(String indexName, String option) { - return ftConfigGet(option); + public final CommandObject> ftConfigGet(String indexName, String option) { + return directSearchCommand(ftConfigGet(option), indexName); } public final CommandObject ftConfigSet(String option, String value) { return new CommandObject<>(commandArguments(SearchCommand.CONFIG).add(SearchKeyword.SET).add(option).add(value), BuilderFactory.STRING); } - public CommandObject ftConfigSet(String indexName, String option, String value) { - return ftConfigSet(option, value); + public final CommandObject ftConfigSet(String indexName, String option, String value) { + return directSearchCommand(ftConfigSet(option, value), indexName); } public final CommandObject ftSugAdd(String key, String string, double score) { @@ -3276,7 +3386,8 @@ public final CommandObject> ftSugGet(String key, String prefix, boo } public final CommandObject> ftSugGetWithScores(String key, String prefix) { - return new CommandObject<>(commandArguments(SearchCommand.SUGGET).key(key).add(prefix).add(SearchKeyword.WITHSCORES), BuilderFactory.TUPLE_LIST); + return new CommandObject<>(commandArguments(SearchCommand.SUGGET).key(key).add(prefix) + .add(SearchKeyword.WITHSCORES), BuilderFactory.TUPLE_LIST); } public final CommandObject> ftSugGetWithScores(String key, String prefix, boolean fuzzy, int max) { @@ -3295,8 +3406,8 @@ public final CommandObject ftSugLen(String key) { return new CommandObject<>(commandArguments(SearchCommand.SUGLEN).key(key), BuilderFactory.LONG); } - public final CommandObject> ftList() { - return new CommandObject<>(commandArguments(SearchCommand._LIST), BuilderFactory.STRING_LIST); + public final CommandObject> ftList() { + return new CommandObject<>(commandArguments(SearchCommand._LIST), BuilderFactory.STRING_SET); } // RediSearch commands @@ -3306,13 +3417,17 @@ public final CommandObject jsonSet(String key, Path2 path, Object object } public final CommandObject jsonSetWithEscape(String key, Path2 path, Object object) { - return new CommandObject<>(commandArguments(JsonCommand.SET).key(key).add(path).add(GsonJson.toJson(object)), BuilderFactory.STRING); + return new CommandObject<>(commandArguments(JsonCommand.SET).key(key).add(path).add( + getJsonObjectMapper().toJson(object)), BuilderFactory.STRING); } + @Deprecated public final CommandObject jsonSet(String key, Path path, Object pojo) { - return new CommandObject<>(commandArguments(JsonCommand.SET).key(key).add(path).add(GsonJson.toJson(pojo)), BuilderFactory.STRING); + return new CommandObject<>(commandArguments(JsonCommand.SET).key(key).add(path).add( + getJsonObjectMapper().toJson(pojo)), BuilderFactory.STRING); } + @Deprecated public final CommandObject jsonSetWithPlainString(String key, Path path, String string) { return new CommandObject<>(commandArguments(JsonCommand.SET).key(key).add(path).add(string), BuilderFactory.STRING); } @@ -3322,43 +3437,62 @@ public final CommandObject jsonSet(String key, Path2 path, Object object } public final CommandObject jsonSetWithEscape(String key, Path2 path, Object object, JsonSetParams params) { - return new CommandObject<>(commandArguments(JsonCommand.SET).key(key).add(path).add(GsonJson.toJson(object)).addParams(params), BuilderFactory.STRING); + return new CommandObject<>(commandArguments(JsonCommand.SET).key(key).add(path).add( + getJsonObjectMapper().toJson(object)).addParams(params), BuilderFactory.STRING); } + @Deprecated public final CommandObject jsonSet(String key, Path path, Object pojo, JsonSetParams params) { - return new CommandObject<>(commandArguments(JsonCommand.SET).key(key).add(path).add(GsonJson.toJson(pojo)).addParams(params), BuilderFactory.STRING); + return new CommandObject<>(commandArguments(JsonCommand.SET).key(key).add(path).add( + getJsonObjectMapper().toJson(pojo)).addParams(params), BuilderFactory.STRING); + } + + public final CommandObject jsonMerge(String key, Path2 path, Object object) { + return new CommandObject<>(commandArguments(JsonCommand.MERGE).key(key).add(path).add(object), BuilderFactory.STRING); + } + + @Deprecated + public final CommandObject jsonMerge(String key, Path path, Object pojo) { + return new CommandObject<>(commandArguments(JsonCommand.MERGE).key(key).add(path).add( + getJsonObjectMapper().toJson(pojo)), BuilderFactory.STRING); } public final CommandObject jsonGet(String key) { - return new CommandObject<>(commandArguments(JsonCommand.GET).key(key), new GsonObjectBuilder<>(Object.class)); + return new CommandObject<>(commandArguments(JsonCommand.GET).key(key), + protocol != RedisProtocol.RESP3 ? JSON_GENERIC_OBJECT : JsonBuilderFactory.JSON_OBJECT); } + @Deprecated public final CommandObject jsonGet(String key, Class clazz) { - return new CommandObject<>(commandArguments(JsonCommand.GET).key(key), new GsonObjectBuilder<>(clazz)); + return new CommandObject<>(commandArguments(JsonCommand.GET).key(key), new JsonObjectBuilder<>(clazz)); } public final CommandObject jsonGet(String key, Path2... paths) { return new CommandObject<>(commandArguments(JsonCommand.GET).key(key).addObjects((Object[]) paths), JsonBuilderFactory.JSON_OBJECT); } + @Deprecated public final CommandObject jsonGet(String key, Path... paths) { - return new CommandObject<>(commandArguments(JsonCommand.GET).key(key).addObjects((Object[]) paths), new GsonObjectBuilder<>(Object.class)); + return new CommandObject<>(commandArguments(JsonCommand.GET).key(key).addObjects((Object[]) paths), JSON_GENERIC_OBJECT); } + @Deprecated public final CommandObject jsonGetAsPlainString(String key, Path path) { return new CommandObject<>(commandArguments(JsonCommand.GET).key(key).add(path), BuilderFactory.STRING); } + @Deprecated public final CommandObject jsonGet(String key, Class clazz, Path... paths) { - return new CommandObject<>(commandArguments(JsonCommand.GET).key(key).addObjects((Object[]) paths), new GsonObjectBuilder<>(clazz)); + return new CommandObject<>(commandArguments(JsonCommand.GET).key(key).addObjects((Object[]) paths), new JsonObjectBuilder<>(clazz)); } public final CommandObject> jsonMGet(Path2 path, String... keys) { return new CommandObject<>(commandArguments(JsonCommand.MGET).keys((Object[]) keys).add(path), JsonBuilderFactory.JSON_ARRAY_LIST); } + @Deprecated public final CommandObject> jsonMGet(Path path, Class clazz, String... keys) { - return new CommandObject<>(commandArguments(JsonCommand.MGET).keys((Object[]) keys).add(path), new GsonObjectListBuilder<>(clazz)); + return new CommandObject<>(commandArguments(JsonCommand.MGET).keys((Object[]) keys).add(path), new JsonObjectListBuilder<>(clazz)); } public final CommandObject jsonDel(String key) { @@ -3369,6 +3503,7 @@ public final CommandObject jsonDel(String key, Path2 path) { return new CommandObject<>(commandArguments(JsonCommand.DEL).key(key).add(path), BuilderFactory.LONG); } + @Deprecated public final CommandObject jsonDel(String key, Path path) { return new CommandObject<>(commandArguments(JsonCommand.DEL).key(key).add(path), BuilderFactory.LONG); } @@ -3381,6 +3516,7 @@ public final CommandObject jsonClear(String key, Path2 path) { return new CommandObject<>(commandArguments(JsonCommand.CLEAR).key(key).add(path), BuilderFactory.LONG); } + @Deprecated public final CommandObject jsonClear(String key, Path path) { return new CommandObject<>(commandArguments(JsonCommand.CLEAR).key(key).add(path), BuilderFactory.LONG); } @@ -3389,34 +3525,44 @@ public final CommandObject> jsonToggle(String key, Path2 path) { return new CommandObject<>(commandArguments(JsonCommand.TOGGLE).key(key).add(path), BuilderFactory.BOOLEAN_LIST); } + @Deprecated public final CommandObject jsonToggle(String key, Path path) { return new CommandObject<>(commandArguments(JsonCommand.TOGGLE).key(key).add(path), BuilderFactory.STRING); } + @Deprecated public final CommandObject> jsonType(String key) { return new CommandObject<>(commandArguments(JsonCommand.TYPE).key(key), JsonBuilderFactory.JSON_TYPE); } public final CommandObject>> jsonType(String key, Path2 path) { - return new CommandObject<>(commandArguments(JsonCommand.TYPE).key(key).add(path), JsonBuilderFactory.JSON_TYPE_LIST); + return new CommandObject<>(commandArguments(JsonCommand.TYPE).key(key).add(path), + protocol != RedisProtocol.RESP3 ? JsonBuilderFactory.JSON_TYPE_LIST : JsonBuilderFactory.JSON_TYPE_RESPONSE_RESP3_COMPATIBLE); } + @Deprecated public final CommandObject> jsonType(String key, Path path) { return new CommandObject<>(commandArguments(JsonCommand.TYPE).key(key).add(path), JsonBuilderFactory.JSON_TYPE); } + @Deprecated public final CommandObject jsonStrAppend(String key, Object string) { - return new CommandObject<>(commandArguments(JsonCommand.STRAPPEND).key(key).add(GsonJson.toJson(string)), BuilderFactory.LONG); + return new CommandObject<>(commandArguments(JsonCommand.STRAPPEND).key(key).add( + getJsonObjectMapper().toJson(string)), BuilderFactory.LONG); } public final CommandObject> jsonStrAppend(String key, Path2 path, Object string) { - return new CommandObject<>(commandArguments(JsonCommand.STRAPPEND).key(key).add(path).add(GsonJson.toJson(string)), BuilderFactory.LONG_LIST); + return new CommandObject<>(commandArguments(JsonCommand.STRAPPEND).key(key).add(path).add( + getJsonObjectMapper().toJson(string)), BuilderFactory.LONG_LIST); } + @Deprecated public final CommandObject jsonStrAppend(String key, Path path, Object string) { - return new CommandObject<>(commandArguments(JsonCommand.STRAPPEND).key(key).add(path).add(GsonJson.toJson(string)), BuilderFactory.LONG); + return new CommandObject<>(commandArguments(JsonCommand.STRAPPEND).key(key).add(path).add( + getJsonObjectMapper().toJson(string)), BuilderFactory.LONG); } + @Deprecated public final CommandObject jsonStrLen(String key) { return new CommandObject<>(commandArguments(JsonCommand.STRLEN).key(key), BuilderFactory.LONG); } @@ -3425,14 +3571,17 @@ public final CommandObject> jsonStrLen(String key, Path2 path) { return new CommandObject<>(commandArguments(JsonCommand.STRLEN).key(key).add(path), BuilderFactory.LONG_LIST); } + @Deprecated public final CommandObject jsonStrLen(String key, Path path) { return new CommandObject<>(commandArguments(JsonCommand.STRLEN).key(key).add(path), BuilderFactory.LONG); } - public final CommandObject jsonNumIncrBy(String key, Path2 path, double value) { - return new CommandObject<>(commandArguments(JsonCommand.NUMINCRBY).key(key).add(path).add(value), JsonBuilderFactory.JSON_ARRAY); + public final CommandObject jsonNumIncrBy(String key, Path2 path, double value) { + return new CommandObject<>(commandArguments(JsonCommand.NUMINCRBY).key(key).add(path).add(value), + JsonBuilderFactory.JSON_ARRAY_OR_DOUBLE_LIST); } + @Deprecated public final CommandObject jsonNumIncrBy(String key, Path path, double value) { return new CommandObject<>(commandArguments(JsonCommand.NUMINCRBY).key(key).add(path).add(value), BuilderFactory.DOUBLE); } @@ -3453,15 +3602,16 @@ public final CommandObject> jsonArrAppend(String key, Path2 path, Obj public final CommandObject> jsonArrAppendWithEscape(String key, Path2 path, Object... objects) { CommandArguments args = commandArguments(JsonCommand.ARRAPPEND).key(key).add(path); for (Object object : objects) { - args.add(GsonJson.toJson(object)); + args.add(getJsonObjectMapper().toJson(object)); } return new CommandObject<>(args, BuilderFactory.LONG_LIST); } + @Deprecated public final CommandObject jsonArrAppend(String key, Path path, Object... pojos) { CommandArguments args = commandArguments(JsonCommand.ARRAPPEND).key(key).add(path); for (Object pojo : pojos) { - args.add(GsonJson.toJson(pojo)); + args.add(getJsonObjectMapper().toJson(pojo)); } return new CommandObject<>(args, BuilderFactory.LONG); } @@ -3471,11 +3621,14 @@ public final CommandObject> jsonArrIndex(String key, Path2 path, Obje } public final CommandObject> jsonArrIndexWithEscape(String key, Path2 path, Object scalar) { - return new CommandObject<>(commandArguments(JsonCommand.ARRINDEX).key(key).add(path).add(GsonJson.toJson(scalar)), BuilderFactory.LONG_LIST); + return new CommandObject<>(commandArguments(JsonCommand.ARRINDEX).key(key).add(path).add( + getJsonObjectMapper().toJson(scalar)), BuilderFactory.LONG_LIST); } + @Deprecated public final CommandObject jsonArrIndex(String key, Path path, Object scalar) { - return new CommandObject<>(commandArguments(JsonCommand.ARRINDEX).key(key).add(path).add(GsonJson.toJson(scalar)), BuilderFactory.LONG); + return new CommandObject<>(commandArguments(JsonCommand.ARRINDEX).key(key).add(path).add( + getJsonObjectMapper().toJson(scalar)), BuilderFactory.LONG); } public final CommandObject> jsonArrInsert(String key, Path2 path, int index, Object... objects) { @@ -3486,51 +3639,59 @@ public final CommandObject> jsonArrInsert(String key, Path2 path, int public final CommandObject> jsonArrInsertWithEscape(String key, Path2 path, int index, Object... objects) { CommandArguments args = commandArguments(JsonCommand.ARRINSERT).key(key).add(path).add(index); for (Object object : objects) { - args.add(GsonJson.toJson(object)); + args.add(getJsonObjectMapper().toJson(object)); } return new CommandObject<>(args, BuilderFactory.LONG_LIST); } + @Deprecated public final CommandObject jsonArrInsert(String key, Path path, int index, Object... pojos) { CommandArguments args = commandArguments(JsonCommand.ARRINSERT).key(key).add(path).add(index); for (Object pojo : pojos) { - args.add(GsonJson.toJson(pojo)); + args.add(getJsonObjectMapper().toJson(pojo)); } return new CommandObject<>(args, BuilderFactory.LONG); } + @Deprecated public final CommandObject jsonArrPop(String key) { - return new CommandObject<>(commandArguments(JsonCommand.ARRPOP).key(key), new GsonObjectBuilder<>(Object.class)); + return new CommandObject<>(commandArguments(JsonCommand.ARRPOP).key(key), new JsonObjectBuilder<>(Object.class)); } + @Deprecated public final CommandObject jsonArrPop(String key, Class clazz) { - return new CommandObject<>(commandArguments(JsonCommand.ARRPOP).key(key), new GsonObjectBuilder<>(clazz)); + return new CommandObject<>(commandArguments(JsonCommand.ARRPOP).key(key), new JsonObjectBuilder<>(clazz)); } public final CommandObject> jsonArrPop(String key, Path2 path) { - return new CommandObject<>(commandArguments(JsonCommand.ARRPOP).key(key).add(path), new GsonObjectListBuilder<>(Object.class)); + return new CommandObject<>(commandArguments(JsonCommand.ARRPOP).key(key).add(path), new JsonObjectListBuilder<>(Object.class)); } + @Deprecated public final CommandObject jsonArrPop(String key, Path path) { - return new CommandObject<>(commandArguments(JsonCommand.ARRPOP).key(key).add(path), new GsonObjectBuilder<>(Object.class)); + return new CommandObject<>(commandArguments(JsonCommand.ARRPOP).key(key).add(path), new JsonObjectBuilder<>(Object.class)); } + @Deprecated public final CommandObject jsonArrPop(String key, Class clazz, Path path) { - return new CommandObject<>(commandArguments(JsonCommand.ARRPOP).key(key).add(path), new GsonObjectBuilder<>(clazz)); + return new CommandObject<>(commandArguments(JsonCommand.ARRPOP).key(key).add(path), new JsonObjectBuilder<>(clazz)); } public final CommandObject> jsonArrPop(String key, Path2 path, int index) { - return new CommandObject<>(commandArguments(JsonCommand.ARRPOP).key(key).add(path).add(index), new GsonObjectListBuilder<>(Object.class)); + return new CommandObject<>(commandArguments(JsonCommand.ARRPOP).key(key).add(path).add(index), new JsonObjectListBuilder<>(Object.class)); } + @Deprecated public final CommandObject jsonArrPop(String key, Path path, int index) { - return new CommandObject<>(commandArguments(JsonCommand.ARRPOP).key(key).add(path).add(index), new GsonObjectBuilder<>(Object.class)); + return new CommandObject<>(commandArguments(JsonCommand.ARRPOP).key(key).add(path).add(index), new JsonObjectBuilder<>(Object.class)); } + @Deprecated public final CommandObject jsonArrPop(String key, Class clazz, Path path, int index) { - return new CommandObject<>(commandArguments(JsonCommand.ARRPOP).key(key).add(path).add(index), new GsonObjectBuilder<>(clazz)); + return new CommandObject<>(commandArguments(JsonCommand.ARRPOP).key(key).add(path).add(index), new JsonObjectBuilder<>(clazz)); } + @Deprecated public final CommandObject jsonArrLen(String key) { return new CommandObject<>(commandArguments(JsonCommand.ARRLEN).key(key), BuilderFactory.LONG); } @@ -3539,6 +3700,7 @@ public final CommandObject> jsonArrLen(String key, Path2 path) { return new CommandObject<>(commandArguments(JsonCommand.ARRLEN).key(key).add(path), BuilderFactory.LONG_LIST); } + @Deprecated public final CommandObject jsonArrLen(String key, Path path) { return new CommandObject<>(commandArguments(JsonCommand.ARRLEN).key(key).add(path), BuilderFactory.LONG); } @@ -3547,14 +3709,17 @@ public final CommandObject> jsonArrTrim(String key, Path2 path, int s return new CommandObject<>(commandArguments(JsonCommand.ARRTRIM).key(key).add(path).add(start).add(stop), BuilderFactory.LONG_LIST); } + @Deprecated public final CommandObject jsonArrTrim(String key, Path path, int start, int stop) { return new CommandObject<>(commandArguments(JsonCommand.ARRTRIM).key(key).add(path).add(start).add(stop), BuilderFactory.LONG); } + @Deprecated public final CommandObject jsonObjLen(String key) { return new CommandObject<>(commandArguments(JsonCommand.OBJLEN).key(key), BuilderFactory.LONG); } + @Deprecated public final CommandObject jsonObjLen(String key, Path path) { return new CommandObject<>(commandArguments(JsonCommand.OBJLEN).key(key).add(path), BuilderFactory.LONG); } @@ -3563,10 +3728,12 @@ public final CommandObject> jsonObjLen(String key, Path2 path) { return new CommandObject<>(commandArguments(JsonCommand.OBJLEN).key(key).add(path), BuilderFactory.LONG_LIST); } + @Deprecated public final CommandObject> jsonObjKeys(String key) { return new CommandObject<>(commandArguments(JsonCommand.OBJKEYS).key(key), BuilderFactory.STRING_LIST); } + @Deprecated public final CommandObject> jsonObjKeys(String key, Path path) { return new CommandObject<>(commandArguments(JsonCommand.OBJKEYS).key(key).add(path), BuilderFactory.STRING_LIST); } @@ -3575,10 +3742,12 @@ public final CommandObject>> jsonObjKeys(String key, Path2 pat return new CommandObject<>(commandArguments(JsonCommand.OBJKEYS).key(key).add(path), BuilderFactory.STRING_LIST_LIST); } + @Deprecated public final CommandObject jsonDebugMemory(String key) { return new CommandObject<>(commandArguments(JsonCommand.DEBUG).add("MEMORY").key(key), BuilderFactory.LONG); } + @Deprecated public final CommandObject jsonDebugMemory(String key, Path path) { return new CommandObject<>(commandArguments(JsonCommand.DEBUG).add("MEMORY").key(key).add(path), BuilderFactory.LONG); } @@ -3586,18 +3755,6 @@ public final CommandObject jsonDebugMemory(String key, Path path) { public final CommandObject> jsonDebugMemory(String key, Path2 path) { return new CommandObject<>(commandArguments(JsonCommand.DEBUG).add("MEMORY").key(key).add(path), BuilderFactory.LONG_LIST); } - - public final CommandObject> jsonResp(String key) { - return new CommandObject<>(commandArguments(JsonCommand.RESP).key(key), BuilderFactory.ENCODED_OBJECT_LIST); - } - - public final CommandObject> jsonResp(String key, Path path) { - return new CommandObject<>(commandArguments(JsonCommand.RESP).key(key).add(path), BuilderFactory.ENCODED_OBJECT_LIST); - } - - public final CommandObject>> jsonResp(String key, Path2 path) { - return new CommandObject<>(commandArguments(JsonCommand.RESP).key(key).add(path), BuilderFactory.ENCODED_OBJECT_LIST_LIST); - } // RedisJSON commands // RedisTimeSeries commands @@ -3677,26 +3834,26 @@ public final CommandObject> tsRevRange(String key, TSRangeParams .addParams(rangeParams), TimeSeriesBuilderFactory.TIMESERIES_ELEMENT_LIST); } - public final CommandObject> tsMRange(long fromTimestamp, long toTimestamp, String... filters) { + public final CommandObject> tsMRange(long fromTimestamp, long toTimestamp, String... filters) { return new CommandObject<>(commandArguments(TimeSeriesCommand.MRANGE).add(fromTimestamp) .add(toTimestamp).add(TimeSeriesKeyword.FILTER).addObjects((Object[]) filters), - TimeSeriesBuilderFactory.TIMESERIES_MRANGE_RESPONSE); + getTimeseriesMultiRangeResponseBuilder()); } - public final CommandObject> tsMRange(TSMRangeParams multiRangeParams) { + public final CommandObject> tsMRange(TSMRangeParams multiRangeParams) { return new CommandObject<>(commandArguments(TimeSeriesCommand.MRANGE) - .addParams(multiRangeParams), TimeSeriesBuilderFactory.TIMESERIES_MRANGE_RESPONSE); + .addParams(multiRangeParams), getTimeseriesMultiRangeResponseBuilder()); } - public final CommandObject> tsMRevRange(long fromTimestamp, long toTimestamp, String... filters) { + public final CommandObject> tsMRevRange(long fromTimestamp, long toTimestamp, String... filters) { return new CommandObject<>(commandArguments(TimeSeriesCommand.MREVRANGE).add(fromTimestamp) .add(toTimestamp).add(TimeSeriesKeyword.FILTER).addObjects((Object[]) filters), - TimeSeriesBuilderFactory.TIMESERIES_MRANGE_RESPONSE); + getTimeseriesMultiRangeResponseBuilder()); } - public final CommandObject> tsMRevRange(TSMRangeParams multiRangeParams) { + public final CommandObject> tsMRevRange(TSMRangeParams multiRangeParams) { return new CommandObject<>(commandArguments(TimeSeriesCommand.MREVRANGE).addParams(multiRangeParams), - TimeSeriesBuilderFactory.TIMESERIES_MRANGE_RESPONSE); + getTimeseriesMultiRangeResponseBuilder()); } public final CommandObject tsGet(String key) { @@ -3707,9 +3864,11 @@ public final CommandObject tsGet(String key, TSGetParams getParams) { return new CommandObject<>(commandArguments(TimeSeriesCommand.GET).key(key).addParams(getParams), TimeSeriesBuilderFactory.TIMESERIES_ELEMENT); } - public final CommandObject>> tsMGet(TSMGetParams multiGetParams, String... filters) { + public final CommandObject> tsMGet(TSMGetParams multiGetParams, String... filters) { return new CommandObject<>(commandArguments(TimeSeriesCommand.MGET).addParams(multiGetParams) - .add(TimeSeriesKeyword.FILTER).addObjects((Object[]) filters), TimeSeriesBuilderFactory.TIMESERIES_MGET_RESPONSE); + .add(TimeSeriesKeyword.FILTER).addObjects((Object[]) filters), + protocol == RedisProtocol.RESP3 ? TimeSeriesBuilderFactory.TIMESERIES_MGET_RESPONSE_RESP3 + : TimeSeriesBuilderFactory.TIMESERIES_MGET_RESPONSE); } public final CommandObject tsCreateRule(String sourceKey, String destKey, AggregationType aggregationType, @@ -3734,11 +3893,21 @@ public final CommandObject> tsQueryIndex(String... filters) { } public final CommandObject tsInfo(String key) { - return new CommandObject<>(commandArguments(TimeSeriesCommand.INFO).key(key), TSInfo.TIMESERIES_INFO); + return new CommandObject<>(commandArguments(TimeSeriesCommand.INFO).key(key), getTimeseriesInfoBuilder()); } public final CommandObject tsInfoDebug(String key) { - return new CommandObject<>(commandArguments(TimeSeriesCommand.INFO).key(key).add(TimeSeriesKeyword.DEBUG), TSInfo.TIMESERIES_INFO); + return new CommandObject<>(commandArguments(TimeSeriesCommand.INFO).key(key).add(TimeSeriesKeyword.DEBUG), + getTimeseriesInfoBuilder()); + } + + private Builder> getTimeseriesMultiRangeResponseBuilder() { + return protocol == RedisProtocol.RESP3 ? TimeSeriesBuilderFactory.TIMESERIES_MRANGE_RESPONSE_RESP3 + : TimeSeriesBuilderFactory.TIMESERIES_MRANGE_RESPONSE; + } + + private Builder getTimeseriesInfoBuilder() { + return protocol == RedisProtocol.RESP3 ? TSInfo.TIMESERIES_INFO_RESP3 : TSInfo.TIMESERIES_INFO; } // RedisTimeSeries commands @@ -3759,7 +3928,7 @@ public final CommandObject bfAdd(String key, String item) { public final CommandObject> bfMAdd(String key, String... items) { return new CommandObject<>(commandArguments(BloomFilterCommand.MADD).key(key). - addObjects((Object[]) items), BuilderFactory.BOOLEAN_LIST); + addObjects((Object[]) items), BuilderFactory.BOOLEAN_WITH_ERROR_LIST); } public final CommandObject> bfInsert(String key, String... items) { @@ -3863,11 +4032,13 @@ public final CommandObject> cfInfo(String key) { } public final CommandObject cmsInitByDim(String key, long width, long depth) { - return new CommandObject<>(commandArguments(CountMinSketchCommand.INITBYDIM).key(key).add(width).add(depth), BuilderFactory.STRING); + return new CommandObject<>(commandArguments(CountMinSketchCommand.INITBYDIM).key(key).add(width) + .add(depth), BuilderFactory.STRING); } public final CommandObject cmsInitByProb(String key, double error, double probability) { - return new CommandObject<>(commandArguments(CountMinSketchCommand.INITBYPROB).key(key).add(error).add(probability), BuilderFactory.STRING); + return new CommandObject<>(commandArguments(CountMinSketchCommand.INITBYPROB).key(key).add(error) + .add(probability), BuilderFactory.STRING); } public final CommandObject> cmsIncrBy(String key, Map itemIncrements) { @@ -3877,7 +4048,8 @@ public final CommandObject> cmsIncrBy(String key, Map i } public final CommandObject> cmsQuery(String key, String... items) { - return new CommandObject<>(commandArguments(CountMinSketchCommand.QUERY).key(key).addObjects((Object[]) items), BuilderFactory.LONG_LIST); + return new CommandObject<>(commandArguments(CountMinSketchCommand.QUERY).key(key) + .addObjects((Object[]) items), BuilderFactory.LONG_LIST); } public final CommandObject cmsMerge(String destKey, String... keys) { @@ -3921,14 +4093,15 @@ public final CommandObject> topkQuery(String key, String... items) return new CommandObject<>(commandArguments(TopKCommand.QUERY).key(key).addObjects((Object[]) items), BuilderFactory.BOOLEAN_LIST); } - public final CommandObject> topkCount(String key, String... items) { - return new CommandObject<>(commandArguments(TopKCommand.COUNT).key(key).addObjects((Object[]) items), BuilderFactory.LONG_LIST); - } - public final CommandObject> topkList(String key) { return new CommandObject<>(commandArguments(TopKCommand.LIST).key(key), BuilderFactory.STRING_LIST); } + public final CommandObject> topkListWithCount(String key) { + return new CommandObject<>(commandArguments(TopKCommand.LIST).key(key) + .add(RedisBloomKeyword.WITHCOUNT), BuilderFactory.STRING_LONG_MAP); + } + public final CommandObject> topkInfo(String key) { return new CommandObject<>(commandArguments(TopKCommand.INFO).key(key), BuilderFactory.ENCODED_OBJECT_MAP); } @@ -4011,33 +4184,101 @@ public final CommandObject> tdigestByRevRank(String key, long... ra // RedisBloom commands // RedisGraph commands + @Deprecated public final CommandObject> graphList() { return new CommandObject<>(commandArguments(GraphCommand.LIST), BuilderFactory.STRING_LIST); } + @Deprecated public final CommandObject> graphProfile(String graphName, String query) { return new CommandObject<>(commandArguments(GraphCommand.PROFILE).key(graphName).add(query), BuilderFactory.STRING_LIST); } + @Deprecated public final CommandObject> graphExplain(String graphName, String query) { return new CommandObject<>(commandArguments(GraphCommand.EXPLAIN).key(graphName).add(query), BuilderFactory.STRING_LIST); } - public final CommandObject>> graphSlowlog(String graphName) { - return new CommandObject<>(commandArguments(GraphCommand.SLOWLOG).key(graphName), BuilderFactory.STRING_LIST_LIST); + @Deprecated + public final CommandObject>> graphSlowlog(String graphName) { + return new CommandObject<>(commandArguments(GraphCommand.SLOWLOG).key(graphName), BuilderFactory.ENCODED_OBJECT_LIST_LIST); } + @Deprecated public final CommandObject graphConfigSet(String configName, Object value) { return new CommandObject<>(commandArguments(GraphCommand.CONFIG).add(GraphKeyword.SET).add(configName).add(value), BuilderFactory.STRING); } + @Deprecated public final CommandObject> graphConfigGet(String configName) { return new CommandObject<>(commandArguments(GraphCommand.CONFIG).add(GraphKeyword.GET).add(configName), BuilderFactory.ENCODED_OBJECT_MAP); } // RedisGraph commands + // RedisGears commands + public final CommandObject tFunctionLoad(String libraryCode, TFunctionLoadParams params) { + return new CommandObject<>(commandArguments(GearsCommand.TFUNCTION).add(GearsKeyword.LOAD) + .addParams(params).add(libraryCode), BuilderFactory.STRING); + } + + public final CommandObject tFunctionDelete(String libraryName) { + return new CommandObject<>(commandArguments(GearsCommand.TFUNCTION).add(GearsKeyword.DELETE) + .add(libraryName), BuilderFactory.STRING); + } + + public final CommandObject> tFunctionList(TFunctionListParams params) { + return new CommandObject<>(commandArguments(GearsCommand.TFUNCTION).add(GearsKeyword.LIST) + .addParams(params), GearsLibraryInfo.GEARS_LIBRARY_INFO_LIST); + } + + public final CommandObject tFunctionCall(String library, String function, List keys, List args) { + return new CommandObject<>(commandArguments(GearsCommand.TFCALL).add(library + "." + function) + .add(keys.size()).keys(keys).addObjects(args), BuilderFactory.AGGRESSIVE_ENCODED_OBJECT); + } + + public final CommandObject tFunctionCallAsync(String library, String function, List keys, List args) { + return new CommandObject<>(commandArguments(GearsCommand.TFCALLASYNC).add(library + "." + function) + .add(keys.size()).keys(keys).addObjects(args), BuilderFactory.AGGRESSIVE_ENCODED_OBJECT); + } + // RedisGears commands + + /** + * Get the instance for JsonObjectMapper if not null, otherwise a new instance reference with + * default implementation will be created and returned. + *

This process of checking whether or not + * the instance reference exists follows 'double-checked lock optimization' approach to reduce the overhead of + * acquiring a lock by testing the lock criteria (the "lock hint") before acquiring the lock.

+ * @return the JsonObjectMapper instance reference + * @see DefaultGsonObjectMapper + */ + private JsonObjectMapper getJsonObjectMapper() { + JsonObjectMapper localRef = this.jsonObjectMapper; + if (Objects.isNull(localRef)) { + synchronized (this) { + localRef = this.jsonObjectMapper; + if (Objects.isNull(localRef)) { + this.jsonObjectMapper = localRef = new DefaultGsonObjectMapper(); + } + } + } + return localRef; + } + + public void setJsonObjectMapper(JsonObjectMapper jsonObjectMapper) { + this.jsonObjectMapper = jsonObjectMapper; + } + + public void setDefaultSearchDialect(int dialect) { + if (dialect == 0) throw new IllegalArgumentException("DIALECT=0 cannot be set."); + this.searchDialect.set(dialect); + } + private class SearchProfileResponseBuilder extends Builder>> { + private static final String PROFILE_STR = "profile"; + private final Builder replyBuilder; public SearchProfileResponseBuilder(Builder replyBuilder) { @@ -4046,30 +4287,47 @@ public SearchProfileResponseBuilder(Builder replyBuilder) { @Override public Map.Entry> build(Object data) { - List list = (List) data; + List list = (List) data; + if (list == null || list.isEmpty()) return null; + + if (list.get(0) instanceof KeyValue) { + for (KeyValue keyValue : (List) data) { + if (PROFILE_STR.equals(BuilderFactory.STRING.build(keyValue.getKey()))) { + return KeyValue.of(replyBuilder.build(data), + BuilderFactory.AGGRESSIVE_ENCODED_OBJECT_MAP.build(keyValue.getValue())); + } + } + } + return KeyValue.of(replyBuilder.build(list.get(0)), SearchBuilderFactory.SEARCH_PROFILE_PROFILE.build(list.get(1))); } } - private class GsonObjectBuilder extends Builder { + + private class JsonObjectBuilder extends Builder { private final Class clazz; - public GsonObjectBuilder(Class clazz) { + public JsonObjectBuilder(Class clazz) { this.clazz = clazz; } @Override public T build(Object data) { - return GsonJson.fromJson(BuilderFactory.STRING.build(data), clazz); + return getJsonObjectMapper().fromJson(BuilderFactory.STRING.build(data), clazz); } } - private class GsonObjectListBuilder extends Builder> { + /** + * {@link JsonObjectBuilder} for {@code Object.class}. + */ + private final Builder JSON_GENERIC_OBJECT = new JsonObjectBuilder<>(Object.class); + + private class JsonObjectListBuilder extends Builder> { private final Class clazz; - public GsonObjectListBuilder(Class clazz) { + public JsonObjectListBuilder(Class clazz) { this.clazz = clazz; } @@ -4079,7 +4337,7 @@ public List build(Object data) { return null; } List list = BuilderFactory.STRING_LIST.build(data); - return list.stream().map(s -> GsonJson.fromJson(s, clazz)).collect(Collectors.toList()); + return list.stream().map(s -> getJsonObjectMapper().fromJson(s, clazz)).collect(Collectors.toList()); } } @@ -4144,9 +4402,4 @@ private CommandArguments addGeoCoordinateFlatMapArgs(CommandArguments args, Map< } return args; } - - private CommandObject addProcessKey(CommandObject object, String sampleKey) { - object.getArguments().processKey(sampleKey); - return object; - } } diff --git a/src/main/java/redis/clients/jedis/Connection.java b/src/main/java/redis/clients/jedis/Connection.java index 868ea26eba..50243e20d7 100644 --- a/src/main/java/redis/clients/jedis/Connection.java +++ b/src/main/java/redis/clients/jedis/Connection.java @@ -1,25 +1,35 @@ package redis.clients.jedis; +import static redis.clients.jedis.util.SafeEncoder.encode; + import java.io.Closeable; import java.io.IOException; import java.net.Socket; import java.net.SocketException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.function.Supplier; +import redis.clients.jedis.Protocol.Command; +import redis.clients.jedis.Protocol.Keyword; +import redis.clients.jedis.args.ClientAttributeOption; import redis.clients.jedis.args.Rawable; import redis.clients.jedis.commands.ProtocolCommand; import redis.clients.jedis.exceptions.JedisConnectionException; import redis.clients.jedis.exceptions.JedisDataException; import redis.clients.jedis.exceptions.JedisException; +import redis.clients.jedis.exceptions.JedisValidationException; import redis.clients.jedis.util.IOUtils; import redis.clients.jedis.util.RedisInputStream; import redis.clients.jedis.util.RedisOutputStream; -import redis.clients.jedis.util.SafeEncoder; public class Connection implements Closeable { private ConnectionPool memberOf; + private RedisProtocol protocol; private final JedisSocketFactory socketFactory; private Socket socket; private RedisOutputStream outputStream; @@ -46,6 +56,10 @@ public Connection(final HostAndPort hostAndPort, final JedisClientConfig clientC initializeFromClientConfig(clientConfig); } + public Connection(final JedisSocketFactory socketFactory) { + this.socketFactory = socketFactory; + } + public Connection(final JedisSocketFactory socketFactory, JedisClientConfig clientConfig) { this.socketFactory = socketFactory; this.soTimeout = clientConfig.getSocketTimeoutMillis(); @@ -53,15 +67,15 @@ public Connection(final JedisSocketFactory socketFactory, JedisClientConfig clie initializeFromClientConfig(clientConfig); } - public Connection(final JedisSocketFactory socketFactory) { - this.socketFactory = socketFactory; - } - @Override public String toString() { return "Connection{" + socketFactory + "}"; } + public final RedisProtocol getRedisProtocol() { + return protocol; + } + public final void setHandlingPool(final ConnectionPool pool) { this.memberOf = pool; } @@ -182,13 +196,21 @@ public void connect() throws JedisConnectionException { outputStream = new RedisOutputStream(socket.getOutputStream()); inputStream = new RedisInputStream(socket.getInputStream()); + + broken = false; // unset broken status when connection is (re)initialized + } catch (JedisConnectionException jce) { - broken = true; + + setBroken(); throw jce; + } catch (IOException ioe) { - broken = true; + + setBroken(); throw new JedisConnectionException("Failed to create input/output stream", ioe); + } finally { + if (broken) { IOUtils.closeQuietly(socket); } @@ -211,16 +233,19 @@ public void close() { } } + /** + * Close the socket and disconnect the server. + */ public void disconnect() { if (isConnected()) { try { outputStream.flush(); socket.close(); } catch (IOException ex) { - broken = true; throw new JedisConnectionException(ex); } finally { IOUtils.closeQuietly(socket); + setBroken(); } } } @@ -244,14 +269,14 @@ public String getStatusCodeReply() { if (null == resp) { return null; } else { - return SafeEncoder.encode(resp); + return encode(resp); } } public String getBulkReply() { final byte[] result = getBinaryBulkReply(); if (null != result) { - return SafeEncoder.encode(result); + return encode(result); } else { return null; } @@ -277,14 +302,23 @@ public List getBinaryMultiBulkReply() { return (List) readProtocolWithCheckingBroken(); } + /** + * @deprecated Use {@link Connection#getUnflushedObject()}. + */ + @Deprecated @SuppressWarnings("unchecked") public List getUnflushedObjectMultiBulkReply() { return (List) readProtocolWithCheckingBroken(); } + @SuppressWarnings("unchecked") + public Object getUnflushedObject() { + return readProtocolWithCheckingBroken(); + } + public List getObjectMultiBulkReply() { flush(); - return getUnflushedObjectMultiBulkReply(); + return (List) readProtocolWithCheckingBroken(); } @SuppressWarnings("unchecked") @@ -314,6 +348,9 @@ protected Object readProtocolWithCheckingBroken() { try { return Protocol.read(inputStream); +// Object read = Protocol.read(inputStream); +// System.out.println(SafeEncoder.encodeObject(read)); +// return read; } catch (JedisConnectionException exc) { broken = true; throw exc; @@ -333,70 +370,144 @@ public List getMany(final int count) { return responses; } - private void initializeFromClientConfig(JedisClientConfig config) { + /** + * Check if the client name libname, libver, characters are legal + * @param info the name + * @return Returns true if legal, false throws exception + * @throws JedisException if characters illegal + */ + private static boolean validateClientInfo(String info) { + for (int i = 0; i < info.length(); i++) { + char c = info.charAt(i); + if (c < '!' || c > '~') { + throw new JedisValidationException("client info cannot contain spaces, " + + "newlines or special characters."); + } + } + return true; + } + + private void initializeFromClientConfig(final JedisClientConfig config) { try { connect(); - String password = config.getPassword(); - if (password != null) { - String user = config.getUser(); - if (user != null) { - auth(user, password); - } else { - auth(password); + + protocol = config.getRedisProtocol(); + + final Supplier credentialsProvider = config.getCredentialsProvider(); + if (credentialsProvider instanceof RedisCredentialsProvider) { + final RedisCredentialsProvider redisCredentialsProvider = (RedisCredentialsProvider) credentialsProvider; + try { + redisCredentialsProvider.prepare(); + helloOrAuth(protocol, redisCredentialsProvider.get()); + } finally { + redisCredentialsProvider.cleanUp(); + } + } else { + helloOrAuth(protocol, credentialsProvider != null ? credentialsProvider.get() + : new DefaultRedisCredentials(config.getUser(), config.getPassword())); + } + + List fireAndForgetMsg = new ArrayList<>(); + + String clientName = config.getClientName(); + if (clientName != null && validateClientInfo(clientName)) { + fireAndForgetMsg.add(new CommandArguments(Command.CLIENT).add(Keyword.SETNAME).add(clientName)); + } + + ClientSetInfoConfig setInfoConfig = config.getClientSetInfoConfig(); + if (setInfoConfig == null) setInfoConfig = ClientSetInfoConfig.DEFAULT; + + if (!setInfoConfig.isDisabled()) { + String libName = JedisMetaInfo.getArtifactId(); + if (libName != null && validateClientInfo(libName)) { + String libNameSuffix = setInfoConfig.getLibNameSuffix(); + if (libNameSuffix != null) { // validation is moved into ClientSetInfoConfig constructor + libName = libName + '(' + libNameSuffix + ')'; + } + fireAndForgetMsg.add(new CommandArguments(Command.CLIENT).add(Keyword.SETINFO) + .add(ClientAttributeOption.LIB_NAME.getRaw()).add(libName)); + } + + String libVersion = JedisMetaInfo.getVersion(); + if (libVersion != null && validateClientInfo(libVersion)) { + fireAndForgetMsg.add(new CommandArguments(Command.CLIENT).add(Keyword.SETINFO) + .add(ClientAttributeOption.LIB_VER.getRaw()).add(libVersion)); } } + + for (CommandArguments arg : fireAndForgetMsg) { + sendCommand(arg); + } + getMany(fireAndForgetMsg.size()); + int dbIndex = config.getDatabase(); if (dbIndex > 0) { select(dbIndex); } - String clientName = config.getClientName(); - if (clientName != null) { - // TODO: need to figure out something without encoding - clientSetname(clientName); - } + } catch (JedisException je) { try { - if (isConnected()) { - quit(); - } disconnect(); } catch (Exception e) { - // + // the first exception 'je' will be thrown } throw je; } } - private String auth(final String password) { - sendCommand(Protocol.Command.AUTH, password); - return getStatusCodeReply(); - } + private void helloOrAuth(final RedisProtocol protocol, final RedisCredentials credentials) { - private String auth(final String user, final String password) { - sendCommand(Protocol.Command.AUTH, user, password); - return getStatusCodeReply(); - } + if (credentials == null || credentials.getPassword() == null) { + if (protocol != null) { + sendCommand(Command.HELLO, encode(protocol.version())); + getOne(); + } + return; + } - public String select(final int index) { - sendCommand(Protocol.Command.SELECT, Protocol.toByteArray(index)); - return getStatusCodeReply(); - } + // Source: https://stackoverflow.com/a/9670279/4021802 + ByteBuffer passBuf = Protocol.CHARSET.encode(CharBuffer.wrap(credentials.getPassword())); + byte[] rawPass = Arrays.copyOfRange(passBuf.array(), passBuf.position(), passBuf.limit()); + Arrays.fill(passBuf.array(), (byte) 0); // clear sensitive data - private String clientSetname(final String name) { - sendCommand(Protocol.Command.CLIENT, Protocol.Keyword.SETNAME.name(), name); - return getStatusCodeReply(); + try { + /// actual HELLO or AUTH --> + if (protocol != null) { + if (credentials.getUser() != null) { + sendCommand(Command.HELLO, encode(protocol.version()), + Keyword.AUTH.getRaw(), encode(credentials.getUser()), rawPass); + getOne(); // Map + } else { + sendCommand(Command.AUTH, rawPass); + getStatusCodeReply(); // OK + sendCommand(Command.HELLO, encode(protocol.version())); + getOne(); // Map + } + } else { // protocol == null + if (credentials.getUser() != null) { + sendCommand(Command.AUTH, encode(credentials.getUser()), rawPass); + } else { + sendCommand(Command.AUTH, rawPass); + } + getStatusCodeReply(); // OK + } + /// <-- actual HELLO or AUTH + } finally { + + Arrays.fill(rawPass, (byte) 0); // clear sensitive data + } + + // clearing 'char[] credentials.getPassword()' should be + // handled in RedisCredentialsProvider.cleanUp() } - public String quit() { - sendCommand(Protocol.Command.QUIT); - String quitReturn = getStatusCodeReply(); - disconnect(); - setBroken(); - return quitReturn; + public String select(final int index) { + sendCommand(Command.SELECT, Protocol.toByteArray(index)); + return getStatusCodeReply(); } public boolean ping() { - sendCommand(Protocol.Command.PING); + sendCommand(Command.PING); String status = getStatusCodeReply(); if (!"PONG".equals(status)) { throw new JedisException(status); diff --git a/src/main/java/redis/clients/jedis/ConnectionFactory.java b/src/main/java/redis/clients/jedis/ConnectionFactory.java index 9df2ac25e3..d286462347 100644 --- a/src/main/java/redis/clients/jedis/ConnectionFactory.java +++ b/src/main/java/redis/clients/jedis/ConnectionFactory.java @@ -35,10 +35,6 @@ public ConnectionFactory(final JedisSocketFactory jedisSocketFactory, final Jedi this.jedisSocketFactory = jedisSocketFactory; } - public void setPassword(final String password) { - this.clientConfig.updatePassword(password); - } - @Override public void activateObject(PooledObject pooledConnection) throws Exception { // what to do ?? @@ -48,14 +44,6 @@ public void activateObject(PooledObject pooledConnection) throws Exc public void destroyObject(PooledObject pooledConnection) throws Exception { final Connection jedis = pooledConnection.getObject(); if (jedis.isConnected()) { - try { - // need a proper test, probably with mock - if (!jedis.isBroken()) { - jedis.quit(); - } - } catch (RuntimeException e) { - logger.debug("Error while QUIT", e); - } try { jedis.close(); } catch (RuntimeException e) { @@ -69,21 +57,9 @@ public PooledObject makeObject() throws Exception { Connection jedis = null; try { jedis = new Connection(jedisSocketFactory, clientConfig); - jedis.connect(); return new DefaultPooledObject<>(jedis); } catch (JedisException je) { - if (jedis != null) { - try { - jedis.quit(); - } catch (RuntimeException e) { - logger.debug("Error while QUIT", e); - } - try { - jedis.close(); - } catch (RuntimeException e) { - logger.debug("Error while close", e); - } - } + logger.debug("Error while makeObject", je); throw je; } } diff --git a/src/main/java/redis/clients/jedis/DefaultJedisClientConfig.java b/src/main/java/redis/clients/jedis/DefaultJedisClientConfig.java index 630f36f262..6d62646a5e 100644 --- a/src/main/java/redis/clients/jedis/DefaultJedisClientConfig.java +++ b/src/main/java/redis/clients/jedis/DefaultJedisClientConfig.java @@ -1,18 +1,19 @@ package redis.clients.jedis; -import java.util.Objects; +import java.util.function.Supplier; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLSocketFactory; public final class DefaultJedisClientConfig implements JedisClientConfig { + private final RedisProtocol redisProtocol; + private final int connectionTimeoutMillis; private final int socketTimeoutMillis; private final int blockingSocketTimeoutMillis; - private final String user; - private volatile String password; + private volatile Supplier credentialsProvider; private final int database; private final String clientName; @@ -23,15 +24,18 @@ public final class DefaultJedisClientConfig implements JedisClientConfig { private final HostAndPortMapper hostAndPortMapper; - private DefaultJedisClientConfig(int connectionTimeoutMillis, int soTimeoutMillis, - int blockingSocketTimeoutMillis, String user, String password, int database, String clientName, - boolean ssl, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, - HostnameVerifier hostnameVerifier, HostAndPortMapper hostAndPortMapper) { + private final ClientSetInfoConfig clientSetInfoConfig; + + private DefaultJedisClientConfig(RedisProtocol protocol, int connectionTimeoutMillis, int soTimeoutMillis, + int blockingSocketTimeoutMillis, Supplier credentialsProvider, int database, + String clientName, boolean ssl, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, + HostnameVerifier hostnameVerifier, HostAndPortMapper hostAndPortMapper, + ClientSetInfoConfig clientSetInfoConfig) { + this.redisProtocol = protocol; this.connectionTimeoutMillis = connectionTimeoutMillis; this.socketTimeoutMillis = soTimeoutMillis; this.blockingSocketTimeoutMillis = blockingSocketTimeoutMillis; - this.user = user; - this.password = password; + this.credentialsProvider = credentialsProvider; this.database = database; this.clientName = clientName; this.ssl = ssl; @@ -39,6 +43,12 @@ private DefaultJedisClientConfig(int connectionTimeoutMillis, int soTimeoutMilli this.sslParameters = sslParameters; this.hostnameVerifier = hostnameVerifier; this.hostAndPortMapper = hostAndPortMapper; + this.clientSetInfoConfig = clientSetInfoConfig; + } + + @Override + public RedisProtocol getRedisProtocol() { + return redisProtocol; } @Override @@ -58,19 +68,18 @@ public int getBlockingSocketTimeoutMillis() { @Override public String getUser() { - return user; + return credentialsProvider.get().getUser(); } @Override public String getPassword() { - return password; + char[] password = credentialsProvider.get().getPassword(); + return password == null ? null : new String(password); } @Override - public synchronized void updatePassword(String password) { - if (!Objects.equals(this.password, password)) { - this.password = password; - } + public Supplier getCredentialsProvider() { + return credentialsProvider; } @Override @@ -108,18 +117,26 @@ public HostAndPortMapper getHostAndPortMapper() { return hostAndPortMapper; } + @Override + public ClientSetInfoConfig getClientSetInfoConfig() { + return clientSetInfoConfig; + } + public static Builder builder() { return new Builder(); } public static class Builder { + private RedisProtocol redisProtocol = null; + private int connectionTimeoutMillis = Protocol.DEFAULT_TIMEOUT; private int socketTimeoutMillis = Protocol.DEFAULT_TIMEOUT; private int blockingSocketTimeoutMillis = 0; private String user = null; private String password = null; + private Supplier credentialsProvider; private int database = Protocol.DEFAULT_DATABASE; private String clientName = null; @@ -130,13 +147,32 @@ public static class Builder { private HostAndPortMapper hostAndPortMapper = null; + private ClientSetInfoConfig clientSetInfoConfig = ClientSetInfoConfig.DEFAULT; + private Builder() { } public DefaultJedisClientConfig build() { - return new DefaultJedisClientConfig(connectionTimeoutMillis, socketTimeoutMillis, - blockingSocketTimeoutMillis, user, password, database, clientName, ssl, sslSocketFactory, - sslParameters, hostnameVerifier, hostAndPortMapper); + if (credentialsProvider == null) { + credentialsProvider = new DefaultRedisCredentialsProvider( + new DefaultRedisCredentials(user, password)); + } + + return new DefaultJedisClientConfig(redisProtocol, connectionTimeoutMillis, socketTimeoutMillis, + blockingSocketTimeoutMillis, credentialsProvider, database, clientName, ssl, + sslSocketFactory, sslParameters, hostnameVerifier, hostAndPortMapper, clientSetInfoConfig); + } + + /** + * Shortcut to {@link Builder#protocol(redis.clients.jedis.RedisProtocol)} with {@link RedisProtocol#RESP3}. + */ + public Builder resp3() { + return protocol(RedisProtocol.RESP3); + } + + public Builder protocol(RedisProtocol protocol) { + this.redisProtocol = protocol; + return this; } public Builder timeoutMillis(int timeoutMillis) { @@ -170,6 +206,16 @@ public Builder password(String password) { return this; } + public Builder credentials(RedisCredentials credentials) { + this.credentialsProvider = new DefaultRedisCredentialsProvider(credentials); + return this; + } + + public Builder credentialsProvider(Supplier credentials) { + this.credentialsProvider = credentials; + return this; + } + public Builder database(int database) { this.database = database; return this; @@ -204,22 +250,29 @@ public Builder hostAndPortMapper(HostAndPortMapper hostAndPortMapper) { this.hostAndPortMapper = hostAndPortMapper; return this; } + + public Builder clientSetInfoConfig(ClientSetInfoConfig setInfoConfig) { + this.clientSetInfoConfig = setInfoConfig; + return this; + } } public static DefaultJedisClientConfig create(int connectionTimeoutMillis, int soTimeoutMillis, int blockingSocketTimeoutMillis, String user, String password, int database, String clientName, boolean ssl, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier, HostAndPortMapper hostAndPortMapper) { - return new DefaultJedisClientConfig(connectionTimeoutMillis, soTimeoutMillis, - blockingSocketTimeoutMillis, user, password, database, clientName, ssl, - sslSocketFactory, sslParameters, hostnameVerifier, hostAndPortMapper); + return new DefaultJedisClientConfig(null, + connectionTimeoutMillis, soTimeoutMillis, blockingSocketTimeoutMillis, + new DefaultRedisCredentialsProvider(new DefaultRedisCredentials(user, password)), database, + clientName, ssl, sslSocketFactory, sslParameters, hostnameVerifier, hostAndPortMapper, null); } public static DefaultJedisClientConfig copyConfig(JedisClientConfig copy) { - return new DefaultJedisClientConfig(copy.getConnectionTimeoutMillis(), - copy.getSocketTimeoutMillis(), copy.getBlockingSocketTimeoutMillis(), copy.getUser(), - copy.getPassword(), copy.getDatabase(), copy.getClientName(), copy.isSsl(), - copy.getSslSocketFactory(), copy.getSslParameters(), copy.getHostnameVerifier(), - copy.getHostAndPortMapper()); + return new DefaultJedisClientConfig(copy.getRedisProtocol(), + copy.getConnectionTimeoutMillis(), copy.getSocketTimeoutMillis(), + copy.getBlockingSocketTimeoutMillis(), copy.getCredentialsProvider(), + copy.getDatabase(), copy.getClientName(), copy.isSsl(), copy.getSslSocketFactory(), + copy.getSslParameters(), copy.getHostnameVerifier(), copy.getHostAndPortMapper(), + copy.getClientSetInfoConfig()); } } diff --git a/src/main/java/redis/clients/jedis/DefaultJedisSocketFactory.java b/src/main/java/redis/clients/jedis/DefaultJedisSocketFactory.java index f9c7cd2228..a2d963e221 100644 --- a/src/main/java/redis/clients/jedis/DefaultJedisSocketFactory.java +++ b/src/main/java/redis/clients/jedis/DefaultJedisSocketFactory.java @@ -70,7 +70,9 @@ private Socket connectToFirstSuccessfulHost(HostAndPort hostAndPort) throws Exce socket.setTcpNoDelay(true); // Socket buffer Whetherclosed, to ensure timely delivery of data socket.setSoLinger(true, 0); // Control calls close () method, the underlying socket is closed immediately - socket.connect(new InetSocketAddress(host.getHostAddress(), hostAndPort.getPort()), connectionTimeout); + // Passing 'host' directly will avoid another call to InetAddress.getByName() inside the InetSocketAddress constructor. + // For machines with ipv4 and ipv6, but the startNode uses ipv4 to connect, the ipv6 connection may fail. + socket.connect(new InetSocketAddress(host, hostAndPort.getPort()), connectionTimeout); return socket; } catch (Exception e) { jce.addSuppressed(e); diff --git a/src/main/java/redis/clients/jedis/DefaultRedisCredentials.java b/src/main/java/redis/clients/jedis/DefaultRedisCredentials.java new file mode 100644 index 0000000000..0adf5de1ed --- /dev/null +++ b/src/main/java/redis/clients/jedis/DefaultRedisCredentials.java @@ -0,0 +1,38 @@ +package redis.clients.jedis; + +public final class DefaultRedisCredentials implements RedisCredentials { + + private final String user; + private final char[] password; + + public DefaultRedisCredentials(String user, char[] password) { + this.user = user; + this.password = password; + } + + public DefaultRedisCredentials(String user, CharSequence password) { + this.user = user; + this.password = password == null ? null + : password instanceof String ? ((String) password).toCharArray() + : toCharArray(password); + } + + @Override + public String getUser() { + return user; + } + + @Override + public char[] getPassword() { + return password; + } + + private static char[] toCharArray(CharSequence seq) { + final int len = seq.length(); + char[] arr = new char[len]; + for (int i = 0; i < len; i++) { + arr[i] = seq.charAt(i); + } + return arr; + } +} diff --git a/src/main/java/redis/clients/jedis/DefaultRedisCredentialsProvider.java b/src/main/java/redis/clients/jedis/DefaultRedisCredentialsProvider.java new file mode 100644 index 0000000000..9ea39ab426 --- /dev/null +++ b/src/main/java/redis/clients/jedis/DefaultRedisCredentialsProvider.java @@ -0,0 +1,19 @@ +package redis.clients.jedis; + +public final class DefaultRedisCredentialsProvider implements RedisCredentialsProvider { + + private volatile RedisCredentials credentials; + + public DefaultRedisCredentialsProvider(RedisCredentials credentials) { + this.credentials = credentials; + } + + public void setCredentials(RedisCredentials credentials) { + this.credentials = credentials; + } + + @Override + public RedisCredentials get() { + return this.credentials; + } +} diff --git a/src/main/java/redis/clients/jedis/GsonJson.java b/src/main/java/redis/clients/jedis/GsonJson.java deleted file mode 100644 index 0da481f0ef..0000000000 --- a/src/main/java/redis/clients/jedis/GsonJson.java +++ /dev/null @@ -1,16 +0,0 @@ -package redis.clients.jedis; - -import com.google.gson.Gson; - -class GsonJson { - - private static final Gson GSON = new Gson(); - - static T fromJson(final String json, final Class classOfT) { - return GSON.fromJson(json, classOfT); - } - - static String toJson(final Object src) { - return GSON.toJson(src); - } -} diff --git a/src/main/java/redis/clients/jedis/Jedis.java b/src/main/java/redis/clients/jedis/Jedis.java index 9f372563b5..181fe279a2 100644 --- a/src/main/java/redis/clients/jedis/Jedis.java +++ b/src/main/java/redis/clients/jedis/Jedis.java @@ -73,6 +73,8 @@ public Jedis(final String host, final int port, final JedisClientConfig config) public Jedis(final HostAndPort hostPort, final JedisClientConfig config) { connection = new Connection(hostPort, config); + RedisProtocol proto = config.getRedisProtocol(); + if (proto != null) commandObjects.setProtocol(proto); } public Jedis(final String host, final int port, final boolean ssl) { @@ -149,6 +151,7 @@ public Jedis(URI uri) { connection = new Connection(new HostAndPort(uri.getHost(), uri.getPort()), DefaultJedisClientConfig.builder().user(JedisURIHelper.getUser(uri)) .password(JedisURIHelper.getPassword(uri)).database(JedisURIHelper.getDBIndex(uri)) + .protocol(JedisURIHelper.getRedisProtocol(uri)) .ssl(JedisURIHelper.isRedisSSLScheme(uri)).build()); } @@ -201,9 +204,12 @@ public Jedis(final URI uri, JedisClientConfig config) { .blockingSocketTimeoutMillis(config.getBlockingSocketTimeoutMillis()) .user(JedisURIHelper.getUser(uri)).password(JedisURIHelper.getPassword(uri)) .database(JedisURIHelper.getDBIndex(uri)).clientName(config.getClientName()) + .protocol(JedisURIHelper.getRedisProtocol(uri)) .ssl(JedisURIHelper.isRedisSSLScheme(uri)).sslSocketFactory(config.getSslSocketFactory()) .sslParameters(config.getSslParameters()).hostnameVerifier(config.getHostnameVerifier()) .build()); + RedisProtocol proto = config.getRedisProtocol(); + if (proto != null) commandObjects.setProtocol(proto); } public Jedis(final JedisSocketFactory jedisSocketFactory) { @@ -212,6 +218,8 @@ public Jedis(final JedisSocketFactory jedisSocketFactory) { public Jedis(final JedisSocketFactory jedisSocketFactory, final JedisClientConfig clientConfig) { connection = new Connection(jedisSocketFactory, clientConfig); + RedisProtocol proto = clientConfig.getRedisProtocol(); + if (proto != null) commandObjects.setProtocol(proto); } public Jedis(final Connection connection) { @@ -237,7 +245,9 @@ public void connect() { connection.connect(); } - // Legacy + /** + * Closing the socket will disconnect the server connection. + */ public void disconnect() { connection.disconnect(); } @@ -319,6 +329,95 @@ public int getDB() { return this.db; } + /** + * @return PONG + */ + @Override + public String ping() { + checkIsInMultiOrPipeline(); + connection.sendCommand(Command.PING); + return connection.getStatusCodeReply(); + } + + /** + * Works same as {@link Jedis#ping()} but returns argument message instead of PONG. + * @param message + * @return message + */ + public byte[] ping(final byte[] message) { + checkIsInMultiOrPipeline(); + connection.sendCommand(Command.PING, message); + return connection.getBinaryBulkReply(); + } + + /** + * Select the DB with having the specified zero-based numeric index. For default every new + * connection is automatically selected to DB 0. + * @param index + * @return OK + */ + @Override + public String select(final int index) { + checkIsInMultiOrPipeline(); + connection.sendCommand(SELECT, toByteArray(index)); + String statusCodeReply = connection.getStatusCodeReply(); + this.db = index; + return statusCodeReply; + } + + @Override + public String swapDB(final int index1, final int index2) { + checkIsInMultiOrPipeline(); + connection.sendCommand(SWAPDB, toByteArray(index1), toByteArray(index2)); + return connection.getStatusCodeReply(); + } + + /** + * Delete all the keys of the currently selected DB. This command never fails. + * @return OK + */ + @Override + public String flushDB() { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.flushDB()); + } + + /** + * Delete all the keys of the currently selected DB. This command never fails. + * @param flushMode + * @return OK + */ + @Override + public String flushDB(FlushMode flushMode) { + checkIsInMultiOrPipeline(); + connection.sendCommand(FLUSHDB, flushMode.getRaw()); + return connection.getStatusCodeReply(); + } + + /** + * Delete all the keys of all the existing databases, not just the currently selected one. This + * command never fails. + * @return OK + */ + @Override + public String flushAll() { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.flushAll()); + } + + /** + * Delete all the keys of all the existing databases, not just the currently selected one. This + * command never fails. + * @param flushMode + * @return OK + */ + @Override + public String flushAll(FlushMode flushMode) { + checkIsInMultiOrPipeline(); + connection.sendCommand(FLUSHALL, flushMode.getRaw()); + return connection.getStatusCodeReply(); + } + /** * COPY source destination [DB destination-db] [REPLACE] * @@ -346,27 +445,6 @@ public boolean copy(byte[] srcKey, byte[] dstKey, boolean replace) { return connection.executeCommand(commandObjects.copy(srcKey, dstKey, replace)); } - /** - * @return PONG - */ - @Override - public String ping() { - checkIsInMultiOrPipeline(); - connection.sendCommand(Command.PING); - return connection.getStatusCodeReply(); - } - - /** - * Works same as {@link Jedis#ping()} but returns argument message instead of PONG. - * @param message - * @return message - */ - public byte[] ping(final byte[] message) { - checkIsInMultiOrPipeline(); - connection.sendCommand(Command.PING, message); - return connection.getBinaryBulkReply(); - } - /** * Set the string value as value of the key. The string can't be longer than 1073741824 bytes (1 * GB). @@ -414,6 +492,12 @@ public byte[] get(final byte[] key) { return connection.executeCommand(commandObjects.get(key)); } + @Override + public byte[] setGet(final byte[] key, final byte[] value) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.setGet(key, value)); + } + @Override public byte[] setGet(final byte[] key, final byte[] value, final SetParams params) { checkIsInMultiOrPipeline(); @@ -440,15 +524,6 @@ public byte[] getEx(final byte[] key, final GetExParams params) { return connection.executeCommand(commandObjects.getEx(key, params)); } - /** - * Ask the server to silently close the connection. - */ - @Override - public String quit() { - checkIsInMultiOrPipeline(); - return connection.quit(); - } - /** * Test if the specified keys exist. The command returns the number of keys exist. * Time complexity: O(N) @@ -494,7 +569,7 @@ public long del(final byte[] key) { /** * This command is very similar to DEL: it removes the specified keys. Just like DEL a key is - * ignored if it does not exist. However the command performs the actual memory reclaiming in a + * ignored if it does not exist. However, the command performs the actual memory reclaiming in a * different thread, so it is not blocking, while DEL is. This is where the command name comes * from: the command just unlinks the keys from the keyspace. The actual removal will happen later * asynchronously. @@ -531,29 +606,6 @@ public String type(final byte[] key) { return connection.executeCommand(commandObjects.type(key)); } - /** - * Delete all the keys of the currently selected DB. This command never fails. - * @return OK - */ - @Override - public String flushDB() { - checkIsInMultiOrPipeline(); - connection.sendCommand(FLUSHDB); - return connection.getStatusCodeReply(); - } - - /** - * Delete all the keys of the currently selected DB. This command never fails. - * @param flushMode - * @return OK - */ - @Override - public String flushDB(FlushMode flushMode) { - checkIsInMultiOrPipeline(); - connection.sendCommand(FLUSHDB, flushMode.getRaw()); - return connection.getStatusCodeReply(); - } - /** * Returns all the keys matching the glob-style pattern as space separated strings. For example if * you have in the database the keys "foo" and "foobar" the command "KEYS foo*" will return @@ -714,7 +766,6 @@ public long pexpireTime(final byte[] key) { return connection.executeCommand(commandObjects.pexpireTime(key)); } - /** * EXPIREAT works exactly like {@link Jedis#expire(byte[], long) EXPIRE} but instead to get the * number of seconds representing the Time To Live of the key as a second argument (that is a @@ -793,28 +844,6 @@ public long touch(final byte[] key) { return connection.executeCommand(commandObjects.touch(key)); } - /** - * Select the DB with having the specified zero-based numeric index. For default every new - * connection connection is automatically selected to DB 0. - * @param index - * @return OK - */ - @Override - public String select(final int index) { - checkIsInMultiOrPipeline(); - connection.sendCommand(SELECT, toByteArray(index)); - String statusCodeReply = connection.getStatusCodeReply(); - this.db = index; - return statusCodeReply; - } - - @Override - public String swapDB(final int index1, final int index2) { - checkIsInMultiOrPipeline(); - connection.sendCommand(SWAPDB, toByteArray(index1), toByteArray(index2)); - return connection.getStatusCodeReply(); - } - /** * Move the specified key from the currently selected DB to the specified destination DB. Note * that this command returns 1 only if the key was successfully moved, and 0 if the target key was @@ -832,31 +861,6 @@ public long move(final byte[] key, final int dbIndex) { return connection.getIntegerReply(); } - /** - * Delete all the keys of all the existing databases, not just the currently selected one. This - * command never fails. - * @return OK - */ - @Override - public String flushAll() { - checkIsInMultiOrPipeline(); - connection.sendCommand(FLUSHALL); - return connection.getStatusCodeReply(); - } - - /** - * Delete all the keys of all the existing databases, not just the currently selected one. This - * command never fails. - * @param flushMode - * @return OK - */ - @Override - public String flushAll(FlushMode flushMode) { - checkIsInMultiOrPipeline(); - connection.sendCommand(FLUSHALL, flushMode.getRaw()); - return connection.getStatusCodeReply(); - } - /** * GETSET is an atomic set this value and return the old value command. Set key to the string * value and return the old value stored at key. The string can't be longer than 1073741824 bytes @@ -921,7 +925,7 @@ public String setex(final byte[] key, final long seconds, final byte[] value) { } /** - * Set the the respective keys to the respective values. MSET will replace old values with new + * Set the respective keys to the respective values. MSET will replace old values with new * values, while {@link Jedis#msetnx(byte[][]) MSETNX} will not perform any operation at all even * if just a single key already exists. *

@@ -969,10 +973,10 @@ public long msetnx(final byte[]... keysvalues) { * DECRBY work just like {@link Jedis#decr(byte[]) DECR} but instead to decrement by 1 the * decrement is integer. *

- * DECR commands are limited to 64 bit signed integers. + * DECR commands are limited to 64-bit signed integers. *

* Note: this is actually a string operation, that is, in Redis there are not "integer" types. - * Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented, + * Simply the string stored at the key is parsed as a base 10 64-bit signed integer, incremented, * and then converted back as a string. *

* Time complexity: O(1) @@ -993,10 +997,10 @@ public long decrBy(final byte[] key, final long decrement) { * Decrement the number stored at key by one. If the key does not exist or contains a value of a * wrong type, set the key to the value of "0" before to perform the decrement operation. *

- * DECR commands are limited to 64 bit signed integers. + * DECR commands are limited to 64-bit signed integers. *

* Note: this is actually a string operation, that is, in Redis there are not "integer" types. - * Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented, + * Simply the string stored at the key is parsed as a base 10 64-bit signed integer, incremented, * and then converted back as a string. *

* Time complexity: O(1) @@ -1016,10 +1020,10 @@ public long decr(final byte[] key) { * INCRBY work just like {@link Jedis#incr(byte[]) INCR} but instead to increment by 1 the * increment is integer. *

- * INCR commands are limited to 64 bit signed integers. + * INCR commands are limited to 64-bit signed integers. *

* Note: this is actually a string operation, that is, in Redis there are not "integer" types. - * Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented, + * Simply the string stored at the key is parsed as a base 10 64-bit signed integer, incremented, * and then converted back as a string. *

* Time complexity: O(1) @@ -1065,10 +1069,10 @@ public double incrByFloat(final byte[] key, final double increment) { * Increment the number stored at key by one. If the key does not exist or contains a value of a * wrong type, set the key to the value of "0" before to perform the increment operation. *

- * INCR commands are limited to 64 bit signed integers. + * INCR commands are limited to 64-bit signed integers. *

* Note: this is actually a string operation, that is, in Redis there are not "integer" types. - * Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented, + * Simply the string stored at the key is parsed as a base 10 64-bit signed integer, incremented, * and then converted back as a string. *

* Time complexity: O(1) @@ -1218,7 +1222,7 @@ public List hmget(final byte[] key, final byte[]... fields) { * before applying the operation. Since the value argument is signed you can use this command to * perform both increments and decrements. *

- * The range of values supported by HINCRBY is limited to 64 bit signed integers. + * The range of values supported by HINCRBY is limited to 64-bit signed integers. *

* Time complexity: O(1) * @param key @@ -1368,7 +1372,7 @@ public List hrandfield(final byte[] key, final long count) { * @return One or multiple random fields with values from a hash. */ @Override - public Map hrandfieldWithValues(final byte[] key, final long count) { + public List> hrandfieldWithValues(final byte[] key, final long count) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.hrandfieldWithValues(key, count)); } @@ -2128,6 +2132,32 @@ public Long zrevrank(final byte[] key, final byte[] member) { return connection.executeCommand(commandObjects.zrevrank(key, member)); } + /** + * Returns the rank and the score of member in the sorted set stored at key, with the scores + * ordered from low to high. + * @param key the key + * @param member the member + * @return the KeyValue contains rank and score. + */ + @Override + public KeyValue zrankWithScore(byte[] key, byte[] member) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.zrankWithScore(key, member)); + } + + /** + * Returns the rank and the score of member in the sorted set stored at key, with the scores + * ordered from high to low. + * @param key the key + * @param member the member + * @return the KeyValue contains rank and score. + */ + @Override + public KeyValue zrevrankWithScore(byte[] key, byte[] member) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.zrevrankWithScore(key, member)); + } + @Override public List zrevrange(final byte[] key, final long start, final long stop) { checkIsInMultiOrPipeline(); @@ -2502,7 +2532,7 @@ public List blpop(final int timeout, final byte[]... keys) { } @Override - public List blpop(final double timeout, final byte[]... keys) { + public KeyValue blpop(final double timeout, final byte[]... keys) { return connection.executeCommand(commandObjects.blpop(timeout, keys)); } @@ -2573,7 +2603,7 @@ public List brpop(final int timeout, final byte[]... keys) { } @Override - public List brpop(final double timeout, final byte[]... keys) { + public KeyValue brpop(final double timeout, final byte[]... keys) { return connection.executeCommand(commandObjects.brpop(timeout, keys)); } @@ -2590,24 +2620,24 @@ public KeyValue> lmpop(ListDirection direction, int count, } @Override - public KeyValue> blmpop(long timeout, ListDirection direction, byte[]... keys) { + public KeyValue> blmpop(double timeout, ListDirection direction, byte[]... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.blmpop(timeout, direction, keys)); } @Override - public KeyValue> blmpop(long timeout, ListDirection direction, int count, byte[]... keys) { + public KeyValue> blmpop(double timeout, ListDirection direction, int count, byte[]... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.blmpop(timeout, direction, count, keys)); } @Override - public List bzpopmax(final double timeout, final byte[]... keys) { + public KeyValue bzpopmax(final double timeout, final byte[]... keys) { return connection.executeCommand(commandObjects.bzpopmax(timeout, keys)); } @Override - public List bzpopmin(final double timeout, final byte[]... keys) { + public KeyValue bzpopmin(final double timeout, final byte[]... keys) { return connection.executeCommand(commandObjects.bzpopmin(timeout, keys)); } @@ -2616,7 +2646,7 @@ public List bzpopmin(final double timeout, final byte[]... keys) { * instructed to require a password before to allow clients to issue commands. This is done using * the requirepass directive in the Redis configuration file. If the password given by the connection * is correct the server replies with an OK status code reply and starts accepting commands from - * the connection. Otherwise an error is returned and the clients needs to try a new password. Note + * the connection. Otherwise, an error is returned and the clients needs to try a new password. Note * that for the high performance nature of Redis it is possible to try a lot of passwords in * parallel in very short time, so make sure to generate a strong and very long password so that * this attack is infeasible. @@ -2658,23 +2688,30 @@ public long zcount(final byte[] key, final byte[] min, final byte[] max) { } @Override - public Set zdiff(final byte[]... keys) { + public List zdiff(final byte[]... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.zdiff(keys)); } @Override - public Set zdiffWithScores(final byte[]... keys) { + public List zdiffWithScores(final byte[]... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.zdiffWithScores(keys)); } @Override + @Deprecated public long zdiffStore(final byte[] dstkey, final byte[]... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.zdiffStore(dstkey, keys)); } + @Override + public long zdiffstore(final byte[] dstkey, final byte[]... keys) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.zdiffstore(dstkey, keys)); + } + /** * Return the all the elements in the sorted set at key with a score between min and max * (including elements with score equal to min or max). @@ -3018,26 +3055,26 @@ public long zremrangeByScore(final byte[] key, final byte[] min, final byte[] ma /** * Add multiple sorted sets, This command is similar to ZUNIONSTORE, but instead of storing the - resulting sorted set, it is returned to the connection. + * resulting sorted set, it is returned to the connection. * @param params * @param keys * @return The result of the union */ @Override - public Set zunion(final ZParams params, final byte[]... keys) { + public List zunion(final ZParams params, final byte[]... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.zunion(params, keys)); } /** - * Add multiple sorted sets with scores, This command is similar to ZUNIONSTORE, but instead of storing the - * resulting sorted set, it is returned to the connection. + * Add multiple sorted sets with scores, This command is similar to ZUNIONSTORE, but instead of + * storing the resulting sorted set, it is returned to the connection. * @param params * @param keys * @return The result of the union with their scores */ @Override - public Set zunionWithScores(final ZParams params, final byte[]... keys) { + public List zunionWithScores(final ZParams params, final byte[]... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.zunionWithScores(params, keys)); } @@ -3114,7 +3151,7 @@ public long zunionstore(final byte[] dstkey, final ZParams params, final byte[]. * @return The result of the intersection */ @Override - public Set zinter(final ZParams params, final byte[]... keys) { + public List zinter(final ZParams params, final byte[]... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.zinter(params, keys)); } @@ -3127,7 +3164,7 @@ public Set zinter(final ZParams params, final byte[]... keys) { * @return The result of the intersection with scores */ @Override - public Set zinterWithScores(final ZParams params, final byte[]... keys) { + public List zinterWithScores(final ZParams params, final byte[]... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.zinterWithScores(params, keys)); } @@ -3260,13 +3297,13 @@ public KeyValue> zmpop(SortedSetOption option, int count, by } @Override - public KeyValue> bzmpop(long timeout, SortedSetOption option, byte[]... keys) { + public KeyValue> bzmpop(double timeout, SortedSetOption option, byte[]... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.bzmpop(timeout, option, keys)); } @Override - public KeyValue> bzmpop(long timeout, SortedSetOption option, int count, byte[]... keys) { + public KeyValue> bzmpop(double timeout, SortedSetOption option, int count, byte[]... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.bzmpop(timeout, option, count, keys)); } @@ -3348,9 +3385,7 @@ public long lastsave() { * Synchronously save the DB on disk, then shutdown the server. *

* Stop all the clients, save the DB, then quit the server. This commands makes sure that the DB - * is switched off without the lost of any data. This is not guaranteed if the connection uses - * simply {@link Jedis#save() SAVE} and then {@link Jedis#quit() QUIT} because other clients may - * alter the DB data between the two commands. + * is switched off without the lost of any data. * @throws JedisException with the status code reply on error. On success nothing is thrown since * the server quits and the connection is closed. */ @@ -3365,21 +3400,6 @@ public void shutdown() throws JedisException { } } - /** - * @deprecated Use {@link Jedis#shutdown(redis.clients.jedis.params.ShutdownParams)}. - */ - @Override - @Deprecated - public void shutdown(final SaveMode saveMode) throws JedisException { - connection.sendCommand(SHUTDOWN, saveMode.getRaw()); - try { - throw new JedisException(connection.getStatusCodeReply()); - } catch (JedisConnectionException jce) { - // expected - connection.setBroken(); - } - } - @Override public void shutdown(ShutdownParams shutdownParams) throws JedisException { connection.sendCommand(new CommandArguments(SHUTDOWN).addParams(shutdownParams)); @@ -3552,17 +3572,17 @@ public List roleBinary() { * @return Bulk reply. */ @Override - public List configGet(final byte[] pattern) { + public Map configGet(final byte[] pattern) { checkIsInMultiOrPipeline(); connection.sendCommand(Command.CONFIG, Keyword.GET.getRaw(), pattern); - return connection.getBinaryMultiBulkReply(); + return BuilderFactory.BINARY_MAP.build(connection.getOne()); } @Override - public List configGet(byte[]... patterns) { + public Map configGet(byte[]... patterns) { checkIsInMultiOrPipeline(); connection.sendCommand(Command.CONFIG, joinParameters(Keyword.GET.getRaw(), patterns)); - return connection.getBinaryMultiBulkReply(); + return BuilderFactory.BINARY_MAP.build(connection.getOne()); } /** @@ -3597,9 +3617,9 @@ public String configResetStat() { * *

* CONFIG REWRITE is also able to rewrite the configuration file from scratch if the original one - * no longer exists for some reason. However if the server was started without a configuration + * no longer exists for some reason. However, if the server was started without a configuration * file at all, the CONFIG REWRITE will just return an error. - * @return OK when the configuration was rewritten properly. Otherwise an error is returned. + * @return OK when the configuration was rewritten properly. Otherwise, an error is returned. */ @Override public String configRewrite() { @@ -3652,29 +3672,18 @@ public String configSet(final byte[]... parameterValues) { } @Override - public long strlen(final byte[] key) { + public String configSetBinary(Map parameterValues) { checkIsInMultiOrPipeline(); - return connection.executeCommand(commandObjects.strlen(key)); + CommandArguments args = new CommandArguments(Command.CONFIG).add(Keyword.SET); + parameterValues.forEach((k, v) -> args.add(k).add(v)); + connection.sendCommand(args); + return connection.getStatusCodeReply(); } - /** - * @deprecated STRALGO LCS command will be removed from Redis 7. - * {@link Jedis#lcs(byte[], byte[], LCSParams) LCS} can be used instead of this method. - */ @Override - @Deprecated - public LCSMatchResult strAlgoLCSKeys(final byte[] keyA, final byte[] keyB, final StrAlgoLCSParams params) { - checkIsInMultiOrPipeline(); - return connection.executeCommand(commandObjects.strAlgoLCSKeys(keyA, keyB, params)); - } - - /** - * @deprecated STRALGO LCS command will be removed from Redis 7. - */ - @Deprecated - public LCSMatchResult strAlgoLCSStrings(final byte[] strA, final byte[] strB, final StrAlgoLCSParams params) { + public long strlen(final byte[] key) { checkIsInMultiOrPipeline(); - return connection.executeCommand(commandObjects.strAlgoLCSStrings(strA, strB, params)); + return connection.executeCommand(commandObjects.strlen(key)); } @Override @@ -3887,14 +3896,12 @@ public byte[] scriptLoad(final byte[] script) { @Override public String scriptKill() { - connection.sendCommand(SCRIPT, KILL); - return connection.getStatusCodeReply(); + return connection.executeCommand(commandObjects.scriptKill()); } @Override public String slowlogReset() { - connection.sendCommand(SLOWLOG, Keyword.RESET); - return connection.getBulkReply(); + return connection.executeCommand(commandObjects.slowlogReset()); } @Override @@ -4111,23 +4118,16 @@ public String aclSetUser(byte[] name) { } @Override - public String aclSetUser(byte[] name, byte[]... keys) { + public String aclSetUser(byte[] name, byte[]... rules) { checkIsInMultiOrPipeline(); - connection.sendCommand(ACL, joinParameters(SETUSER.getRaw(), name, keys)); + connection.sendCommand(ACL, joinParameters(SETUSER.getRaw(), name, rules)); return connection.getStatusCodeReply(); } @Override - public long aclDelUser(byte[] name) { + public long aclDelUser(byte[]... names) { checkIsInMultiOrPipeline(); - connection.sendCommand(ACL, DELUSER.getRaw(), name); - return connection.getIntegerReply(); - } - - @Override - public long aclDelUser(byte[] name, byte[]... names) { - checkIsInMultiOrPipeline(); - connection.sendCommand(ACL, joinParameters(DELUSER.getRaw(), name, names)); + connection.sendCommand(ACL, joinParameters(DELUSER.getRaw(), names)); return connection.getIntegerReply(); } @@ -4181,7 +4181,7 @@ public String clientKill(final String ip, final int port) { @Override public long clientKill(ClientKillParams params) { checkIsInMultiOrPipeline(); - connection.sendCommand(CLIENT, joinParameters(KILL.getRaw(), params.getByteParams())); + connection.sendCommand(new CommandArguments(CLIENT).add(KILL).addParams(params)); return this.connection.getIntegerReply(); } @@ -4231,6 +4231,13 @@ public byte[] clientInfoBinary() { return connection.getBinaryBulkReply(); } + @Override + public String clientSetInfo(ClientAttributeOption attr, byte[] value) { + checkIsInMultiOrPipeline(); + connection.sendCommand(CLIENT, SETINFO.getRaw(), attr.getRaw(), value); + return connection.getStatusCodeReply(); + } + @Override public String clientSetname(final byte[] name) { checkIsInMultiOrPipeline(); @@ -4303,6 +4310,20 @@ public String clientNoEvictOff() { return connection.getBulkReply(); } + @Override + public String clientNoTouchOn() { + checkIsInMultiOrPipeline(); + connection.sendCommand(CLIENT, "NO-TOUCH", "ON"); + return connection.getStatusCodeReply(); + } + + @Override + public String clientNoTouchOff() { + checkIsInMultiOrPipeline(); + connection.sendCommand(CLIENT, "NO-TOUCH", "OFF"); + return connection.getStatusCodeReply(); + } + public List time() { checkIsInMultiOrPipeline(); connection.sendCommand(Command.TIME); @@ -4342,6 +4363,13 @@ public long waitReplicas(final int replicas, final long timeout) { return connection.getIntegerReply(); } + @Override + public KeyValue waitAOF(long numLocal, long numReplicas, long timeout) { + checkIsInMultiOrPipeline(); + connection.sendCommand(WAITAOF, toByteArray(numLocal), toByteArray(numReplicas), toByteArray(timeout)); + return BuilderFactory.LONG_LONG_PAIR.build(connection.getOne()); + } + @Override public long pfadd(final byte[] key, final byte[]... elements) { checkIsInMultiOrPipeline(); @@ -4618,13 +4646,13 @@ public long hstrlen(final byte[] key, final byte[] field) { } @Override - public List xread(XReadParams xReadParams, Entry... streams) { + public List xread(XReadParams xReadParams, Entry... streams) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.xread(xReadParams, streams)); } @Override - public List xreadGroup(byte[] groupName, byte[] consumer, + public List xreadGroup(byte[] groupName, byte[] consumer, XReadGroupParams xReadGroupParams, Entry... streams) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.xreadGroup(groupName, consumer, xReadGroupParams, streams)); @@ -4643,25 +4671,25 @@ public long xlen(byte[] key) { } @Override - public List xrange(byte[] key, byte[] start, byte[] end) { + public List xrange(byte[] key, byte[] start, byte[] end) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.xrange(key, start, end)); } @Override - public List xrange(byte[] key, byte[] start, byte[] end, int count) { + public List xrange(byte[] key, byte[] start, byte[] end, int count) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.xrange(key, start, end, count)); } @Override - public List xrevrange(byte[] key, byte[] end, byte[] start) { + public List xrevrange(byte[] key, byte[] end, byte[] start) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.xrevrange(key, end, start)); } @Override - public List xrevrange(byte[] key, byte[] end, byte[] start, int count) { + public List xrevrange(byte[] key, byte[] end, byte[] start, int count) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.xrevrange(key, end, start, count)); } @@ -4720,17 +4748,6 @@ public long xtrim(byte[] key, XTrimParams params) { return connection.executeCommand(commandObjects.xtrim(key, params)); } - /** - * @deprecated Use {@link Jedis#xpending(byte[], byte[], redis.clients.jedis.params.XPendingParams)}. - */ - @Override - @Deprecated - public List xpending(byte[] key, byte[] groupName, byte[] start, byte[] end, int count, - byte[] consumerName) { - checkIsInMultiOrPipeline(); - return connection.executeCommand(commandObjects.xpending(key, groupName, start, end, count, consumerName)); - } - @Override public Object xpending(final byte[] key, final byte[] groupName) { checkIsInMultiOrPipeline(); @@ -4789,13 +4806,6 @@ public Object xinfoStreamFull(byte[] key, int count) { return connection.executeCommand(commandObjects.xinfoStreamFull(key, count)); } - @Override - @Deprecated - public List xinfoGroup(byte[] key) { - checkIsInMultiOrPipeline(); - return connection.executeCommand(commandObjects.xinfoGroup(key)); - } - @Override public List xinfoGroups(byte[] key) { checkIsInMultiOrPipeline(); @@ -4915,6 +4925,12 @@ public String get(final String key) { return connection.executeCommand(commandObjects.get(key)); } + @Override + public String setGet(final String key, final String value) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.setGet(key, value)); + } + @Override public String setGet(final String key, final String value, final SetParams params) { checkIsInMultiOrPipeline(); @@ -4986,7 +5002,7 @@ public long del(final String key) { /** * This command is very similar to DEL: it removes the specified keys. Just like DEL a key is - * ignored if it does not exist. However the command performs the actual memory reclaiming in a + * ignored if it does not exist. However, the command performs the actual memory reclaiming in a * different thread, so it is not blocking, while DEL is. This is where the command name comes * from: the command just unlinks the keys from the keyspace. The actual removal will happen later * asynchronously. @@ -5346,7 +5362,7 @@ public String setex(final String key, final long seconds, final String value) { } /** - * Set the the respective keys to the respective values. MSET will replace old values with new + * Set the respective keys to the respective values. MSET will replace old values with new * values, while {@link Jedis#msetnx(String...) MSETNX} will not perform any operation at all even * if just a single key already exists. *

@@ -5368,7 +5384,7 @@ public String mset(final String... keysvalues) { } /** - * Set the the respective keys to the respective values. {@link Jedis#mset(String...) MSET} will + * Set the respective keys to the respective values. {@link Jedis#mset(String...) MSET} will * replace old values with new values, while MSETNX will not perform any operation at all even if * just a single key already exists. *

@@ -5393,10 +5409,10 @@ public long msetnx(final String... keysvalues) { * IDECRBY work just like {@link Jedis#decr(String) INCR} but instead to decrement by 1 the * decrement is integer. *

- * INCR commands are limited to 64 bit signed integers. + * INCR commands are limited to 64-bit signed integers. *

* Note: this is actually a string operation, that is, in Redis there are not "integer" types. - * Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented, + * Simply the string stored at the key is parsed as a base 10 64-bit signed integer, incremented, * and then converted back as a string. *

* Time complexity: O(1) @@ -5417,10 +5433,10 @@ public long decrBy(final String key, final long decrement) { * Decrement the number stored at key by one. If the key does not exist or contains a value of a * wrong type, set the key to the value of "0" before to perform the decrement operation. *

- * INCR commands are limited to 64 bit signed integers. + * INCR commands are limited to 64-bit signed integers. *

* Note: this is actually a string operation, that is, in Redis there are not "integer" types. - * Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented, + * Simply the string stored at the key is parsed as a base 10 64-bit signed integer, incremented, * and then converted back as a string. *

* Time complexity: O(1) @@ -5440,10 +5456,10 @@ public long decr(final String key) { * INCRBY work just like {@link Jedis#incr(String) INCR} but instead to increment by 1 the * increment is integer. *

- * INCR commands are limited to 64 bit signed integers. + * INCR commands are limited to 64-bit signed integers. *

* Note: this is actually a string operation, that is, in Redis there are not "integer" types. - * Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented, + * Simply the string stored at the key is parsed as a base 10 64-bit signed integer, incremented, * and then converted back as a string. *

* Time complexity: O(1) @@ -5485,10 +5501,10 @@ public double incrByFloat(final String key, final double increment) { * Increment the number stored at key by one. If the key does not exist or contains a value of a * wrong type, set the key to the value of "0" before to perform the increment operation. *

- * INCR commands are limited to 64 bit signed integers. + * INCR commands are limited to 64-bit signed integers. *

* Note: this is actually a string operation, that is, in Redis there are not "integer" types. - * Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented, + * Simply the string stored at the key is parsed as a base 10 64-bit signed integer, incremented, * and then converted back as a string. *

* Time complexity: O(1) @@ -5638,7 +5654,7 @@ public List hmget(final String key, final String... fields) { * before applying the operation. Since the value argument is signed you can use this command to * perform both increments and decrements. *

- * The range of values supported by HINCRBY is limited to 64 bit signed integers. + * The range of values supported by HINCRBY is limited to 64-bit signed integers. *

* Time complexity: O(1) * @param key @@ -5792,7 +5808,7 @@ public List hrandfield(final String key, final long count) { * @return one or multiple random fields with values from a hash. */ @Override - public Map hrandfieldWithValues(final String key, final long count) { + public List> hrandfieldWithValues(final String key, final long count) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.hrandfieldWithValues(key, count)); } @@ -6241,7 +6257,7 @@ public long sinterstore(final String dstkey, final String... keys) { } /** - * This command works exactly like {@link Jedis#sinter(String[]) SINTER} but instead of returning + * This command works exactly like {@link Jedis#sinter(String...) SINTER} but instead of returning * the result set, it returns just the cardinality of the result. *

* Time complexity O(N*M) worst case where N is the cardinality of the smallest @@ -6255,7 +6271,7 @@ public long sintercard(String... keys) { } /** - * This command works exactly like {@link Jedis#sinter(String[]) SINTER} but instead of returning + * This command works exactly like {@link Jedis#sinter(String...) SINTER} but instead of returning * the result set, it returns just the cardinality of the result. *

* Time complexity O(N*M) worst case where N is the cardinality of the smallest @@ -6370,7 +6386,7 @@ public String srandmember(final String key) { * @param key * @param count if positive, return an array of distinct elements. * If negative the behavior changes and the command is allowed to - * return the same element multiple times + * return the same element multiple times * @return A list of randomly selected elements */ @Override @@ -6427,23 +6443,30 @@ public Double zaddIncr(final String key, final double score, final String member } @Override - public Set zdiff(String... keys) { + public List zdiff(String... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.zdiff(keys)); } @Override - public Set zdiffWithScores(String... keys) { + public List zdiffWithScores(String... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.zdiffWithScores(keys)); } @Override + @Deprecated public long zdiffStore(final String dstkey, final String... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.zdiffStore(dstkey, keys)); } + @Override + public long zdiffstore(final String dstkey, final String... keys) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.zdiffstore(dstkey, keys)); + } + @Override public List zrange(final String key, final long start, final long stop) { checkIsInMultiOrPipeline(); @@ -6538,6 +6561,32 @@ public Long zrevrank(final String key, final String member) { return connection.executeCommand(commandObjects.zrevrank(key, member)); } + /** + * Returns the rank and the score of member in the sorted set stored at key, with the scores + * ordered from low to high. + * @param key the key + * @param member the member + * @return the KeyValue contains rank and score. + */ + @Override + public KeyValue zrankWithScore(String key, String member) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.zrankWithScore(key, member)); + } + + /** + * Returns the rank and the score of member in the sorted set stored at key, with the scores + * ordered from high to low. + * @param key the key + * @param member the member + * @return the KeyValue contains rank and score. + */ + @Override + public KeyValue zrevrankWithScore(String key, String member) { + checkIsInMultiOrPipeline(); + return connection.executeCommand(commandObjects.zrevrankWithScore(key, member)); + } + @Override public List zrevrange(final String key, final long start, final long stop) { checkIsInMultiOrPipeline(); @@ -6893,7 +6942,7 @@ public List blpop(final int timeout, final String... keys) { } @Override - public KeyedListElement blpop(final double timeout, final String... keys) { + public KeyValue blpop(final double timeout, final String... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.blpop(timeout, keys)); } @@ -6967,7 +7016,7 @@ public List brpop(final int timeout, final String... keys) { } @Override - public KeyedListElement brpop(final double timeout, final String... keys) { + public KeyValue brpop(final double timeout, final String... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.brpop(timeout, keys)); } @@ -6985,25 +7034,25 @@ public KeyValue> lmpop(ListDirection direction, int count, } @Override - public KeyValue> blmpop(long timeout, ListDirection direction, String... keys) { + public KeyValue> blmpop(double timeout, ListDirection direction, String... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.blmpop(timeout, direction, keys)); } @Override - public KeyValue> blmpop(long timeout, ListDirection direction, int count, String... keys) { + public KeyValue> blmpop(double timeout, ListDirection direction, int count, String... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.blmpop(timeout, direction, count, keys)); } @Override - public KeyedZSetElement bzpopmax(double timeout, String... keys) { + public KeyValue bzpopmax(double timeout, String... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.bzpopmax(timeout, keys)); } @Override - public KeyedZSetElement bzpopmin(double timeout, String... keys) { + public KeyValue bzpopmin(double timeout, String... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.bzpopmin(timeout, keys)); } @@ -7015,7 +7064,7 @@ public List blpop(final int timeout, final String key) { } @Override - public KeyedListElement blpop(double timeout, String key) { + public KeyValue blpop(double timeout, String key) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.blpop(timeout, key)); } @@ -7027,7 +7076,7 @@ public List brpop(final int timeout, final String key) { } @Override - public KeyedListElement brpop(double timeout, String key) { + public KeyValue brpop(double timeout, String key) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.brpop(timeout, key)); } @@ -7393,7 +7442,7 @@ public long zremrangeByScore(final String key, final String min, final String ma * @return A set with members of the resulting set */ @Override - public Set zunion(ZParams params, String... keys) { + public List zunion(ZParams params, String... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.zunion(params, keys)); } @@ -7406,7 +7455,7 @@ public Set zunion(ZParams params, String... keys) { * @return A set with members of the resulting set with scores */ @Override - public Set zunionWithScores(ZParams params, String... keys) { + public List zunionWithScores(ZParams params, String... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.zunionWithScores(params, keys)); } @@ -7492,7 +7541,7 @@ public long zunionstore(final String dstkey, final ZParams params, final String. * @return A set with members of the resulting set */ @Override - public Set zinter(final ZParams params, final String... keys) { + public List zinter(final ZParams params, final String... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.zinter(params, keys)); } @@ -7505,7 +7554,7 @@ public Set zinter(final ZParams params, final String... keys) { * @return A set with members of the resulting set with scores */ @Override - public Set zinterWithScores(final ZParams params, final String... keys) { + public List zinterWithScores(final ZParams params, final String... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.zinterWithScores(params, keys)); } @@ -7646,13 +7695,13 @@ public KeyValue> zmpop(SortedSetOption option, int count, St } @Override - public KeyValue> bzmpop(long timeout, SortedSetOption option, String... keys) { + public KeyValue> bzmpop(double timeout, SortedSetOption option, String... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.bzmpop(timeout, option, keys)); } @Override - public KeyValue> bzmpop(long timeout, SortedSetOption option, int count, String... keys) { + public KeyValue> bzmpop(double timeout, SortedSetOption option, int count, String... keys) { checkIsInMultiOrPipeline(); return connection.executeCommand(commandObjects.bzmpop(timeout, option, count, keys)); } @@ -7663,36 +7712,6 @@ public long strlen(final String key) { return connection.executeCommand(commandObjects.strlen(key)); } - /** - * Calculate the longest common subsequence of keyA and keyB. - * @deprecated STRALGO LCS command will be removed from Redis 7. - * {@link Jedis#lcs(String, String, LCSParams) LCS} can be used instead of this method. - * @param keyA - * @param keyB - * @param params - * @return According to StrAlgoLCSParams to decide to return content to fill LCSMatchResult. - */ - @Override - @Deprecated - public LCSMatchResult strAlgoLCSKeys(final String keyA, final String keyB, final StrAlgoLCSParams params) { - checkIsInMultiOrPipeline(); - return connection.executeCommand(commandObjects.strAlgoLCSKeys(keyA, keyB, params)); - } - - /** - * Calculate the longest common subsequence of strA and strB. - * @deprecated STRALGO LCS command will be removed from Redis 7. - * @param strA - * @param strB - * @param params - * @return According to StrAlgoLCSParams to decide to return content to fill LCSMatchResult. - */ - @Deprecated - public LCSMatchResult strAlgoLCSStrings(final String strA, final String strB, final StrAlgoLCSParams params) { - checkIsInMultiOrPipeline(); - return connection.executeCommand(commandObjects.strAlgoLCSStrings(strA, strB, params)); - } - /** * Calculate the longest common subsequence of keyA and keyB. * @param keyA @@ -7847,17 +7866,17 @@ public List role() { * @return Bulk reply. */ @Override - public List configGet(final String pattern) { + public Map configGet(final String pattern) { checkIsInMultiOrPipeline(); connection.sendCommand(Command.CONFIG, Keyword.GET.name(), pattern); - return connection.getMultiBulkReply(); + return BuilderFactory.STRING_MAP.build(connection.getOne()); } @Override - public List configGet(String... patterns) { + public Map configGet(String... patterns) { checkIsInMultiOrPipeline(); connection.sendCommand(Command.CONFIG, joinParameters(Keyword.GET.name(), patterns)); - return connection.getMultiBulkReply(); + return BuilderFactory.STRING_MAP.build(connection.getOne()); } /** @@ -7903,6 +7922,15 @@ public String configSet(final String... parameterValues) { return connection.getStatusCodeReply(); } + @Override + public String configSet(Map parameterValues) { + checkIsInMultiOrPipeline(); + CommandArguments args = new CommandArguments(Command.CONFIG).add(Keyword.SET); + parameterValues.forEach((k, v) -> args.add(k).add(v)); + connection.sendCommand(args); + return connection.getStatusCodeReply(); + } + public long publish(final String channel, final String message) { checkIsInMultiOrPipeline(); connection.sendCommand(PUBLISH, channel, message); @@ -7941,6 +7969,24 @@ public Map pubsubNumSub(String... channels) { return BuilderFactory.PUBSUB_NUMSUB_MAP.build(connection.getOne()); } + public List pubsubShardChannels() { + checkIsInMultiOrPipeline(); + connection.sendCommand(PUBSUB, SHARDCHANNELS); + return connection.getMultiBulkReply(); + } + + public List pubsubShardChannels(final String pattern) { + checkIsInMultiOrPipeline(); + connection.sendCommand(PUBSUB, SHARDCHANNELS.name(), pattern); + return connection.getMultiBulkReply(); + } + + public Map pubsubShardNumSub(String... channels) { + checkIsInMultiOrPipeline(); + connection.sendCommand(PUBSUB, joinParameters(SHARDNUMSUB.name(), channels)); + return BuilderFactory.PUBSUB_NUMSUB_MAP.build(connection.getOne()); + } + @Override public Object eval(final String script, final int keyCount, final String... params) { checkIsInMultiOrPipeline(); @@ -8325,23 +8371,16 @@ public String aclSetUser(final String name) { } @Override - public String aclSetUser(String name, String... params) { + public String aclSetUser(String name, String... rules) { checkIsInMultiOrPipeline(); - connection.sendCommand(ACL, joinParameters(SETUSER.name(), name, params)); + connection.sendCommand(ACL, joinParameters(SETUSER.name(), name, rules)); return connection.getStatusCodeReply(); } @Override - public long aclDelUser(final String name) { - checkIsInMultiOrPipeline(); - connection.sendCommand(ACL, DELUSER.name(), name); - return connection.getIntegerReply(); - } - - @Override - public long aclDelUser(final String name, String... names) { + public long aclDelUser(final String... names) { checkIsInMultiOrPipeline(); - connection.sendCommand(ACL, joinParameters(DELUSER.name(), name, names)); + connection.sendCommand(ACL, joinParameters(DELUSER.name(), names)); return connection.getIntegerReply(); } @@ -8349,7 +8388,7 @@ public long aclDelUser(final String name, String... names) { public AccessControlUser aclGetUser(final String name) { checkIsInMultiOrPipeline(); connection.sendCommand(ACL, GETUSER.name(), name); - return BuilderFactory.ACCESS_CONTROL_USER.build(connection.getObjectMultiBulkReply()); + return BuilderFactory.ACCESS_CONTROL_USER.build(connection.getOne()); } @Override @@ -8377,28 +8416,28 @@ public String aclWhoAmI() { public List aclCat() { checkIsInMultiOrPipeline(); connection.sendCommand(ACL, CAT); - return BuilderFactory.STRING_LIST.build(connection.getObjectMultiBulkReply()); + return BuilderFactory.STRING_LIST.build(connection.getOne()); } @Override public List aclCat(String category) { checkIsInMultiOrPipeline(); connection.sendCommand(ACL, CAT.name(), category); - return BuilderFactory.STRING_LIST.build(connection.getObjectMultiBulkReply()); + return BuilderFactory.STRING_LIST.build(connection.getOne()); } @Override public List aclLog() { checkIsInMultiOrPipeline(); connection.sendCommand(ACL, LOG); - return BuilderFactory.ACCESS_CONTROL_LOG_ENTRY_LIST.build(connection.getObjectMultiBulkReply()); + return BuilderFactory.ACCESS_CONTROL_LOG_ENTRY_LIST.build(connection.getOne()); } @Override public List aclLog(int limit) { checkIsInMultiOrPipeline(); connection.sendCommand(ACL, LOG.getRaw(), toByteArray(limit)); - return BuilderFactory.ACCESS_CONTROL_LOG_ENTRY_LIST.build(connection.getObjectMultiBulkReply()); + return BuilderFactory.ACCESS_CONTROL_LOG_ENTRY_LIST.build(connection.getOne()); } @Override @@ -8514,6 +8553,13 @@ public String clientInfo() { return connection.getBulkReply(); } + @Override + public String clientSetInfo(ClientAttributeOption attr, String value) { + checkIsInMultiOrPipeline(); + connection.sendCommand(CLIENT, SETINFO.getRaw(), attr.getRaw(), encode(value)); + return connection.getStatusCodeReply(); + } + @Override public String clientSetname(final String name) { checkIsInMultiOrPipeline(); @@ -8712,7 +8758,7 @@ public long clusterKeySlot(final String key) { public long clusterCountFailureReports(final String nodeId) { checkIsInMultiOrPipeline(); connection.sendCommand(CLUSTER, "COUNT-FAILURE-REPORTS", nodeId); - return connection.getIntegerReply(); + return connection.getIntegerReply(); } @Override @@ -8740,7 +8786,7 @@ public String clusterSetConfigEpoch(long configEpoch) { public String clusterBumpEpoch() { checkIsInMultiOrPipeline(); connection.sendCommand(CLUSTER, ClusterKeyword.BUMPEPOCH); - return connection.getStatusCodeReply(); + return connection.getBulkReply(); } @Override @@ -8780,12 +8826,20 @@ public String clusterFailover(ClusterFailoverOption failoverOption) { } @Override + @Deprecated public List clusterSlots() { checkIsInMultiOrPipeline(); connection.sendCommand(CLUSTER, ClusterKeyword.SLOTS); return connection.getObjectMultiBulkReply(); } + @Override + public List clusterShards() { + checkIsInMultiOrPipeline(); + connection.sendCommand(CLUSTER, ClusterKeyword.SHARDS); + return BuilderFactory.CLUSTER_SHARD_INFO_LIST.build(connection.getObjectMultiBulkReply()); + } + @Override public String clusterMyId() { checkIsInMultiOrPipeline(); @@ -8793,6 +8847,13 @@ public String clusterMyId() { return connection.getBulkReply(); } + @Override + public String clusterMyShardId() { + checkIsInMultiOrPipeline(); + connection.sendCommand(CLUSTER, ClusterKeyword.MYSHARDID); + return connection.getBulkReply(); + } + @Override public List> clusterLinks() { checkIsInMultiOrPipeline(); @@ -9136,7 +9197,7 @@ public String moduleUnload(final String name) { public List moduleList() { checkIsInMultiOrPipeline(); connection.sendCommand(Command.MODULE, LIST); - return BuilderFactory.MODULE_LIST.build(connection.getObjectMultiBulkReply()); + return BuilderFactory.MODULE_LIST.build(connection.getOne()); } @Override @@ -9206,6 +9267,12 @@ public String lolwut(LolwutParams lolwutParams) { return connection.getBulkReply(); } + @Override + public String reset() { + connection.sendCommand(Command.RESET); + return connection.getStatusCodeReply(); + } + @Override public String latencyDoctor() { checkIsInMultiOrPipeline(); @@ -9357,17 +9424,6 @@ public StreamPendingSummary xpending(final String key, final String groupName) { return connection.executeCommand(commandObjects.xpending(key, groupName)); } - /** - * @deprecated Use {@link Jedis#xpending(java.lang.String, java.lang.String, redis.clients.jedis.params.XPendingParams)}. - */ - @Override - @Deprecated - public List xpending(final String key, final String groupName, - final StreamEntryID start, final StreamEntryID end, final int count, final String consumerName) { - checkIsInMultiOrPipeline(); - return connection.executeCommand(commandObjects.xpending(key, groupName, start, end, count, consumerName)); - } - @Override public List xpending(final String key, final String groupName, final XPendingParams params) { checkIsInMultiOrPipeline(); @@ -9419,12 +9475,6 @@ public StreamFullInfo xinfoStreamFull(String key, int count) { return connection.executeCommand(commandObjects.xinfoStreamFull(key, count)); } - @Override - @Deprecated - public List xinfoGroup(String key) { - return connection.executeCommand(commandObjects.xinfoGroup(key)); - } - @Override public List xinfoGroups(String key) { return connection.executeCommand(commandObjects.xinfoGroups(key)); @@ -9435,6 +9485,11 @@ public List xinfoConsumers(String key, String group) { return connection.executeCommand(commandObjects.xinfoConsumers(key, group)); } + @Override + public List xinfoConsumers2(String key, String group) { + return connection.executeCommand(commandObjects.xinfoConsumers2(key, group)); + } + @Override public Object fcall(final byte[] name, final List keys, final List args) { checkIsInMultiOrPipeline(); diff --git a/src/main/java/redis/clients/jedis/JedisBroadcast.java b/src/main/java/redis/clients/jedis/JedisBroadcast.java deleted file mode 100644 index b6bf2228b8..0000000000 --- a/src/main/java/redis/clients/jedis/JedisBroadcast.java +++ /dev/null @@ -1,180 +0,0 @@ -package redis.clients.jedis; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Supplier; - -import redis.clients.jedis.Protocol.Command; -import redis.clients.jedis.Protocol.Keyword; -import redis.clients.jedis.args.FlushMode; -import redis.clients.jedis.providers.ConnectionProvider; -import redis.clients.jedis.search.FTCreateParams; -import redis.clients.jedis.search.IndexOptions; -import redis.clients.jedis.search.Schema; -import redis.clients.jedis.search.SearchProtocol.SearchCommand; -import redis.clients.jedis.search.SearchProtocol.SearchKeyword; -import redis.clients.jedis.search.schemafields.SchemaField; -import redis.clients.jedis.util.Pool; - -public class JedisBroadcast { - - private final ConnectionProvider provider; - - public JedisBroadcast(UnifiedJedis jedis) { - this(jedis.provider); - } - - public JedisBroadcast(ConnectionProvider provider) { - if (provider == null) { - throw new NullPointerException("ConnectionProvider cannot be null."); - } - this.provider = provider; - } - - public final Map> broadcastCommand(CommandObject commandObject) { - Map connectionMap = provider.getConnectionMap(); - Map> responseMap = new HashMap<>(connectionMap.size(), 1f); - for (Map.Entry entry : connectionMap.entrySet()) { - Object key = entry.getKey(); - Object connection = entry.getValue(); - try { - responseMap.put(key, new BroadcastResponse<>(executeCommand(connection, commandObject))); - } catch (RuntimeException re) { - responseMap.put(key, new BroadcastResponse<>(re)); - } - } - return responseMap; - } - - private T executeCommand(Object connection, CommandObject commandObject) { - if (connection instanceof Connection) { - return ((Connection) connection).executeCommand(commandObject); - } else if (connection instanceof Pool) { - try (Connection _conn = ((Pool) connection).getResource()) { - return _conn.executeCommand(commandObject); - } - } - throw new IllegalStateException(connection.getClass() + "is not supported."); - } - - public Map> ping() { - return broadcastCommand(new CommandObject<>(new CommandArguments(Command.PING), - BuilderFactory.STRING)); - } - - public Map> configSet(final String... parameterValues) { - if (parameterValues.length > 0 && parameterValues.length % 2 != 0) { - throw new IllegalArgumentException("It requires 'pair's of config parameter-values."); - } - CommandArguments args = new CommandArguments(Command.CONFIG).add(Keyword.SET) - .addObjects((Object[]) parameterValues); - return broadcastCommand(new CommandObject<>(args, BuilderFactory.STRING)); - } - - public Map> flushDB() { - return broadcastCommand(new CommandObject<>(new CommandArguments(Command.FLUSHDB), - BuilderFactory.STRING)); - } - - public Map> flushDB(FlushMode flushMode) { - return broadcastCommand(new CommandObject<>(new CommandArguments(Command.FLUSHDB) - .add(flushMode), BuilderFactory.STRING)); - } - - public Map> flushAll() { - return broadcastCommand(new CommandObject<>(new CommandArguments(Command.FLUSHALL), - BuilderFactory.STRING)); - } - - public Map> flushAll(FlushMode flushMode) { - return broadcastCommand(new CommandObject<>(new CommandArguments(Command.FLUSHALL) - .add(flushMode), BuilderFactory.STRING)); - } - - public Map> waitReplicas(final int replicas, final long timeout) { - CommandArguments args = new CommandArguments(Command.WAIT) - .add(Protocol.toByteArray(replicas)).add(Protocol.toByteArray(timeout)); - return broadcastCommand(new CommandObject<>(args, BuilderFactory.LONG)); - } - - public Map>> scriptExists(String... sha1) { - CommandObject> command = new CommandObject<>(new CommandArguments(Command.SCRIPT) - .add(Keyword.EXISTS).addObjects((Object[]) sha1), BuilderFactory.BOOLEAN_LIST); - return broadcastCommand(command); - } - - public Map>> scriptExists(byte[]... sha1) { - CommandObject> command = new CommandObject<>(new CommandArguments(Command.SCRIPT) - .add(Keyword.EXISTS).addObjects((Object[]) sha1), BuilderFactory.BOOLEAN_LIST); - return broadcastCommand(command); - } - - public Map> scriptLoad(String script) { - CommandObject command = new CommandObject<>(new CommandArguments(Command.SCRIPT) - .add(Keyword.LOAD).add(script), BuilderFactory.STRING); - return broadcastCommand(command); - } - - public Map> scriptLoad(byte[] script) { - CommandObject command = new CommandObject<>(new CommandArguments(Command.SCRIPT) - .add(Keyword.LOAD).add(script), BuilderFactory.BINARY); - return broadcastCommand(command); - } - - public Map> scriptFlush() { - CommandObject command = new CommandObject<>(new CommandArguments(Command.SCRIPT) - .add(Keyword.FLUSH), BuilderFactory.STRING); - return broadcastCommand(command); - } - - public Map> scriptFlush(FlushMode flushMode) { - CommandObject command = new CommandObject<>(new CommandArguments(Command.SCRIPT) - .add(Keyword.FLUSH).add(flushMode), BuilderFactory.STRING); - return broadcastCommand(command); - } - - public Map> scriptKill() { - CommandObject command = new CommandObject<>(new CommandArguments(Command.SCRIPT) - .add(Keyword.KILL), BuilderFactory.STRING); - return broadcastCommand(command); - } - - public Map> ftCreate(String indexName, IndexOptions indexOptions, Schema schema) { - CommandArguments args = new CommandArguments(SearchCommand.CREATE).add(indexName) - .addParams(indexOptions).add(SearchKeyword.SCHEMA); - schema.fields.forEach(field -> args.addParams(field)); - return broadcastCommand(new CommandObject<>(args, BuilderFactory.STRING)); - } - - public Map> ftCreate(String indexName, SchemaField... schemaFields) { - return ftCreate(indexName, Arrays.asList(schemaFields)); - } - - public Map> ftCreate(String indexName, FTCreateParams createParams, SchemaField... schemaFields) { - return ftCreate(indexName, createParams, Arrays.asList(schemaFields)); - } - - public Map> ftCreate(String indexName, Iterable schemaFields) { - return ftCreate(indexName, FTCreateParams.createParams(), schemaFields); - } - - public Map> ftCreate(String indexName, FTCreateParams createParams, - Iterable schemaFields) { - CommandArguments args = new CommandArguments(SearchCommand.CREATE).add(indexName) - .addParams(createParams).add(SearchKeyword.SCHEMA); - schemaFields.forEach(field -> args.addParams(field)); - return broadcastCommand(new CommandObject<>(args, BuilderFactory.STRING)); - } - - public Map> ftDropIndex(String indexName) { - return broadcastCommand(new CommandObject<>(new CommandArguments(SearchCommand.DROPINDEX) - .add(indexName), BuilderFactory.STRING)); - } - - public Map> ftDropIndexDD(String indexName) { - return broadcastCommand(new CommandObject<>(new CommandArguments(SearchCommand.DROPINDEX) - .add(indexName).add(SearchKeyword.DD), BuilderFactory.STRING)); - } -} diff --git a/src/main/java/redis/clients/jedis/JedisBroadcastAndRoundRobinConfig.java b/src/main/java/redis/clients/jedis/JedisBroadcastAndRoundRobinConfig.java new file mode 100644 index 0000000000..50b5b6efc0 --- /dev/null +++ b/src/main/java/redis/clients/jedis/JedisBroadcastAndRoundRobinConfig.java @@ -0,0 +1,10 @@ +package redis.clients.jedis; + +public interface JedisBroadcastAndRoundRobinConfig { + + public enum RediSearchMode { + DEFAULT, LIGHT; + } + + RediSearchMode getRediSearchModeInCluster(); +} diff --git a/src/main/java/redis/clients/jedis/JedisClientConfig.java b/src/main/java/redis/clients/jedis/JedisClientConfig.java index 355c347285..0ad6e979f6 100644 --- a/src/main/java/redis/clients/jedis/JedisClientConfig.java +++ b/src/main/java/redis/clients/jedis/JedisClientConfig.java @@ -1,11 +1,16 @@ package redis.clients.jedis; +import java.util.function.Supplier; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLSocketFactory; public interface JedisClientConfig { + default RedisProtocol getRedisProtocol() { + return null; + } + /** * @return Connection timeout in milliseconds */ @@ -39,7 +44,9 @@ default String getPassword() { return null; } - default void updatePassword(String password) { + default Supplier getCredentialsProvider() { + return new DefaultRedisCredentialsProvider( + new DefaultRedisCredentials(getUser(), getPassword())); } default int getDatabase() { @@ -73,4 +80,11 @@ default HostAndPortMapper getHostAndPortMapper() { return null; } + /** + * Modify the behavior of internally executing CLIENT SETINFO command. + * @return CLIENT SETINFO config + */ + default ClientSetInfoConfig getClientSetInfoConfig() { + return ClientSetInfoConfig.DEFAULT; + } } diff --git a/src/main/java/redis/clients/jedis/JedisCluster.java b/src/main/java/redis/clients/jedis/JedisCluster.java index 6ed9a54408..4a73df3d07 100644 --- a/src/main/java/redis/clients/jedis/JedisCluster.java +++ b/src/main/java/redis/clients/jedis/JedisCluster.java @@ -4,12 +4,16 @@ import java.util.Collections; import java.util.Map; import java.util.Set; + import org.apache.commons.pool2.impl.GenericObjectPoolConfig; -import redis.clients.jedis.executors.ClusterCommandExecutor; + import redis.clients.jedis.providers.ClusterConnectionProvider; +import redis.clients.jedis.util.JedisClusterCRC16; public class JedisCluster extends UnifiedJedis { + public static final String INIT_NO_ERROR_PROPERTY = "jedis.cluster.initNoError"; + /** * Default timeout in milliseconds. */ @@ -100,6 +104,12 @@ public JedisCluster(Set nodes, String user, String password) { this(nodes, DefaultJedisClientConfig.builder().user(user).password(password).build()); } + public JedisCluster(Set nodes, String user, String password, + HostAndPortMapper hostAndPortMap) { + this(nodes, DefaultJedisClientConfig.builder().user(user).password(password) + .hostAndPortMapper(hostAndPortMap).build()); + } + public JedisCluster(Set nodes, final GenericObjectPoolConfig poolConfig) { this(nodes, DEFAULT_TIMEOUT, DEFAULT_MAX_ATTEMPTS, poolConfig); } @@ -124,8 +134,8 @@ public JedisCluster(Set clusterNodes, int connectionTimeout, int so this(clusterNodes, connectionTimeout, soTimeout, maxAttempts, password, null, poolConfig); } - public JedisCluster(Set clusterNodes, int connectionTimeout, - int soTimeout, int maxAttempts, String password, String clientName, + public JedisCluster(Set clusterNodes, int connectionTimeout, int soTimeout, + int maxAttempts, String password, String clientName, GenericObjectPoolConfig poolConfig) { this(clusterNodes, connectionTimeout, soTimeout, maxAttempts, null, password, clientName, poolConfig); @@ -139,9 +149,9 @@ public JedisCluster(Set clusterNodes, int connectionTimeout, int so maxAttempts, poolConfig); } - public JedisCluster(Set clusterNodes, int connectionTimeout, - int soTimeout, int infiniteSoTimeout, int maxAttempts, String user, String password, - String clientName, GenericObjectPoolConfig poolConfig) { + public JedisCluster(Set clusterNodes, int connectionTimeout, int soTimeout, + int infiniteSoTimeout, int maxAttempts, String user, String password, String clientName, + GenericObjectPoolConfig poolConfig) { this(clusterNodes, DefaultJedisClientConfig.builder().connectionTimeoutMillis(connectionTimeout) .socketTimeoutMillis(soTimeout).blockingSocketTimeoutMillis(infiniteSoTimeout) .user(user).password(password).clientName(clientName).build(), maxAttempts, poolConfig); @@ -169,7 +179,8 @@ public JedisCluster(Set clusterNodes, JedisClientConfig clientConfi } public JedisCluster(Set clusterNodes, JedisClientConfig clientConfig, - int maxAttempts, Duration maxTotalRetriesDuration, GenericObjectPoolConfig poolConfig) { + int maxAttempts, Duration maxTotalRetriesDuration, + GenericObjectPoolConfig poolConfig) { super(clusterNodes, clientConfig, poolConfig, maxAttempts, maxTotalRetriesDuration); } @@ -181,10 +192,18 @@ public JedisCluster(Set clusterNodes, JedisClientConfig clientConfi super(clusterNodes, clientConfig, maxAttempts); } - public JedisCluster(Set clusterNodes, JedisClientConfig clientConfig, int maxAttempts, Duration maxTotalRetriesDuration) { + public JedisCluster(Set clusterNodes, JedisClientConfig clientConfig, int maxAttempts, + Duration maxTotalRetriesDuration) { super(clusterNodes, clientConfig, maxAttempts, maxTotalRetriesDuration); } + public JedisCluster(Set clusterNodes, JedisClientConfig clientConfig, + GenericObjectPoolConfig poolConfig, Duration topologyRefreshPeriod, int maxAttempts, + Duration maxTotalRetriesDuration) { + this(new ClusterConnectionProvider(clusterNodes, clientConfig, poolConfig, topologyRefreshPeriod), + maxAttempts, maxTotalRetriesDuration); + } + public JedisCluster(ClusterConnectionProvider provider, int maxAttempts, Duration maxTotalRetriesDuration) { super(provider, maxAttempts, maxTotalRetriesDuration); @@ -198,8 +217,39 @@ public Connection getConnectionFromSlot(int slot) { return ((ClusterConnectionProvider) provider).getConnectionFromSlot(slot); } + // commands + public long spublish(String channel, String message) { + return executeCommand(commandObjects.spublish(channel, message)); + } + + public long spublish(byte[] channel, byte[] message) { + return executeCommand(commandObjects.spublish(channel, message)); + } + + public void ssubscribe(final JedisShardedPubSub jedisPubSub, final String... channels) { + try (Connection connection = getConnectionFromSlot(JedisClusterCRC16.getSlot(channels[0]))) { + jedisPubSub.proceed(connection, channels); + } + } + + public void ssubscribe(BinaryJedisShardedPubSub jedisPubSub, final byte[]... channels) { + try (Connection connection = getConnectionFromSlot(JedisClusterCRC16.getSlot(channels[0]))) { + jedisPubSub.proceed(connection, channels); + } + } + // commands + @Override public ClusterPipeline pipelined() { - return new ClusterPipeline((ClusterConnectionProvider) provider); + return new ClusterPipeline((ClusterConnectionProvider) provider, (ClusterCommandObjects) commandObjects); + } + + /** + * @return nothing + * @throws UnsupportedOperationException + */ + @Override + public Transaction multi() { + throw new UnsupportedOperationException(); } } diff --git a/src/main/java/redis/clients/jedis/JedisClusterInfoCache.java b/src/main/java/redis/clients/jedis/JedisClusterInfoCache.java index 324e059079..bea4982fd4 100644 --- a/src/main/java/redis/clients/jedis/JedisClusterInfoCache.java +++ b/src/main/java/redis/clients/jedis/JedisClusterInfoCache.java @@ -1,6 +1,8 @@ package redis.clients.jedis; +import java.time.Duration; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -9,20 +11,29 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import redis.clients.jedis.exceptions.JedisClusterOperationException; import redis.clients.jedis.exceptions.JedisException; import redis.clients.jedis.util.SafeEncoder; +import static redis.clients.jedis.JedisCluster.INIT_NO_ERROR_PROPERTY; + public class JedisClusterInfoCache { + private static final Logger logger = LoggerFactory.getLogger(JedisClusterInfoCache.class); + private final Map nodes = new HashMap<>(); - private final Map slots = new HashMap<>(); - private final Map slotNodes = new HashMap<>(); + private final ConnectionPool[] slots = new ConnectionPool[Protocol.CLUSTER_HASHSLOTS]; + private final HostAndPort[] slotNodes = new HostAndPort[Protocol.CLUSTER_HASHSLOTS]; private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); private final Lock r = rwl.readLock(); @@ -35,15 +46,18 @@ public class JedisClusterInfoCache { private static final int MASTER_NODE_INDEX = 2; - @Deprecated - public JedisClusterInfoCache(final JedisClientConfig clientConfig) { - this(clientConfig, new GenericObjectPoolConfig()); - } - - @Deprecated - public JedisClusterInfoCache(final JedisClientConfig clientConfig, - final GenericObjectPoolConfig poolConfig) { - this(clientConfig, poolConfig, null); + /** + * The single thread executor for the topology refresh task. + */ + private ScheduledExecutorService topologyRefreshExecutor = null; + + class TopologyRefreshTask implements Runnable { + @Override + public void run() { + logger.debug("Cluster topology refresh run, old nodes: {}", nodes.keySet()); + renewClusterSlots(null); + logger.debug("Cluster topology refresh run, new nodes: {}", nodes.keySet()); + } } public JedisClusterInfoCache(final JedisClientConfig clientConfig, final Set startNodes) { @@ -52,15 +66,55 @@ public JedisClusterInfoCache(final JedisClientConfig clientConfig, final Set poolConfig, final Set startNodes) { + this(clientConfig, poolConfig, startNodes, null); + } + + public JedisClusterInfoCache(final JedisClientConfig clientConfig, + final GenericObjectPoolConfig poolConfig, final Set startNodes, + final Duration topologyRefreshPeriod) { this.poolConfig = poolConfig; this.clientConfig = clientConfig; this.startNodes = startNodes; + if (topologyRefreshPeriod != null) { + logger.info("Cluster topology refresh start, period: {}, startNodes: {}", topologyRefreshPeriod, startNodes); + topologyRefreshExecutor = Executors.newSingleThreadScheduledExecutor(); + topologyRefreshExecutor.scheduleWithFixedDelay(new TopologyRefreshTask(), topologyRefreshPeriod.toMillis(), + topologyRefreshPeriod.toMillis(), TimeUnit.MILLISECONDS); + } + } + + /** + * Check whether the number and order of slots in the cluster topology are equal to CLUSTER_HASHSLOTS + * @param slotsInfo the cluster topology + * @return if slots is ok, return true, elese return false. + */ + private boolean checkClusterSlotSequence(List slotsInfo) { + List slots = new ArrayList<>(); + for (Object slotInfoObj : slotsInfo) { + List slotInfo = (List)slotInfoObj; + slots.addAll(getAssignedSlotArray(slotInfo)); + } + Collections.sort(slots); + if (slots.size() != Protocol.CLUSTER_HASHSLOTS) { + return false; + } + for (int i = 0; i < Protocol.CLUSTER_HASHSLOTS; ++i) { + if (i != slots.get(i)) { + return false; + } + } + return true; } public void discoverClusterNodesAndSlots(Connection jedis) { List slotsInfo = executeClusterSlots(jedis); - if (slotsInfo.isEmpty()) { - throw new JedisClusterOperationException("Cluster slots list is empty."); + if (System.getProperty(INIT_NO_ERROR_PROPERTY) == null) { + if (slotsInfo.isEmpty()) { + throw new JedisClusterOperationException("Cluster slots list is empty."); + } + if (!checkClusterSlotSequence(slotsInfo)) { + throw new JedisClusterOperationException("Cluster slots have holes."); + } } w.lock(); try { @@ -143,13 +197,18 @@ public void renewClusterSlots(Connection jedis) { private void discoverClusterSlots(Connection jedis) { List slotsInfo = executeClusterSlots(jedis); - if (slotsInfo.isEmpty()) { - throw new JedisClusterOperationException("Cluster slots list is empty."); + if (System.getProperty(INIT_NO_ERROR_PROPERTY) == null) { + if (slotsInfo.isEmpty()) { + throw new JedisClusterOperationException("Cluster slots list is empty."); + } + if (!checkClusterSlotSequence(slotsInfo)) { + throw new JedisClusterOperationException("Cluster slots have holes."); + } } w.lock(); try { - this.slots.clear(); - this.slotNodes.clear(); + Arrays.fill(slots, null); + Arrays.fill(slotNodes, null); Set hostAndPortKeys = new HashSet<>(); for (Object slotInfoObj : slotsInfo) { @@ -224,8 +283,8 @@ public void assignSlotToNode(int slot, HostAndPort targetNode) { w.lock(); try { ConnectionPool targetPool = setupNodeIfNotExist(targetNode); - slots.put(slot, targetPool); - slotNodes.put(slot, targetNode); + slots[slot] = targetPool; + slotNodes[slot] = targetNode; } finally { w.unlock(); } @@ -236,8 +295,8 @@ public void assignSlotsToNode(List targetSlots, HostAndPort targetNode) try { ConnectionPool targetPool = setupNodeIfNotExist(targetNode); for (Integer slot : targetSlots) { - slots.put(slot, targetPool); - slotNodes.put(slot, targetNode); + slots[slot] = targetPool; + slotNodes[slot] = targetNode; } } finally { w.unlock(); @@ -260,7 +319,7 @@ public ConnectionPool getNode(HostAndPort node) { public ConnectionPool getSlotPool(int slot) { r.lock(); try { - return slots.get(slot); + return slots[slot]; } finally { r.unlock(); } @@ -269,7 +328,7 @@ public ConnectionPool getSlotPool(int slot) { public HostAndPort getSlotNode(int slot) { r.lock(); try { - return slotNodes.get(slot); + return slotNodes[slot]; } finally { r.unlock(); } @@ -311,13 +370,21 @@ public void reset() { } } nodes.clear(); - slots.clear(); - slotNodes.clear(); + Arrays.fill(slots, null); + Arrays.fill(slotNodes, null); } finally { w.unlock(); } } + public void close() { + reset(); + if (topologyRefreshExecutor != null) { + logger.info("Cluster topology refresh shutdown, startNodes: {}", startNodes); + topologyRefreshExecutor.shutdownNow(); + } + } + public static String getNodeKey(HostAndPort hnp) { //return hnp.getHost() + ":" + hnp.getPort(); return hnp.toString(); diff --git a/src/main/java/redis/clients/jedis/JedisFactory.java b/src/main/java/redis/clients/jedis/JedisFactory.java index 6827b620ef..b84e2b05ae 100644 --- a/src/main/java/redis/clients/jedis/JedisFactory.java +++ b/src/main/java/redis/clients/jedis/JedisFactory.java @@ -101,7 +101,7 @@ protected JedisFactory(final JedisSocketFactory jedisSocketFactory, final JedisC } /** - * {@link #setHostAndPort(redis.clients.jedis.HostAndPort) setHostAndPort} must be called later. + * {@link JedisFactory#setHostAndPort(redis.clients.jedis.HostAndPort) setHostAndPort} must be called later. */ JedisFactory(final JedisClientConfig clientConfig) { this.clientConfig = clientConfig; @@ -130,6 +130,7 @@ protected JedisFactory(final URI uri, final int connectionTimeout, final int soT .socketTimeoutMillis(soTimeout).blockingSocketTimeoutMillis(infiniteSoTimeout) .user(JedisURIHelper.getUser(uri)).password(JedisURIHelper.getPassword(uri)) .database(JedisURIHelper.getDBIndex(uri)).clientName(clientName) + .protocol(JedisURIHelper.getRedisProtocol(uri)) .ssl(JedisURIHelper.isRedisSSLScheme(uri)).sslSocketFactory(sslSocketFactory) .sslParameters(sslParameters).hostnameVerifier(hostnameVerifier).build(); this.jedisSocketFactory = new DefaultJedisSocketFactory(new HostAndPort(uri.getHost(), uri.getPort()), this.clientConfig); @@ -142,10 +143,6 @@ void setHostAndPort(final HostAndPort hostAndPort) { ((DefaultJedisSocketFactory) jedisSocketFactory).updateHostAndPort(hostAndPort); } - public void setPassword(final String password) { - this.clientConfig.updatePassword(password); - } - @Override public void activateObject(PooledObject pooledJedis) throws Exception { final Jedis jedis = pooledJedis.getObject(); @@ -158,14 +155,6 @@ public void activateObject(PooledObject pooledJedis) throws Exception { public void destroyObject(PooledObject pooledJedis) throws Exception { final Jedis jedis = pooledJedis.getObject(); if (jedis.isConnected()) { - try { - // need a proper test, probably with mock - if (!jedis.isBroken()) { - jedis.quit(); - } - } catch (RuntimeException e) { - logger.debug("Error while QUIT", e); - } try { jedis.close(); } catch (RuntimeException e) { @@ -179,21 +168,9 @@ public PooledObject makeObject() throws Exception { Jedis jedis = null; try { jedis = new Jedis(jedisSocketFactory, clientConfig); - jedis.connect(); return new DefaultPooledObject<>(jedis); } catch (JedisException je) { - if (jedis != null) { - try { - jedis.quit(); - } catch (RuntimeException e) { - logger.debug("Error while QUIT", e); - } - try { - jedis.close(); - } catch (RuntimeException e) { - logger.debug("Error while close", e); - } - } + logger.debug("Error while makeObject", je); throw je; } } diff --git a/src/main/java/redis/clients/jedis/JedisMetaInfo.java b/src/main/java/redis/clients/jedis/JedisMetaInfo.java new file mode 100644 index 0000000000..04470de70a --- /dev/null +++ b/src/main/java/redis/clients/jedis/JedisMetaInfo.java @@ -0,0 +1,42 @@ +package redis.clients.jedis; + +import java.io.InputStream; +import java.util.Properties; +import org.slf4j.LoggerFactory; + +/** + * Jedis Meta info load version groupId + */ +class JedisMetaInfo { + + private static final String groupId; + private static final String artifactId; + private static final String version; + + static { + Properties p = new Properties(); + try (InputStream in = JedisMetaInfo.class.getClassLoader() + .getResourceAsStream("redis/clients/jedis/pom.properties")) { + p.load(in); + } catch (Exception e) { + LoggerFactory.getLogger(JedisMetaInfo.class) + .error("Load Jedis meta info from pom.properties failed", e); + } + + groupId = p.getProperty("groupId", null); + artifactId = p.getProperty("artifactId", null); + version = p.getProperty("version", null); + } + + public static String getGroupId() { + return groupId; + } + + public static String getArtifactId() { + return artifactId; + } + + public static String getVersion() { + return version; + } +} diff --git a/src/main/java/redis/clients/jedis/JedisPooled.java b/src/main/java/redis/clients/jedis/JedisPooled.java index f573341868..bc751527ca 100644 --- a/src/main/java/redis/clients/jedis/JedisPooled.java +++ b/src/main/java/redis/clients/jedis/JedisPooled.java @@ -353,11 +353,13 @@ public JedisPooled(final GenericObjectPoolConfig poolConfig, final U final int connectionTimeout, final int soTimeout, final int infiniteSoTimeout, final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { - this(new HostAndPort(uri.getHost(), uri.getPort()), DefaultJedisClientConfig.create( - connectionTimeout, soTimeout, infiniteSoTimeout, JedisURIHelper.getUser(uri), - JedisURIHelper.getPassword(uri), JedisURIHelper.getDBIndex(uri), null, - JedisURIHelper.isRedisSSLScheme(uri), sslSocketFactory, sslParameters, hostnameVerifier, - null), poolConfig); + this(new HostAndPort(uri.getHost(), uri.getPort()), DefaultJedisClientConfig.builder() + .connectionTimeoutMillis(connectionTimeout).socketTimeoutMillis(soTimeout) + .blockingSocketTimeoutMillis(infiniteSoTimeout).user(JedisURIHelper.getUser(uri)) + .password(JedisURIHelper.getPassword(uri)).database(JedisURIHelper.getDBIndex(uri)) + .protocol(JedisURIHelper.getRedisProtocol(uri)).ssl(JedisURIHelper.isRedisSSLScheme(uri)) + .sslSocketFactory(sslSocketFactory).sslParameters(sslParameters) + .hostnameVerifier(hostnameVerifier).build(), poolConfig); } public JedisPooled(final HostAndPort hostAndPort, final GenericObjectPoolConfig poolConfig) { diff --git a/src/main/java/redis/clients/jedis/JedisPubSub.java b/src/main/java/redis/clients/jedis/JedisPubSub.java index e34ea39c6f..95229bfa5f 100644 --- a/src/main/java/redis/clients/jedis/JedisPubSub.java +++ b/src/main/java/redis/clients/jedis/JedisPubSub.java @@ -1,191 +1,11 @@ package redis.clients.jedis; -import static redis.clients.jedis.Protocol.ResponseKeyword.*; - -import java.util.Arrays; -import java.util.List; - -import redis.clients.jedis.Protocol.Command; -import redis.clients.jedis.exceptions.JedisConnectionException; -import redis.clients.jedis.exceptions.JedisException; import redis.clients.jedis.util.SafeEncoder; -public abstract class JedisPubSub { - - private static final String JEDIS_SUBSCRIPTION_MESSAGE = "JedisPubSub is not subscribed to a Jedis instance."; - private int subscribedChannels = 0; - private volatile Connection client; - - public void onMessage(String channel, String message) { - } - - public void onPMessage(String pattern, String channel, String message) { - } - - public void onSubscribe(String channel, int subscribedChannels) { - } - - public void onUnsubscribe(String channel, int subscribedChannels) { - } - - public void onPUnsubscribe(String pattern, int subscribedChannels) { - } - - public void onPSubscribe(String pattern, int subscribedChannels) { - } - - public void onPong(String pattern) { - - } - - public void unsubscribe() { - if (client == null) { - throw new JedisConnectionException(JEDIS_SUBSCRIPTION_MESSAGE); - } - client.sendCommand(Command.UNSUBSCRIBE); - client.flush(); - } - - public void unsubscribe(String... channels) { - if (client == null) { - throw new JedisConnectionException(JEDIS_SUBSCRIPTION_MESSAGE); - } - client.sendCommand(Command.UNSUBSCRIBE, channels); - client.flush(); - } - - public void subscribe(String... channels) { - if (client == null) { - throw new JedisConnectionException(JEDIS_SUBSCRIPTION_MESSAGE); - } - client.sendCommand(Command.SUBSCRIBE, channels); - client.flush(); - } - - public void psubscribe(String... patterns) { - if (client == null) { - throw new JedisConnectionException(JEDIS_SUBSCRIPTION_MESSAGE); - } - client.sendCommand(Command.PSUBSCRIBE, patterns); - client.flush(); - } - - public void punsubscribe() { - if (client == null) { - throw new JedisConnectionException(JEDIS_SUBSCRIPTION_MESSAGE); - } - client.sendCommand(Command.PUNSUBSCRIBE); - client.flush(); - } - - public void punsubscribe(String... patterns) { - if (client == null) { - throw new JedisConnectionException(JEDIS_SUBSCRIPTION_MESSAGE); - } - client.sendCommand(Command.PUNSUBSCRIBE, patterns); - client.flush(); - } - - public void ping() { - if (client == null) { - throw new JedisConnectionException(JEDIS_SUBSCRIPTION_MESSAGE); - } - client.sendCommand(Command.PING); - client.flush(); - } - - public void ping(String argument) { - if (client == null) { - throw new JedisConnectionException(JEDIS_SUBSCRIPTION_MESSAGE); - } - client.sendCommand(Command.PING, argument); - client.flush(); - } - - public boolean isSubscribed() { - return subscribedChannels > 0; - } - - public void proceedWithPatterns(Connection client, String... patterns) { - this.client = client; - this.client.setTimeoutInfinite(); - try { - psubscribe(patterns); - process(); - } finally { - this.client.rollbackTimeout(); - } - } - - public void proceed(Connection client, String... channels) { - this.client = client; - this.client.setTimeoutInfinite(); - try { - subscribe(channels); - process(); - } finally { - this.client.rollbackTimeout(); - } - } - -// private void process(Client client) { - private void process() { - - do { - List reply = client.getUnflushedObjectMultiBulkReply(); - final Object firstObj = reply.get(0); - if (!(firstObj instanceof byte[])) { - throw new JedisException("Unknown message type: " + firstObj); - } - final byte[] resp = (byte[]) firstObj; - if (Arrays.equals(SUBSCRIBE.getRaw(), resp)) { - subscribedChannels = ((Long) reply.get(2)).intValue(); - final byte[] bchannel = (byte[]) reply.get(1); - final String strchannel = (bchannel == null) ? null : SafeEncoder.encode(bchannel); - onSubscribe(strchannel, subscribedChannels); - } else if (Arrays.equals(UNSUBSCRIBE.getRaw(), resp)) { - subscribedChannels = ((Long) reply.get(2)).intValue(); - final byte[] bchannel = (byte[]) reply.get(1); - final String strchannel = (bchannel == null) ? null : SafeEncoder.encode(bchannel); - onUnsubscribe(strchannel, subscribedChannels); - } else if (Arrays.equals(MESSAGE.getRaw(), resp)) { - final byte[] bchannel = (byte[]) reply.get(1); - final byte[] bmesg = (byte[]) reply.get(2); - final String strchannel = (bchannel == null) ? null : SafeEncoder.encode(bchannel); - final String strmesg = (bmesg == null) ? null : SafeEncoder.encode(bmesg); - onMessage(strchannel, strmesg); - } else if (Arrays.equals(PMESSAGE.getRaw(), resp)) { - final byte[] bpattern = (byte[]) reply.get(1); - final byte[] bchannel = (byte[]) reply.get(2); - final byte[] bmesg = (byte[]) reply.get(3); - final String strpattern = (bpattern == null) ? null : SafeEncoder.encode(bpattern); - final String strchannel = (bchannel == null) ? null : SafeEncoder.encode(bchannel); - final String strmesg = (bmesg == null) ? null : SafeEncoder.encode(bmesg); - onPMessage(strpattern, strchannel, strmesg); - } else if (Arrays.equals(PSUBSCRIBE.getRaw(), resp)) { - subscribedChannels = ((Long) reply.get(2)).intValue(); - final byte[] bpattern = (byte[]) reply.get(1); - final String strpattern = (bpattern == null) ? null : SafeEncoder.encode(bpattern); - onPSubscribe(strpattern, subscribedChannels); - } else if (Arrays.equals(PUNSUBSCRIBE.getRaw(), resp)) { - subscribedChannels = ((Long) reply.get(2)).intValue(); - final byte[] bpattern = (byte[]) reply.get(1); - final String strpattern = (bpattern == null) ? null : SafeEncoder.encode(bpattern); - onPUnsubscribe(strpattern, subscribedChannels); - } else if (Arrays.equals(PONG.getRaw(), resp)) { - final byte[] bpattern = (byte[]) reply.get(1); - final String strpattern = (bpattern == null) ? null : SafeEncoder.encode(bpattern); - onPong(strpattern); - } else { - throw new JedisException("Unknown message type: " + firstObj); - } - } while (isSubscribed()); - -// /* Invalidate instance since this thread is no longer listening */ -// this.client = null; - } +public abstract class JedisPubSub extends JedisPubSubBase { - public int getSubscribedChannels() { - return subscribedChannels; + @Override + protected final String encode(byte[] raw) { + return SafeEncoder.encode(raw); } } diff --git a/src/main/java/redis/clients/jedis/JedisPubSubBase.java b/src/main/java/redis/clients/jedis/JedisPubSubBase.java new file mode 100644 index 0000000000..7092680e33 --- /dev/null +++ b/src/main/java/redis/clients/jedis/JedisPubSubBase.java @@ -0,0 +1,180 @@ +package redis.clients.jedis; + +import static redis.clients.jedis.Protocol.ResponseKeyword.*; + +import java.util.Arrays; +import java.util.List; + +import redis.clients.jedis.Protocol.Command; +import redis.clients.jedis.exceptions.JedisException; +import redis.clients.jedis.util.SafeEncoder; + +public abstract class JedisPubSubBase { + + private int subscribedChannels = 0; + private volatile Connection client; + + public void onMessage(T channel, T message) { + } + + public void onPMessage(T pattern, T channel, T message) { + } + + public void onSubscribe(T channel, int subscribedChannels) { + } + + public void onUnsubscribe(T channel, int subscribedChannels) { + } + + public void onPUnsubscribe(T pattern, int subscribedChannels) { + } + + public void onPSubscribe(T pattern, int subscribedChannels) { + } + + public void onPong(T pattern) { + } + + private void sendAndFlushCommand(Command command, T... args) { + if (client == null) { + throw new JedisException(getClass() + " is not connected to a Connection."); + } + CommandArguments cargs = new CommandArguments(command).addObjects(args); + client.sendCommand(cargs); + client.flush(); + } + + public final void unsubscribe() { + sendAndFlushCommand(Command.UNSUBSCRIBE); + } + + public final void unsubscribe(T... channels) { + sendAndFlushCommand(Command.UNSUBSCRIBE, channels); + } + + public final void subscribe(T... channels) { + sendAndFlushCommand(Command.SUBSCRIBE, channels); + } + + public final void psubscribe(T... patterns) { + sendAndFlushCommand(Command.PSUBSCRIBE, patterns); + } + + public final void punsubscribe() { + sendAndFlushCommand(Command.PUNSUBSCRIBE); + } + + public final void punsubscribe(T... patterns) { + sendAndFlushCommand(Command.PUNSUBSCRIBE, patterns); + } + + public final void ping() { + sendAndFlushCommand(Command.PING); + } + + public final void ping(T argument) { + sendAndFlushCommand(Command.PING, argument); + } + + public final boolean isSubscribed() { + return subscribedChannels > 0; + } + + public final int getSubscribedChannels() { + return subscribedChannels; + } + + public final void proceed(Connection client, T... channels) { + this.client = client; + this.client.setTimeoutInfinite(); + try { + subscribe(channels); + process(); + } finally { + this.client.rollbackTimeout(); + } + } + + public final void proceedWithPatterns(Connection client, T... patterns) { + this.client = client; + this.client.setTimeoutInfinite(); + try { + psubscribe(patterns); + process(); + } finally { + this.client.rollbackTimeout(); + } + } + + protected abstract T encode(byte[] raw); + +// private void process(Client client) { + private void process() { + + do { + Object reply = client.getUnflushedObject(); + + if (reply instanceof List) { + List listReply = (List) reply; + final Object firstObj = listReply.get(0); + if (!(firstObj instanceof byte[])) { + throw new JedisException("Unknown message type: " + firstObj); + } + final byte[] resp = (byte[]) firstObj; + if (Arrays.equals(SUBSCRIBE.getRaw(), resp)) { + subscribedChannels = ((Long) listReply.get(2)).intValue(); + final byte[] bchannel = (byte[]) listReply.get(1); + final T enchannel = (bchannel == null) ? null : encode(bchannel); + onSubscribe(enchannel, subscribedChannels); + } else if (Arrays.equals(UNSUBSCRIBE.getRaw(), resp)) { + subscribedChannels = ((Long) listReply.get(2)).intValue(); + final byte[] bchannel = (byte[]) listReply.get(1); + final T enchannel = (bchannel == null) ? null : encode(bchannel); + onUnsubscribe(enchannel, subscribedChannels); + } else if (Arrays.equals(MESSAGE.getRaw(), resp)) { + final byte[] bchannel = (byte[]) listReply.get(1); + final byte[] bmesg = (byte[]) listReply.get(2); + final T enchannel = (bchannel == null) ? null : encode(bchannel); + final T enmesg = (bmesg == null) ? null : encode(bmesg); + onMessage(enchannel, enmesg); + } else if (Arrays.equals(PMESSAGE.getRaw(), resp)) { + final byte[] bpattern = (byte[]) listReply.get(1); + final byte[] bchannel = (byte[]) listReply.get(2); + final byte[] bmesg = (byte[]) listReply.get(3); + final T enpattern = (bpattern == null) ? null : encode(bpattern); + final T enchannel = (bchannel == null) ? null : encode(bchannel); + final T enmesg = (bmesg == null) ? null : encode(bmesg); + onPMessage(enpattern, enchannel, enmesg); + } else if (Arrays.equals(PSUBSCRIBE.getRaw(), resp)) { + subscribedChannels = ((Long) listReply.get(2)).intValue(); + final byte[] bpattern = (byte[]) listReply.get(1); + final T enpattern = (bpattern == null) ? null : encode(bpattern); + onPSubscribe(enpattern, subscribedChannels); + } else if (Arrays.equals(PUNSUBSCRIBE.getRaw(), resp)) { + subscribedChannels = ((Long) listReply.get(2)).intValue(); + final byte[] bpattern = (byte[]) listReply.get(1); + final T enpattern = (bpattern == null) ? null : encode(bpattern); + onPUnsubscribe(enpattern, subscribedChannels); + } else if (Arrays.equals(PONG.getRaw(), resp)) { + final byte[] bpattern = (byte[]) listReply.get(1); + final T enpattern = (bpattern == null) ? null : encode(bpattern); + onPong(enpattern); + } else { + throw new JedisException("Unknown message type: " + firstObj); + } + } else if (reply instanceof byte[]) { + byte[] resp = (byte[]) reply; + if ("PONG".equals(SafeEncoder.encode(resp))) { + onPong(null); + } else { + onPong(encode(resp)); + } + } else { + throw new JedisException("Unknown message type: " + reply); + } + } while (isSubscribed()); + +// /* Invalidate instance since this thread is no longer listening */ +// this.client = null; + } +} diff --git a/src/main/java/redis/clients/jedis/JedisSentinelPool.java b/src/main/java/redis/clients/jedis/JedisSentinelPool.java index 6f921ddd97..586750540c 100644 --- a/src/main/java/redis/clients/jedis/JedisSentinelPool.java +++ b/src/main/java/redis/clients/jedis/JedisSentinelPool.java @@ -31,8 +31,8 @@ public class JedisSentinelPool extends Pool { private final Object initPoolLock = new Object(); public JedisSentinelPool(String masterName, Set sentinels, - final JedisClientConfig masteClientConfig, final JedisClientConfig sentinelClientConfig) { - this(masterName, sentinels, new JedisFactory(masteClientConfig), sentinelClientConfig); + final JedisClientConfig masterClientConfig, final JedisClientConfig sentinelClientConfig) { + this(masterName, sentinels, new JedisFactory(masterClientConfig), sentinelClientConfig); } public JedisSentinelPool(String masterName, Set sentinels, @@ -167,9 +167,9 @@ public JedisSentinelPool(String masterName, Set sentinels, } public JedisSentinelPool(String masterName, Set sentinels, - final GenericObjectPoolConfig poolConfig, final JedisClientConfig masteClientConfig, + final GenericObjectPoolConfig poolConfig, final JedisClientConfig masterClientConfig, final JedisClientConfig sentinelClientConfig) { - this(masterName, sentinels, poolConfig, new JedisFactory(masteClientConfig), sentinelClientConfig); + this(masterName, sentinels, poolConfig, new JedisFactory(masterClientConfig), sentinelClientConfig); } public JedisSentinelPool(String masterName, Set sentinels, diff --git a/src/main/java/redis/clients/jedis/JedisSentineled.java b/src/main/java/redis/clients/jedis/JedisSentineled.java index 6d449e8d76..063d1c40d9 100644 --- a/src/main/java/redis/clients/jedis/JedisSentineled.java +++ b/src/main/java/redis/clients/jedis/JedisSentineled.java @@ -6,41 +6,11 @@ public class JedisSentineled extends UnifiedJedis { - /** - * This constructor is here for easier transition from {@link JedisSentinelPool#JedisSentinelPool( - * java.lang.String, java.util.Set, redis.clients.jedis.JedisClientConfig, redis.clients.jedis.JedisClientConfig)}. - * - * @deprecated Use {@link #JedisSentineled(java.lang.String, redis.clients.jedis.JedisClientConfig, - * java.util.Set, redis.clients.jedis.JedisClientConfig)}. - */ - @Deprecated - // Legacy - public JedisSentineled(String masterName, Set sentinels, - final JedisClientConfig masterClientConfig, final JedisClientConfig sentinelClientConfig) { - this(masterName, masterClientConfig, sentinels, sentinelClientConfig); - } - public JedisSentineled(String masterName, final JedisClientConfig masterClientConfig, Set sentinels, final JedisClientConfig sentinelClientConfig) { this(new SentineledConnectionProvider(masterName, masterClientConfig, sentinels, sentinelClientConfig)); } - /** - * This constructor is here for easier transition from {@link JedisSentinelPool#JedisSentinelPool( - * java.lang.String, java.util.Set, org.apache.commons.pool2.impl.GenericObjectPoolConfig, - * redis.clients.jedis.JedisClientConfig, redis.clients.jedis.JedisClientConfig)}. - * - * @deprecated Use {@link #JedisSentineled(java.lang.String, redis.clients.jedis.JedisClientConfig, - * org.apache.commons.pool2.impl.GenericObjectPoolConfig, java.util.Set, redis.clients.jedis.JedisClientConfig)}. - */ - @Deprecated - // Legacy - public JedisSentineled(String masterName, Set sentinels, - final GenericObjectPoolConfig poolConfig, final JedisClientConfig masterClientConfig, - final JedisClientConfig sentinelClientConfig) { - this(masterName, masterClientConfig, poolConfig, sentinels, sentinelClientConfig); - } - public JedisSentineled(String masterName, final JedisClientConfig masterClientConfig, final GenericObjectPoolConfig poolConfig, Set sentinels, final JedisClientConfig sentinelClientConfig) { @@ -54,4 +24,9 @@ public JedisSentineled(SentineledConnectionProvider sentineledConnectionProvider public HostAndPort getCurrentMaster() { return ((SentineledConnectionProvider) provider).getCurrentMaster(); } + + @Override + public Pipeline pipelined() { + return (Pipeline) super.pipelined(); + } } diff --git a/src/main/java/redis/clients/jedis/JedisShardedPubSub.java b/src/main/java/redis/clients/jedis/JedisShardedPubSub.java new file mode 100644 index 0000000000..2ec3038bdb --- /dev/null +++ b/src/main/java/redis/clients/jedis/JedisShardedPubSub.java @@ -0,0 +1,11 @@ +package redis.clients.jedis; + +import redis.clients.jedis.util.SafeEncoder; + +public abstract class JedisShardedPubSub extends JedisShardedPubSubBase { + + @Override + protected final String encode(byte[] raw) { + return SafeEncoder.encode(raw); + } +} diff --git a/src/main/java/redis/clients/jedis/JedisShardedPubSubBase.java b/src/main/java/redis/clients/jedis/JedisShardedPubSubBase.java new file mode 100644 index 0000000000..f0a251f61f --- /dev/null +++ b/src/main/java/redis/clients/jedis/JedisShardedPubSubBase.java @@ -0,0 +1,107 @@ +package redis.clients.jedis; + +import static redis.clients.jedis.Protocol.ResponseKeyword.*; + +import java.util.Arrays; +import java.util.List; + +import redis.clients.jedis.Protocol.Command; +import redis.clients.jedis.exceptions.JedisException; + +public abstract class JedisShardedPubSubBase { + + private int subscribedChannels = 0; + private volatile Connection client; + + public void onSMessage(T channel, T message) { + } + + public void onSSubscribe(T channel, int subscribedChannels) { + } + + public void onSUnsubscribe(T channel, int subscribedChannels) { + } + + private void sendAndFlushCommand(Command command, T... args) { + if (client == null) { + throw new JedisException(getClass() + " is not connected to a Connection."); + } + CommandArguments cargs = new CommandArguments(command).addObjects(args); + client.sendCommand(cargs); + client.flush(); + } + + public final void sunsubscribe() { + sendAndFlushCommand(Command.SUNSUBSCRIBE); + } + + public final void sunsubscribe(T... channels) { + sendAndFlushCommand(Command.SUNSUBSCRIBE, channels); + } + + public final void ssubscribe(T... channels) { + sendAndFlushCommand(Command.SSUBSCRIBE, channels); + } + + public final boolean isSubscribed() { + return subscribedChannels > 0; + } + + public final int getSubscribedChannels() { + return subscribedChannels; + } + + public final void proceed(Connection client, T... channels) { + this.client = client; + this.client.setTimeoutInfinite(); + try { + ssubscribe(channels); + process(); + } finally { + this.client.rollbackTimeout(); + } + } + + protected abstract T encode(byte[] raw); + +// private void process(Client client) { + private void process() { + + do { + Object reply = client.getUnflushedObject(); + + if (reply instanceof List) { + List listReply = (List) reply; + final Object firstObj = listReply.get(0); + if (!(firstObj instanceof byte[])) { + throw new JedisException("Unknown message type: " + firstObj); + } + final byte[] resp = (byte[]) firstObj; + if (Arrays.equals(SSUBSCRIBE.getRaw(), resp)) { + subscribedChannels = ((Long) listReply.get(2)).intValue(); + final byte[] bchannel = (byte[]) listReply.get(1); + final T enchannel = (bchannel == null) ? null : encode(bchannel); + onSSubscribe(enchannel, subscribedChannels); + } else if (Arrays.equals(SUNSUBSCRIBE.getRaw(), resp)) { + subscribedChannels = ((Long) listReply.get(2)).intValue(); + final byte[] bchannel = (byte[]) listReply.get(1); + final T enchannel = (bchannel == null) ? null : encode(bchannel); + onSUnsubscribe(enchannel, subscribedChannels); + } else if (Arrays.equals(SMESSAGE.getRaw(), resp)) { + final byte[] bchannel = (byte[]) listReply.get(1); + final byte[] bmesg = (byte[]) listReply.get(2); + final T enchannel = (bchannel == null) ? null : encode(bchannel); + final T enmesg = (bmesg == null) ? null : encode(bmesg); + onSMessage(enchannel, enmesg); + } else { + throw new JedisException("Unknown message type: " + firstObj); + } + } else { + throw new JedisException("Unknown message type: " + reply); + } + } while (isSubscribed()); + +// /* Invalidate instance since this thread is no longer listening */ +// this.client = null; + } +} diff --git a/src/main/java/redis/clients/jedis/JedisSharding.java b/src/main/java/redis/clients/jedis/JedisSharding.java index 1f7f1700cf..2a94ea2df2 100644 --- a/src/main/java/redis/clients/jedis/JedisSharding.java +++ b/src/main/java/redis/clients/jedis/JedisSharding.java @@ -6,6 +6,10 @@ import redis.clients.jedis.providers.ShardedConnectionProvider; import redis.clients.jedis.util.Hashing; +/** + * @deprecated Sharding/Sharded feature will be removed in next major release. + */ +@Deprecated public class JedisSharding extends UnifiedJedis { public static final Pattern DEFAULT_KEY_TAG_PATTERN = Pattern.compile("\\{(.+?)\\}"); @@ -16,20 +20,24 @@ public JedisSharding(List shards) { public JedisSharding(List shards, JedisClientConfig clientConfig) { this(new ShardedConnectionProvider(shards, clientConfig)); + setProtocol(clientConfig); } public JedisSharding(List shards, JedisClientConfig clientConfig, GenericObjectPoolConfig poolConfig) { this(new ShardedConnectionProvider(shards, clientConfig, poolConfig)); + setProtocol(clientConfig); } public JedisSharding(List shards, JedisClientConfig clientConfig, Hashing algo) { this(new ShardedConnectionProvider(shards, clientConfig, algo)); + setProtocol(clientConfig); } public JedisSharding(List shards, JedisClientConfig clientConfig, GenericObjectPoolConfig poolConfig, Hashing algo) { this(new ShardedConnectionProvider(shards, clientConfig, poolConfig, algo)); + setProtocol(clientConfig); } public JedisSharding(ShardedConnectionProvider provider) { @@ -40,8 +48,22 @@ public JedisSharding(ShardedConnectionProvider provider, Pattern tagPattern) { super(provider, tagPattern); } + private void setProtocol(JedisClientConfig clientConfig) { + RedisProtocol proto = clientConfig.getRedisProtocol(); + if (proto == RedisProtocol.RESP3) commandObjects.setProtocol(proto); + } + @Override public ShardedPipeline pipelined() { return new ShardedPipeline((ShardedConnectionProvider) provider); } + + /** + * @return nothing + * @throws UnsupportedOperationException + */ + @Override + public Transaction multi() { + throw new UnsupportedOperationException(); + } } diff --git a/src/main/java/redis/clients/jedis/Module.java b/src/main/java/redis/clients/jedis/Module.java index 3dbf9b46cf..0c3d356c21 100644 --- a/src/main/java/redis/clients/jedis/Module.java +++ b/src/main/java/redis/clients/jedis/Module.java @@ -1,5 +1,7 @@ package redis.clients.jedis; +// TODO: 'resps' package +// TODO: remove public class Module { private final String name; diff --git a/src/main/java/redis/clients/jedis/MultiClusterClientConfig.java b/src/main/java/redis/clients/jedis/MultiClusterClientConfig.java new file mode 100644 index 0000000000..c39efae7d4 --- /dev/null +++ b/src/main/java/redis/clients/jedis/MultiClusterClientConfig.java @@ -0,0 +1,332 @@ +package redis.clients.jedis; + +import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig.SlidingWindowType; +import redis.clients.jedis.exceptions.JedisConnectionException; +import redis.clients.jedis.exceptions.JedisValidationException; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; + + +/** + * @author Allen Terleto (aterleto) + *

+ * Config which supports multiple cluster/database endpoint configurations + * that all share retry and circuit breaker configuration settings. + *

+ * With this Config users can seamlessly failover to Disaster Recovery (DR), Backup, and Active-Active cluster(s) + * by using simple configuration which is passed through from Resilience4j - https://resilience4j.readme.io/docs + *

+ * Configuration options related to automatic failback (e.g. HALF_OPENED state) are not supported and therefore + * not passed through to Jedis users. + *

+ */ +public final class MultiClusterClientConfig { + + private static final int RETRY_MAX_ATTEMPTS_DEFAULT = 3; + private static final int RETRY_WAIT_DURATION_DEFAULT = 500; // measured in milliseconds + private static final int RETRY_WAIT_DURATION_EXPONENTIAL_BACKOFF_MULTIPLIER_DEFAULT = 2; + private static final Class RETRY_INCLUDED_EXCEPTIONS_DEFAULT = JedisConnectionException.class; + + private static final float CIRCUIT_BREAKER_FAILURE_RATE_THRESHOLD_DEFAULT = 50.0f; // measured as percentage + private static final int CIRCUIT_BREAKER_SLIDING_WINDOW_MIN_CALLS_DEFAULT = 100; + private static final SlidingWindowType CIRCUIT_BREAKER_SLIDING_WINDOW_TYPE_DEFAULT = SlidingWindowType.COUNT_BASED; + private static final int CIRCUIT_BREAKER_SLIDING_WINDOW_SIZE_DEFAULT = 100; + private static final int CIRCUIT_BREAKER_SLOW_CALL_DURATION_THRESHOLD_DEFAULT = 60000; // measured in milliseconds + private static final float CIRCUIT_BREAKER_SLOW_CALL_RATE_THRESHOLD_DEFAULT = 100.0f; // measured as percentage + private static final Class CIRCUIT_BREAKER_INCLUDED_EXCEPTIONS_DEFAULT = JedisConnectionException.class; + + private final ClusterConfig[] clusterConfigs; + + //////////// Retry Config - https://resilience4j.readme.io/docs/retry //////////// + + /** Maximum number of attempts (including the initial call as the first attempt) */ + private int retryMaxAttempts; + + /** Fixed wait duration between retry attempt */ + private Duration retryWaitDuration; + + /** Wait duration increases exponentially between attempts due to the multiplier. + * For example, if we specified an initial wait time of 1s and a multiplier of 2, + * the retries would be done after 1s, 2s, 4s, 8s, 16s, and so on */ + private int retryWaitDurationExponentialBackoffMultiplier; + + /** Configures a list of Throwable classes that are recorded as a failure and thus are retried. + * This parameter supports subtyping. */ + private List retryIncludedExceptionList; + + /** Configures a list of Throwable classes that are ignored and thus are not retried. + * This parameter supports subtyping. */ + private List retryIgnoreExceptionList; + + //////////// Circuit Breaker Config - https://resilience4j.readme.io/docs/circuitbreaker //////////// + + /** When the failure rate is equal or greater than the threshold the CircuitBreaker transitions + * to open and starts short-circuiting calls */ + private float circuitBreakerFailureRateThreshold; + + /** Minimum number of calls required (per sliding window period) before the CircuitBreaker + * can calculate the error rate or slow call rate. For example, if the value is 10, + * then at least 10 calls must be recorded, before the failure rate can be calculated. However, if + * only 9 calls have been recorded, the CircuitBreaker will not transition to open even if all 9 have failed */ + private int circuitBreakerSlidingWindowMinCalls; + + /** Used to record the outcome of calls when the CircuitBreaker is closed. + * If the type is COUNT_BASED, the last slidingWindowSize calls are recorded and aggregated. + * If the type is TIME_BASED, the calls of the last slidingWindowSize seconds are recorded and aggregated */ + private SlidingWindowType circuitBreakerSlidingWindowType; + + /** Size of the sliding window which is used to record the outcome of calls when the CircuitBreaker is closed */ + private int circuitBreakerSlidingWindowSize; + + /** Duration threshold above which calls are considered as slow and increase the rate of slow calls */ + private Duration circuitBreakerSlowCallDurationThreshold; + + /** When the percentage of slow calls is equal or greater the threshold, + * the CircuitBreaker transitions to open and starts short-circuiting calls. + * CircuitBreaker considers a call as slow when the call duration is greater than slowCallDurationThreshold */ + private float circuitBreakerSlowCallRateThreshold; + + /** A list of exceptions that are recorded as a failure and thus increase the failure rate. + * Any exception matching or inheriting from one of the list counts as a failure, unless explicitly + * ignored via ignoreExceptions. If you specify a list of exceptions, all other exceptions count as + * a success, unless they are explicitly ignored by ignoreExceptions */ + private List circuitBreakerIncludedExceptionList; + + /** A list of exceptions that are ignored and neither count as a failure nor success. + * Any exception matching or inheriting from one of the list will not count as a + * failure nor success, even if the exceptions is part of recordExceptions */ + private List circuitBreakerIgnoreExceptionList; + + + public MultiClusterClientConfig(ClusterConfig[] clusterConfigs) { + this.clusterConfigs = clusterConfigs; + } + + public ClusterConfig[] getClusterConfigs() { + return clusterConfigs; + } + + public int getRetryMaxAttempts() { + return retryMaxAttempts; + } + + public Duration getRetryWaitDuration() { + return retryWaitDuration; + } + + public int getRetryWaitDurationExponentialBackoffMultiplier() { + return retryWaitDurationExponentialBackoffMultiplier; + } + + public float getCircuitBreakerFailureRateThreshold() { + return circuitBreakerFailureRateThreshold; + } + + public int getCircuitBreakerSlidingWindowMinCalls() { + return circuitBreakerSlidingWindowMinCalls; + } + + public int getCircuitBreakerSlidingWindowSize() { + return circuitBreakerSlidingWindowSize; + } + + public Duration getCircuitBreakerSlowCallDurationThreshold() { + return circuitBreakerSlowCallDurationThreshold; + } + + public float getCircuitBreakerSlowCallRateThreshold() { + return circuitBreakerSlowCallRateThreshold; + } + + public List getRetryIncludedExceptionList() { + return retryIncludedExceptionList; + } + + public List getRetryIgnoreExceptionList() { + return retryIgnoreExceptionList; + } + + public List getCircuitBreakerIncludedExceptionList() { + return circuitBreakerIncludedExceptionList; + } + + public List getCircuitBreakerIgnoreExceptionList() { + return circuitBreakerIgnoreExceptionList; + } + + public SlidingWindowType getCircuitBreakerSlidingWindowType() { + return circuitBreakerSlidingWindowType; + } + + public static class ClusterConfig { + + private int priority; + private HostAndPort hostAndPort; + private JedisClientConfig clientConfig; + + public ClusterConfig(HostAndPort hostAndPort, JedisClientConfig clientConfig) { + this.hostAndPort = hostAndPort; + this.clientConfig = clientConfig; + } + + public int getPriority() { + return priority; + } + + private void setPriority(int priority) { + this.priority = priority; + } + + public HostAndPort getHostAndPort() { + return hostAndPort; + } + + public JedisClientConfig getJedisClientConfig() { + return clientConfig; + } + } + + public static class Builder { + + private ClusterConfig[] clusterConfigs; + + private int retryMaxAttempts = RETRY_MAX_ATTEMPTS_DEFAULT; + private int retryWaitDuration = RETRY_WAIT_DURATION_DEFAULT; + private int retryWaitDurationExponentialBackoffMultiplier = RETRY_WAIT_DURATION_EXPONENTIAL_BACKOFF_MULTIPLIER_DEFAULT; + private List retryIncludedExceptionList; + private List retryIgnoreExceptionList; + + private float circuitBreakerFailureRateThreshold = CIRCUIT_BREAKER_FAILURE_RATE_THRESHOLD_DEFAULT; + private int circuitBreakerSlidingWindowMinCalls = CIRCUIT_BREAKER_SLIDING_WINDOW_MIN_CALLS_DEFAULT; + private SlidingWindowType circuitBreakerSlidingWindowType = CIRCUIT_BREAKER_SLIDING_WINDOW_TYPE_DEFAULT; + private int circuitBreakerSlidingWindowSize = CIRCUIT_BREAKER_SLIDING_WINDOW_SIZE_DEFAULT; + private int circuitBreakerSlowCallDurationThreshold = CIRCUIT_BREAKER_SLOW_CALL_DURATION_THRESHOLD_DEFAULT; + private float circuitBreakerSlowCallRateThreshold = CIRCUIT_BREAKER_SLOW_CALL_RATE_THRESHOLD_DEFAULT; + private List circuitBreakerIncludedExceptionList; + private List circuitBreakerIgnoreExceptionList; + private List> circuitBreakerFallbackExceptionList; + + public Builder(ClusterConfig[] clusterConfigs) { + + if (clusterConfigs == null || clusterConfigs.length < 1) + throw new JedisValidationException("ClusterClientConfigs are required for MultiClusterPooledConnectionProvider"); + + for (int i = 0; i < clusterConfigs.length; i++) + clusterConfigs[i].setPriority(i + 1); + + this.clusterConfigs = clusterConfigs; + } + + public Builder retryMaxAttempts(int retryMaxAttempts) { + this.retryMaxAttempts = retryMaxAttempts; + return this; + } + + public Builder retryWaitDuration(int retryWaitDuration) { + this.retryWaitDuration = retryWaitDuration; + return this; + } + + public Builder retryWaitDurationExponentialBackoffMultiplier(int retryWaitDurationExponentialBackoffMultiplier) { + this.retryWaitDurationExponentialBackoffMultiplier = retryWaitDurationExponentialBackoffMultiplier; + return this; + } + + public Builder retryIncludedExceptionList(List retryIncludedExceptionList) { + this.retryIncludedExceptionList = retryIncludedExceptionList; + return this; + } + + public Builder retryIgnoreExceptionList(List retryIgnoreExceptionList) { + this.retryIgnoreExceptionList = retryIgnoreExceptionList; + return this; + } + + public Builder circuitBreakerFailureRateThreshold(float circuitBreakerFailureRateThreshold) { + this.circuitBreakerFailureRateThreshold = circuitBreakerFailureRateThreshold; + return this; + } + + public Builder circuitBreakerSlidingWindowMinCalls(int circuitBreakerSlidingWindowMinCalls) { + this.circuitBreakerSlidingWindowMinCalls = circuitBreakerSlidingWindowMinCalls; + return this; + } + + public Builder circuitBreakerSlidingWindowType(SlidingWindowType circuitBreakerSlidingWindowType) { + this.circuitBreakerSlidingWindowType = circuitBreakerSlidingWindowType; + return this; + } + + public Builder circuitBreakerSlidingWindowSize(int circuitBreakerSlidingWindowSize) { + this.circuitBreakerSlidingWindowSize = circuitBreakerSlidingWindowSize; + return this; + } + + public Builder circuitBreakerSlowCallDurationThreshold(int circuitBreakerSlowCallDurationThreshold) { + this.circuitBreakerSlowCallDurationThreshold = circuitBreakerSlowCallDurationThreshold; + return this; + } + + public Builder circuitBreakerSlowCallRateThreshold(float circuitBreakerSlowCallRateThreshold) { + this.circuitBreakerSlowCallRateThreshold = circuitBreakerSlowCallRateThreshold; + return this; + } + + public Builder circuitBreakerIncludedExceptionList(List circuitBreakerIncludedExceptionList) { + this.circuitBreakerIncludedExceptionList = circuitBreakerIncludedExceptionList; + return this; + } + + public Builder circuitBreakerIgnoreExceptionList(List circuitBreakerIgnoreExceptionList) { + this.circuitBreakerIgnoreExceptionList = circuitBreakerIgnoreExceptionList; + return this; + } + + public Builder circuitBreakerFallbackExceptionList(List> circuitBreakerFallbackExceptionList) { + this.circuitBreakerFallbackExceptionList = circuitBreakerFallbackExceptionList; + return this; + } + + public MultiClusterClientConfig build() { + MultiClusterClientConfig config = new MultiClusterClientConfig(this.clusterConfigs); + + config.retryMaxAttempts = this.retryMaxAttempts; + config.retryWaitDuration = Duration.ofMillis(this.retryWaitDuration); + config.retryWaitDurationExponentialBackoffMultiplier = this.retryWaitDurationExponentialBackoffMultiplier; + + if (this.retryIncludedExceptionList != null && !retryIncludedExceptionList.isEmpty()) + config.retryIncludedExceptionList = this.retryIncludedExceptionList; + + else { + config.retryIncludedExceptionList = new ArrayList<>(); + config.retryIncludedExceptionList.add(RETRY_INCLUDED_EXCEPTIONS_DEFAULT); + } + + if (this.retryIgnoreExceptionList != null && !retryIgnoreExceptionList.isEmpty()) + config.retryIgnoreExceptionList = this.retryIgnoreExceptionList; + + config.circuitBreakerFailureRateThreshold = this.circuitBreakerFailureRateThreshold; + config.circuitBreakerSlidingWindowMinCalls = this.circuitBreakerSlidingWindowMinCalls; + config.circuitBreakerSlidingWindowType = this.circuitBreakerSlidingWindowType; + config.circuitBreakerSlidingWindowSize = this.circuitBreakerSlidingWindowSize; + config.circuitBreakerSlowCallDurationThreshold = Duration.ofMillis(this.circuitBreakerSlowCallDurationThreshold); + config.circuitBreakerSlowCallRateThreshold = this.circuitBreakerSlowCallRateThreshold; + + if (this.circuitBreakerIncludedExceptionList != null && !circuitBreakerIncludedExceptionList.isEmpty()) + config.circuitBreakerIncludedExceptionList = this.circuitBreakerIncludedExceptionList; + + else { + config.circuitBreakerIncludedExceptionList = new ArrayList<>(); + config.circuitBreakerIncludedExceptionList.add(CIRCUIT_BREAKER_INCLUDED_EXCEPTIONS_DEFAULT); + } + + if (this.circuitBreakerIgnoreExceptionList != null && !circuitBreakerIgnoreExceptionList.isEmpty()) + config.circuitBreakerIgnoreExceptionList = this.circuitBreakerIgnoreExceptionList; + + return config; + } + } + +} \ No newline at end of file diff --git a/src/main/java/redis/clients/jedis/MultiNodePipelineBase.java b/src/main/java/redis/clients/jedis/MultiNodePipelineBase.java index ddb8b37db2..a01ff4d1bb 100644 --- a/src/main/java/redis/clients/jedis/MultiNodePipelineBase.java +++ b/src/main/java/redis/clients/jedis/MultiNodePipelineBase.java @@ -1,68 +1,59 @@ package redis.clients.jedis; -import java.io.Closeable; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Queue; -import java.util.Set; -import org.json.JSONArray; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import redis.clients.jedis.args.*; -import redis.clients.jedis.bloom.*; -import redis.clients.jedis.commands.PipelineBinaryCommands; -import redis.clients.jedis.commands.PipelineCommands; -import redis.clients.jedis.commands.RedisModulePipelineCommands; import redis.clients.jedis.exceptions.JedisConnectionException; import redis.clients.jedis.graph.GraphCommandObjects; -import redis.clients.jedis.graph.ResultSet; -import redis.clients.jedis.json.JsonSetParams; -import redis.clients.jedis.json.Path; -import redis.clients.jedis.json.Path2; -import redis.clients.jedis.params.*; import redis.clients.jedis.providers.ConnectionProvider; -import redis.clients.jedis.resps.*; -import redis.clients.jedis.search.*; -import redis.clients.jedis.search.aggr.AggregationBuilder; -import redis.clients.jedis.search.aggr.AggregationResult; -import redis.clients.jedis.search.schemafields.SchemaField; -import redis.clients.jedis.timeseries.*; import redis.clients.jedis.util.IOUtils; -import redis.clients.jedis.util.KeyValue; -public abstract class MultiNodePipelineBase implements PipelineCommands, PipelineBinaryCommands, - RedisModulePipelineCommands, Closeable { +public abstract class MultiNodePipelineBase extends PipelineBase { private final Logger log = LoggerFactory.getLogger(getClass()); + /** + * The number of processes for {@code sync()}. If you have enough cores for client (and you have + * more than 3 cluster nodes), you may increase this number of workers. + * Suggestion: ≤ cluster nodes. + */ + public static volatile int MULTI_NODE_PIPELINE_SYNC_WORKERS = 3; + private final Map>> pipelinedResponses; private final Map connections; private volatile boolean syncing = false; - private final CommandObjects commandObjects; - private GraphCommandObjects graphCommandObjects; - public MultiNodePipelineBase(CommandObjects commandObjects) { + super(commandObjects); pipelinedResponses = new LinkedHashMap<>(); connections = new LinkedHashMap<>(); - this.commandObjects = commandObjects; } /** * Sub-classes must call this method, if graph commands are going to be used. + * @param connectionProvider connection provider */ protected final void prepareGraphCommands(ConnectionProvider connectionProvider) { - this.graphCommandObjects = new GraphCommandObjects(connectionProvider); + GraphCommandObjects graphCommandObjects = new GraphCommandObjects(connectionProvider); + graphCommandObjects.setBaseCommandArgumentsCreator((comm) -> this.commandObjects.commandArguments(comm)); + super.setGraphCommands(graphCommandObjects); } protected abstract HostAndPort getNodeKey(CommandArguments args); protected abstract Connection getConnection(HostAndPort nodeKey); + @Override protected final Response appendCommand(CommandObject commandObject) { HostAndPort nodeKey = getNodeKey(commandObject.getArguments()); @@ -72,10 +63,16 @@ protected final Response appendCommand(CommandObject commandObject) { queue = pipelinedResponses.get(nodeKey); connection = connections.get(nodeKey); } else { - queue = new LinkedList<>(); - connection = getConnection(nodeKey); - pipelinedResponses.put(nodeKey, queue); - connections.put(nodeKey, connection); + pipelinedResponses.putIfAbsent(nodeKey, new LinkedList<>()); + queue = pipelinedResponses.get(nodeKey); + + Connection newOne = getConnection(nodeKey); + connections.putIfAbsent(nodeKey, newOne); + connection = connections.get(nodeKey); + if (connection != newOne) { + log.debug("Duplicate connection to {}, closing it.", nodeKey); + IOUtils.closeQuietly(newOne); + } } connection.sendCommand(commandObject.getArguments()); @@ -93,12 +90,16 @@ public void close() { } } + @Override public final void sync() { if (syncing) { return; } syncing = true; + ExecutorService executorService = Executors.newFixedThreadPool(MULTI_NODE_PIPELINE_SYNC_WORKERS); + + CountDownLatch countDownLatch = new CountDownLatch(pipelinedResponses.size()); Iterator>>> pipelinedResponsesIterator = pipelinedResponses.entrySet().iterator(); while (pipelinedResponsesIterator.hasNext()) { @@ -106,4197 +107,36 @@ public final void sync() { HostAndPort nodeKey = entry.getKey(); Queue> queue = entry.getValue(); Connection connection = connections.get(nodeKey); - try { - List unformatted = connection.getMany(queue.size()); - for (Object o : unformatted) { - queue.poll().set(o); + executorService.submit(() -> { + try { + List unformatted = connection.getMany(queue.size()); + for (Object o : unformatted) { + queue.poll().set(o); + } + } catch (JedisConnectionException jce) { + log.error("Error with connection to " + nodeKey, jce); + // cleanup the connection + pipelinedResponsesIterator.remove(); + connections.remove(nodeKey); + IOUtils.closeQuietly(connection); + } finally { + countDownLatch.countDown(); } - } catch (JedisConnectionException jce) { - log.error("Error with connection to " + nodeKey, jce); - // cleanup the connection - pipelinedResponsesIterator.remove(); - connections.remove(nodeKey); - IOUtils.closeQuietly(connection); - } + }); } - syncing = false; - } - - @Override - public Response exists(String key) { - return appendCommand(commandObjects.exists(key)); - } - - @Override - public Response exists(String... keys) { - return appendCommand(commandObjects.exists(keys)); - } - - @Override - public Response persist(String key) { - return appendCommand(commandObjects.persist(key)); - } - - @Override - public Response type(String key) { - return appendCommand(commandObjects.type(key)); - } - - @Override - public Response dump(String key) { - return appendCommand(commandObjects.dump(key)); - } - - @Override - public Response restore(String key, long ttl, byte[] serializedValue) { - return appendCommand(commandObjects.restore(key, ttl, serializedValue)); - } - - @Override - public Response restore(String key, long ttl, byte[] serializedValue, RestoreParams params) { - return appendCommand(commandObjects.restore(key, ttl, serializedValue, params)); - } - - @Override - public Response expire(String key, long seconds) { - return appendCommand(commandObjects.expire(key, seconds)); - } - - @Override - public Response expire(String key, long seconds, ExpiryOption expiryOption) { - return appendCommand(commandObjects.expire(key, seconds, expiryOption)); - } - - @Override - public Response pexpire(String key, long milliseconds) { - return appendCommand(commandObjects.pexpire(key, milliseconds)); - } - - @Override - public Response pexpire(String key, long milliseconds, ExpiryOption expiryOption) { - return appendCommand(commandObjects.pexpire(key, milliseconds, expiryOption)); - } - - @Override - public Response expireTime(String key) { - return appendCommand(commandObjects.expireTime(key)); - } - - @Override - public Response pexpireTime(String key) { - return appendCommand(commandObjects.pexpireTime(key)); - } - - @Override - public Response expireAt(String key, long unixTime) { - return appendCommand(commandObjects.expireAt(key, unixTime)); - } - - @Override - public Response expireAt(String key, long unixTime, ExpiryOption expiryOption) { - return appendCommand(commandObjects.expireAt(key, unixTime, expiryOption)); - } - - @Override - public Response pexpireAt(String key, long millisecondsTimestamp) { - return appendCommand(commandObjects.pexpireAt(key, millisecondsTimestamp)); - } - - @Override - public Response pexpireAt(String key, long millisecondsTimestamp, ExpiryOption expiryOption) { - return appendCommand(commandObjects.pexpireAt(key, millisecondsTimestamp, expiryOption)); - } - - @Override - public Response ttl(String key) { - return appendCommand(commandObjects.ttl(key)); - } - - @Override - public Response pttl(String key) { - return appendCommand(commandObjects.pttl(key)); - } - - @Override - public Response touch(String key) { - return appendCommand(commandObjects.touch(key)); - } - - @Override - public Response touch(String... keys) { - return appendCommand(commandObjects.touch(keys)); - } - - @Override - public Response> sort(String key) { - return appendCommand(commandObjects.sort(key)); - } - - @Override - public Response sort(String key, String dstKey) { - return appendCommand(commandObjects.sort(key, dstKey)); - } - - @Override - public Response> sort(String key, SortingParams sortingParams) { - return appendCommand(commandObjects.sort(key, sortingParams)); - } - - @Override - public Response sort(String key, SortingParams sortingParams, String dstKey) { - return appendCommand(commandObjects.sort(key, sortingParams, dstKey)); - } - - @Override - public Response> sortReadonly(String key, SortingParams sortingParams) { - return appendCommand(commandObjects.sortReadonly(key, sortingParams)); - } - - @Override - public Response del(String key) { - return appendCommand(commandObjects.del(key)); - } - - @Override - public Response del(String... keys) { - return appendCommand(commandObjects.del(keys)); - } - - @Override - public Response unlink(String key) { - return appendCommand(commandObjects.unlink(key)); - } - - @Override - public Response unlink(String... keys) { - return appendCommand(commandObjects.unlink(keys)); - } - - @Override - public Response copy(String srcKey, String dstKey, boolean replace) { - return appendCommand(commandObjects.copy(srcKey, dstKey, replace)); - } - - @Override - public Response rename(String oldKey, String newKey) { - return appendCommand(commandObjects.rename(oldKey, newKey)); - } - - @Override - public Response renamenx(String oldKey, String newKey) { - return appendCommand(commandObjects.renamenx(oldKey, newKey)); - } - - @Override - public Response memoryUsage(String key) { - return appendCommand(commandObjects.memoryUsage(key)); - } - - @Override - public Response memoryUsage(String key, int samples) { - return appendCommand(commandObjects.memoryUsage(key, samples)); - } - - @Override - public Response objectRefcount(String key) { - return appendCommand(commandObjects.objectRefcount(key)); - } - - @Override - public Response objectEncoding(String key) { - return appendCommand(commandObjects.objectEncoding(key)); - } - - @Override - public Response objectIdletime(String key) { - return appendCommand(commandObjects.objectIdletime(key)); - } - - @Override - public Response objectFreq(String key) { - return appendCommand(commandObjects.objectFreq(key)); - } - - @Override - public Response migrate(String host, int port, String key, int timeout) { - return appendCommand(commandObjects.migrate(host, port, key, timeout)); - } - - @Override - public Response migrate(String host, int port, int timeout, MigrateParams params, String... keys) { - return appendCommand(commandObjects.migrate(host, port, timeout, params, keys)); - } - - @Override - public Response> keys(String pattern) { - return appendCommand(commandObjects.keys(pattern)); - } - - @Override - public Response> scan(String cursor) { - return appendCommand(commandObjects.scan(cursor)); - } - - @Override - public Response> scan(String cursor, ScanParams params) { - return appendCommand(commandObjects.scan(cursor, params)); - } - - @Override - public Response> scan(String cursor, ScanParams params, String type) { - return appendCommand(commandObjects.scan(cursor, params, type)); - } - - @Override - public Response randomKey() { - return appendCommand(commandObjects.randomKey()); - } - - @Override - public Response get(String key) { - return appendCommand(commandObjects.get(key)); - } - - @Override - public Response setGet(String key, String value, SetParams params) { - return appendCommand(commandObjects.setGet(key, value, params)); - } - - @Override - public Response getDel(String key) { - return appendCommand(commandObjects.getDel(key)); - } - - @Override - public Response getEx(String key, GetExParams params) { - return appendCommand(commandObjects.getEx(key, params)); - } - - @Override - public Response setbit(String key, long offset, boolean value) { - return appendCommand(commandObjects.setbit(key, offset, value)); - } - - @Override - public Response getbit(String key, long offset) { - return appendCommand(commandObjects.getbit(key, offset)); - } - - @Override - public Response setrange(String key, long offset, String value) { - return appendCommand(commandObjects.setrange(key, offset, value)); - } - - @Override - public Response getrange(String key, long startOffset, long endOffset) { - return appendCommand(commandObjects.getrange(key, startOffset, endOffset)); - } - - @Override - public Response getSet(String key, String value) { - return appendCommand(commandObjects.getSet(key, value)); - } - - @Override - public Response setnx(String key, String value) { - return appendCommand(commandObjects.setnx(key, value)); - } - - @Override - public Response setex(String key, long seconds, String value) { - return appendCommand(commandObjects.setex(key, seconds, value)); - } - - @Override - public Response psetex(String key, long milliseconds, String value) { - return appendCommand(commandObjects.psetex(key, milliseconds, value)); - } - - @Override - public Response> mget(String... keys) { - return appendCommand(commandObjects.mget(keys)); - } - - @Override - public Response mset(String... keysvalues) { - return appendCommand(commandObjects.mset(keysvalues)); - } - - @Override - public Response msetnx(String... keysvalues) { - return appendCommand(commandObjects.msetnx(keysvalues)); - } - - @Override - public Response incr(String key) { - return appendCommand(commandObjects.incr(key)); - } - - @Override - public Response incrBy(String key, long increment) { - return appendCommand(commandObjects.incrBy(key, increment)); - } - - @Override - public Response incrByFloat(String key, double increment) { - return appendCommand(commandObjects.incrByFloat(key, increment)); - } - - @Override - public Response decr(String key) { - return appendCommand(commandObjects.decr(key)); - } - - @Override - public Response decrBy(String key, long decrement) { - return appendCommand(commandObjects.decrBy(key, decrement)); - } - - @Override - public Response append(String key, String value) { - return appendCommand(commandObjects.append(key, value)); - } - - @Override - public Response substr(String key, int start, int end) { - return appendCommand(commandObjects.substr(key, start, end)); - } - - @Override - public Response strlen(String key) { - return appendCommand(commandObjects.strlen(key)); - } - - @Override - public Response bitcount(String key) { - return appendCommand(commandObjects.bitcount(key)); - } - - @Override - public Response bitcount(String key, long start, long end) { - return appendCommand(commandObjects.bitcount(key, start, end)); - } - - @Override - public Response bitcount(String key, long start, long end, BitCountOption option) { - return appendCommand(commandObjects.bitcount(key, start, end, option)); - } - - @Override - public Response bitpos(String key, boolean value) { - return appendCommand(commandObjects.bitpos(key, value)); - } - - @Override - public Response bitpos(String key, boolean value, BitPosParams params) { - return appendCommand(commandObjects.bitpos(key, value, params)); - } - - @Override - public Response> bitfield(String key, String... arguments) { - return appendCommand(commandObjects.bitfield(key, arguments)); - } - - @Override - public Response> bitfieldReadonly(String key, String... arguments) { - return appendCommand(commandObjects.bitfieldReadonly(key, arguments)); - } - - @Override - public Response bitop(BitOP op, String destKey, String... srcKeys) { - return appendCommand(commandObjects.bitop(op, destKey, srcKeys)); - } - - @Override - public Response strAlgoLCSKeys(String keyA, String keyB, StrAlgoLCSParams params) { - return appendCommand(commandObjects.strAlgoLCSKeys(keyA, keyB, params)); - } + try { + countDownLatch.await(); + } catch (InterruptedException e) { + log.error("Thread is interrupted during sync.", e); + } - @Override - public Response lcs(String keyA, String keyB, LCSParams params) { - return appendCommand(commandObjects.lcs(keyA, keyB, params)); - } + executorService.shutdownNow(); - @Override - public Response set(String key, String value) { - return appendCommand(commandObjects.set(key, value)); + syncing = false; } - @Override - public Response set(String key, String value, SetParams params) { - return appendCommand(commandObjects.set(key, value, params)); - } - - @Override - public Response rpush(String key, String... string) { - return appendCommand(commandObjects.rpush(key, string)); - } - - @Override - public Response lpush(String key, String... string) { - return appendCommand(commandObjects.lpush(key, string)); - } - - @Override - public Response llen(String key) { - return appendCommand(commandObjects.llen(key)); - } - - @Override - public Response> lrange(String key, long start, long stop) { - return appendCommand(commandObjects.lrange(key, start, stop)); - } - - @Override - public Response ltrim(String key, long start, long stop) { - return appendCommand(commandObjects.ltrim(key, start, stop)); - } - - @Override - public Response lindex(String key, long index) { - return appendCommand(commandObjects.lindex(key, index)); - } - - @Override - public Response lset(String key, long index, String value) { - return appendCommand(commandObjects.lset(key, index, value)); - } - - @Override - public Response lrem(String key, long count, String value) { - return appendCommand(commandObjects.lrem(key, count, value)); - } - - @Override - public Response lpop(String key) { - return appendCommand(commandObjects.lpop(key)); - } - - @Override - public Response> lpop(String key, int count) { - return appendCommand(commandObjects.lpop(key, count)); - } - - @Override - public Response lpos(String key, String element) { - return appendCommand(commandObjects.lpos(key, element)); - } - - @Override - public Response lpos(String key, String element, LPosParams params) { - return appendCommand(commandObjects.lpos(key, element, params)); - } - - @Override - public Response> lpos(String key, String element, LPosParams params, long count) { - return appendCommand(commandObjects.lpos(key, element, params, count)); - } - - @Override - public Response rpop(String key) { - return appendCommand(commandObjects.rpop(key)); - } - - @Override - public Response> rpop(String key, int count) { - return appendCommand(commandObjects.rpop(key, count)); - } - - @Override - public Response linsert(String key, ListPosition where, String pivot, String value) { - return appendCommand(commandObjects.linsert(key, where, pivot, value)); - } - - @Override - public Response lpushx(String key, String... strings) { - return appendCommand(commandObjects.lpushx(key, strings)); - } - - @Override - public Response rpushx(String key, String... strings) { - return appendCommand(commandObjects.rpushx(key, strings)); - } - - @Override - public Response> blpop(int timeout, String key) { - return appendCommand(commandObjects.blpop(timeout, key)); - } - - @Override - public Response blpop(double timeout, String key) { - return appendCommand(commandObjects.blpop(timeout, key)); - } - - @Override - public Response> brpop(int timeout, String key) { - return appendCommand(commandObjects.brpop(timeout, key)); - } - - @Override - public Response brpop(double timeout, String key) { - return appendCommand(commandObjects.brpop(timeout, key)); - } - - @Override - public Response> blpop(int timeout, String... keys) { - return appendCommand(commandObjects.blpop(timeout, keys)); - } - - @Override - public Response blpop(double timeout, String... keys) { - return appendCommand(commandObjects.blpop(timeout, keys)); - } - - @Override - public Response> brpop(int timeout, String... keys) { - return appendCommand(commandObjects.brpop(timeout, keys)); - } - - @Override - public Response brpop(double timeout, String... keys) { - return appendCommand(commandObjects.brpop(timeout, keys)); - } - - @Override - public Response rpoplpush(String srcKey, String dstKey) { - return appendCommand(commandObjects.rpoplpush(srcKey, dstKey)); - } - - @Override - public Response brpoplpush(String source, String destination, int timeout) { - return appendCommand(commandObjects.brpoplpush(source, destination, timeout)); - } - - @Override - public Response lmove(String srcKey, String dstKey, ListDirection from, ListDirection to) { - return appendCommand(commandObjects.lmove(srcKey, dstKey, from, to)); - } - - @Override - public Response blmove(String srcKey, String dstKey, ListDirection from, ListDirection to, double timeout) { - return appendCommand(commandObjects.blmove(srcKey, dstKey, from, to, timeout)); - } - - @Override - public Response>> lmpop(ListDirection direction, String... keys) { - return appendCommand(commandObjects.lmpop(direction, keys)); - } - - @Override - public Response>> lmpop(ListDirection direction, int count, String... keys) { - return appendCommand(commandObjects.lmpop(direction, count, keys)); - } - - @Override - public Response>> blmpop(long timeout, ListDirection direction, String... keys) { - return appendCommand(commandObjects.blmpop(timeout, direction, keys)); - } - - @Override - public Response>> blmpop(long timeout, ListDirection direction, int count, String... keys) { - return appendCommand(commandObjects.blmpop(timeout, direction, count, keys)); - } - - @Override - public Response hset(String key, String field, String value) { - return appendCommand(commandObjects.hset(key, field, value)); - } - - @Override - public Response hset(String key, Map hash) { - return appendCommand(commandObjects.hset(key, hash)); - } - - @Override - public Response hget(String key, String field) { - return appendCommand(commandObjects.hget(key, field)); - } - - @Override - public Response hsetnx(String key, String field, String value) { - return appendCommand(commandObjects.hsetnx(key, field, value)); - } - - @Override - public Response hmset(String key, Map hash) { - return appendCommand(commandObjects.hmset(key, hash)); - } - - @Override - public Response> hmget(String key, String... fields) { - return appendCommand(commandObjects.hmget(key, fields)); - } - - @Override - public Response hincrBy(String key, String field, long value) { - return appendCommand(commandObjects.hincrBy(key, field, value)); - } - - @Override - public Response hincrByFloat(String key, String field, double value) { - return appendCommand(commandObjects.hincrByFloat(key, field, value)); - } - - @Override - public Response hexists(String key, String field) { - return appendCommand(commandObjects.hexists(key, field)); - } - - @Override - public Response hdel(String key, String... field) { - return appendCommand(commandObjects.hdel(key, field)); - } - - @Override - public Response hlen(String key) { - return appendCommand(commandObjects.hlen(key)); - } - - @Override - public Response> hkeys(String key) { - return appendCommand(commandObjects.hkeys(key)); - } - - @Override - public Response> hvals(String key) { - return appendCommand(commandObjects.hvals(key)); - } - - @Override - public Response> hgetAll(String key) { - return appendCommand(commandObjects.hgetAll(key)); - } - - @Override - public Response hrandfield(String key) { - return appendCommand(commandObjects.hrandfield(key)); - } - - @Override - public Response> hrandfield(String key, long count) { - return appendCommand(commandObjects.hrandfield(key, count)); - } - - @Override - public Response> hrandfieldWithValues(String key, long count) { - return appendCommand(commandObjects.hrandfieldWithValues(key, count)); - } - - @Override - public Response>> hscan(String key, String cursor, ScanParams params) { - return appendCommand(commandObjects.hscan(key, cursor, params)); - } - - @Override - public Response hstrlen(String key, String field) { - return appendCommand(commandObjects.hstrlen(key, field)); - } - - @Override - public Response sadd(String key, String... members) { - return appendCommand(commandObjects.sadd(key, members)); - } - - @Override - public Response> smembers(String key) { - return appendCommand(commandObjects.smembers(key)); - } - - @Override - public Response srem(String key, String... members) { - return appendCommand(commandObjects.srem(key, members)); - } - - @Override - public Response spop(String key) { - return appendCommand(commandObjects.spop(key)); - } - - @Override - public Response> spop(String key, long count) { - return appendCommand(commandObjects.spop(key, count)); - } - - @Override - public Response scard(String key) { - return appendCommand(commandObjects.scard(key)); - } - - @Override - public Response sismember(String key, String member) { - return appendCommand(commandObjects.sismember(key, member)); - } - - @Override - public Response> smismember(String key, String... members) { - return appendCommand(commandObjects.smismember(key, members)); - } - - @Override - public Response srandmember(String key) { - return appendCommand(commandObjects.srandmember(key)); - } - - @Override - public Response> srandmember(String key, int count) { - return appendCommand(commandObjects.srandmember(key, count)); - } - - @Override - public Response> sscan(String key, String cursor, ScanParams params) { - return appendCommand(commandObjects.sscan(key, cursor, params)); - } - - @Override - public Response> sdiff(String... keys) { - return appendCommand(commandObjects.sdiff(keys)); - } - - @Override - public Response sdiffstore(String dstKey, String... keys) { - return appendCommand(commandObjects.sdiffstore(dstKey, keys)); - } - - @Override - public Response> sinter(String... keys) { - return appendCommand(commandObjects.sinter(keys)); - } - - @Override - public Response sinterstore(String dstKey, String... keys) { - return appendCommand(commandObjects.sinterstore(dstKey, keys)); - } - - @Override - public Response sintercard(String... keys){ - return appendCommand(commandObjects.sintercard(keys)); - } - - @Override - public Response sintercard(int limit, String... keys){ - return appendCommand(commandObjects.sintercard(limit, keys)); - } - - @Override - public Response> sunion(String... keys) { - return appendCommand(commandObjects.sunion(keys)); - } - - @Override - public Response sunionstore(String dstKey, String... keys) { - return appendCommand(commandObjects.sunionstore(dstKey, keys)); - } - - @Override - public Response smove(String srcKey, String dstKey, String member) { - return appendCommand(commandObjects.smove(srcKey, dstKey, member)); - } - - @Override - public Response zadd(String key, double score, String member) { - return appendCommand(commandObjects.zadd(key, score, member)); - } - - @Override - public Response zadd(String key, double score, String member, ZAddParams params) { - return appendCommand(commandObjects.zadd(key, score, member, params)); - } - - @Override - public Response zadd(String key, Map scoreMembers) { - return appendCommand(commandObjects.zadd(key, scoreMembers)); - } - - @Override - public Response zadd(String key, Map scoreMembers, ZAddParams params) { - return appendCommand(commandObjects.zadd(key, scoreMembers, params)); - } - - @Override - public Response zaddIncr(String key, double score, String member, ZAddParams params) { - return appendCommand(commandObjects.zaddIncr(key, score, member, params)); - } - - @Override - public Response zrem(String key, String... members) { - return appendCommand(commandObjects.zrem(key, members)); - } - - @Override - public Response zincrby(String key, double increment, String member) { - return appendCommand(commandObjects.zincrby(key, increment, member)); - } - - @Override - public Response zincrby(String key, double increment, String member, ZIncrByParams params) { - return appendCommand(commandObjects.zincrby(key, increment, member, params)); - } - - @Override - public Response zrank(String key, String member) { - return appendCommand(commandObjects.zrank(key, member)); - } - - @Override - public Response zrevrank(String key, String member) { - return appendCommand(commandObjects.zrevrank(key, member)); - } - - @Override - public Response> zrange(String key, long start, long stop) { - return appendCommand(commandObjects.zrange(key, start, stop)); - } - - @Override - public Response> zrevrange(String key, long start, long stop) { - return appendCommand(commandObjects.zrevrange(key, start, stop)); - } - - @Override - public Response> zrangeWithScores(String key, long start, long stop) { - return appendCommand(commandObjects.zrangeWithScores(key, start, stop)); - } - - @Override - public Response> zrevrangeWithScores(String key, long start, long stop) { - return appendCommand(commandObjects.zrevrangeWithScores(key, start, stop)); - } - - @Override - public Response> zrange(String key, ZRangeParams zRangeParams) { - return appendCommand(commandObjects.zrange(key, zRangeParams)); - } - - @Override - public Response> zrangeWithScores(String key, ZRangeParams zRangeParams) { - return appendCommand(commandObjects.zrangeWithScores(key, zRangeParams)); - } - - @Override - public Response zrangestore(String dest, String src, ZRangeParams zRangeParams) { - return appendCommand(commandObjects.zrangestore(dest, src, zRangeParams)); - } - - @Override - public Response zrandmember(String key) { - return appendCommand(commandObjects.zrandmember(key)); - } - - @Override - public Response> zrandmember(String key, long count) { - return appendCommand(commandObjects.zrandmember(key, count)); - } - - @Override - public Response> zrandmemberWithScores(String key, long count) { - return appendCommand(commandObjects.zrandmemberWithScores(key, count)); - } - - @Override - public Response zcard(String key) { - return appendCommand(commandObjects.zcard(key)); - } - - @Override - public Response zscore(String key, String member) { - return appendCommand(commandObjects.zscore(key, member)); - } - - @Override - public Response> zmscore(String key, String... members) { - return appendCommand(commandObjects.zmscore(key, members)); - } - - @Override - public Response zpopmax(String key) { - return appendCommand(commandObjects.zpopmax(key)); - } - - @Override - public Response> zpopmax(String key, int count) { - return appendCommand(commandObjects.zpopmax(key, count)); - } - - @Override - public Response zpopmin(String key) { - return appendCommand(commandObjects.zpopmin(key)); - } - - @Override - public Response> zpopmin(String key, int count) { - return appendCommand(commandObjects.zpopmin(key, count)); - } - - @Override - public Response zcount(String key, double min, double max) { - return appendCommand(commandObjects.zcount(key, min, max)); - } - - @Override - public Response zcount(String key, String min, String max) { - return appendCommand(commandObjects.zcount(key, min, max)); - } - - @Override - public Response> zrangeByScore(String key, double min, double max) { - return appendCommand(commandObjects.zrangeByScore(key, min, max)); - } - - @Override - public Response> zrangeByScore(String key, String min, String max) { - return appendCommand(commandObjects.zrangeByScore(key, min, max)); - } - - @Override - public Response> zrevrangeByScore(String key, double max, double min) { - return appendCommand(commandObjects.zrevrangeByScore(key, max, min)); - - } - - @Override - public Response> zrangeByScore(String key, double min, double max, int offset, int count) { - return appendCommand(commandObjects.zrangeByScore(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByScore(String key, String max, String min) { - return appendCommand(commandObjects.zrevrangeByScore(key, max, min)); - } - - @Override - public Response> zrangeByScore(String key, String min, String max, int offset, int count) { - return appendCommand(commandObjects.zrangeByScore(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByScore(String key, double max, double min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByScore(key, max, min, offset, count)); - } - - @Override - public Response> zrangeByScoreWithScores(String key, double min, double max) { - return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max)); - } - - @Override - public Response> zrevrangeByScoreWithScores(String key, double max, double min) { - return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min)); - } - - @Override - public Response> zrangeByScoreWithScores(String key, double min, double max, int offset, int count) { - return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByScore(String key, String max, String min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByScore(key, max, min, offset, count)); - } - - @Override - public Response> zrangeByScoreWithScores(String key, String min, String max) { - return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max)); - } - - @Override - public Response> zrevrangeByScoreWithScores(String key, String max, String min) { - return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min)); - } - - @Override - public Response> zrangeByScoreWithScores(String key, String min, String max, int offset, int count) { - return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByScoreWithScores(String key, double max, double min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min, offset, count)); - } - - @Override - public Response> zrevrangeByScoreWithScores(String key, String max, String min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min, offset, count)); - } - - @Override - public Response zremrangeByRank(String key, long start, long stop) { - return appendCommand(commandObjects.zremrangeByRank(key, start, stop)); - } - - @Override - public Response zremrangeByScore(String key, double min, double max) { - return appendCommand(commandObjects.zremrangeByScore(key, min, max)); - } - - @Override - public Response zremrangeByScore(String key, String min, String max) { - return appendCommand(commandObjects.zremrangeByScore(key, min, max)); - } - - @Override - public Response zlexcount(String key, String min, String max) { - return appendCommand(commandObjects.zlexcount(key, min, max)); - } - - @Override - public Response> zrangeByLex(String key, String min, String max) { - return appendCommand(commandObjects.zrangeByLex(key, min, max)); - } - - @Override - public Response> zrangeByLex(String key, String min, String max, int offset, int count) { - return appendCommand(commandObjects.zrangeByLex(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByLex(String key, String max, String min) { - return appendCommand(commandObjects.zrevrangeByLex(key, max, min)); - } - - @Override - public Response> zrevrangeByLex(String key, String max, String min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByLex(key, max, min, offset, count)); - } - - @Override - public Response zremrangeByLex(String key, String min, String max) { - return appendCommand(commandObjects.zremrangeByLex(key, min, max)); - } - - @Override - public Response> zscan(String key, String cursor, ScanParams params) { - return appendCommand(commandObjects.zscan(key, cursor, params)); - } - - @Override - public Response bzpopmax(double timeout, String... keys) { - return appendCommand(commandObjects.bzpopmax(timeout, keys)); - } - - @Override - public Response bzpopmin(double timeout, String... keys) { - return appendCommand(commandObjects.bzpopmin(timeout, keys)); - } - - @Override - public Response>> zmpop(SortedSetOption option, String... keys) { - return appendCommand(commandObjects.zmpop(option, keys)); - } - - @Override - public Response>> zmpop(SortedSetOption option, int count, String... keys) { - return appendCommand(commandObjects.zmpop(option, count, keys)); - } - - @Override - public Response>> bzmpop(long timeout, SortedSetOption option, String... keys) { - return appendCommand(commandObjects.bzmpop(timeout, option, keys)); - } - - @Override - public Response>> bzmpop(long timeout, SortedSetOption option, int count, String... keys) { - return appendCommand(commandObjects.bzmpop(timeout, option, count, keys)); - } - - @Override - public Response> zdiff(String... keys) { - return appendCommand(commandObjects.zdiff(keys)); - } - - @Override - public Response> zdiffWithScores(String... keys) { - return appendCommand(commandObjects.zdiffWithScores(keys)); - } - - @Override - public Response zdiffStore(String dstKey, String... keys) { - return appendCommand(commandObjects.zdiffStore(dstKey, keys)); - } - - @Override - public Response zinterstore(String dstKey, String... sets) { - return appendCommand(commandObjects.zinterstore(dstKey, sets)); - } - - @Override - public Response zinterstore(String dstKey, ZParams params, String... sets) { - return appendCommand(commandObjects.zinterstore(dstKey, params, sets)); - } - - @Override - public Response> zinter(ZParams params, String... keys) { - return appendCommand(commandObjects.zinter(params, keys)); - } - - @Override - public Response> zinterWithScores(ZParams params, String... keys) { - return appendCommand(commandObjects.zinterWithScores(params, keys)); - } - - @Override - public Response zintercard(String... keys) { - return appendCommand(commandObjects.zintercard(keys)); - } - - @Override - public Response zintercard(long limit, String... keys) { - return appendCommand(commandObjects.zintercard(limit, keys)); - } - - @Override - public Response> zunion(ZParams params, String... keys) { - return appendCommand(commandObjects.zunion(params, keys)); - } - - @Override - public Response> zunionWithScores(ZParams params, String... keys) { - return appendCommand(commandObjects.zunionWithScores(params, keys)); - } - - @Override - public Response zunionstore(String dstKey, String... sets) { - return appendCommand(commandObjects.zunionstore(dstKey, sets)); - } - - @Override - public Response zunionstore(String dstKey, ZParams params, String... sets) { - return appendCommand(commandObjects.zunionstore(dstKey, params, sets)); - } - - @Override - public Response geoadd(String key, double longitude, double latitude, String member) { - return appendCommand(commandObjects.geoadd(key, longitude, latitude, member)); - } - - @Override - public Response geoadd(String key, Map memberCoordinateMap) { - return appendCommand(commandObjects.geoadd(key, memberCoordinateMap)); - } - - @Override - public Response geoadd(String key, GeoAddParams params, Map memberCoordinateMap) { - return appendCommand(commandObjects.geoadd(key, params, memberCoordinateMap)); - } - - @Override - public Response geodist(String key, String member1, String member2) { - return appendCommand(commandObjects.geodist(key, member1, member2)); - } - - @Override - public Response geodist(String key, String member1, String member2, GeoUnit unit) { - return appendCommand(commandObjects.geodist(key, member1, member2, unit)); - } - - @Override - public Response> geohash(String key, String... members) { - return appendCommand(commandObjects.geohash(key, members)); - } - - @Override - public Response> geopos(String key, String... members) { - return appendCommand(commandObjects.geopos(key, members)); - } - - @Override - public Response> georadius(String key, double longitude, double latitude, double radius, GeoUnit unit) { - return appendCommand(commandObjects.georadius(key, longitude, latitude, radius, unit)); - } - - @Override - public Response> georadiusReadonly(String key, double longitude, double latitude, double radius, GeoUnit unit) { - return appendCommand(commandObjects.georadiusReadonly(key, longitude, latitude, radius, unit)); - } - - @Override - public Response> georadius(String key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param) { - return appendCommand(commandObjects.georadius(key, longitude, latitude, radius, unit, param)); - } - - @Override - public Response> georadiusReadonly(String key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param) { - return appendCommand(commandObjects.georadiusReadonly(key, longitude, latitude, radius, unit, param)); - } - - @Override - public Response> georadiusByMember(String key, String member, double radius, GeoUnit unit) { - return appendCommand(commandObjects.georadiusByMember(key, member, radius, unit)); - } - - @Override - public Response> georadiusByMemberReadonly(String key, String member, double radius, GeoUnit unit) { - return appendCommand(commandObjects.georadiusByMemberReadonly(key, member, radius, unit)); - } - - @Override - public Response> georadiusByMember(String key, String member, double radius, GeoUnit unit, GeoRadiusParam param) { - return appendCommand(commandObjects.georadiusByMember(key, member, radius, unit, param)); - } - - @Override - public Response> georadiusByMemberReadonly(String key, String member, double radius, GeoUnit unit, GeoRadiusParam param) { - return appendCommand(commandObjects.georadiusByMemberReadonly(key, member, radius, unit, param)); - } - - @Override - public Response georadiusStore(String key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param, GeoRadiusStoreParam storeParam) { - return appendCommand(commandObjects.georadiusStore(key, longitude, latitude, radius, unit, param, storeParam)); - } - - @Override - public Response georadiusByMemberStore(String key, String member, double radius, GeoUnit unit, GeoRadiusParam param, GeoRadiusStoreParam storeParam) { - return appendCommand(commandObjects.georadiusByMemberStore(key, member, radius, unit, param, storeParam)); - } - - @Override - public Response> geosearch(String key, String member, double radius, GeoUnit unit) { - return appendCommand(commandObjects.geosearch(key, member, radius, unit)); - } - - @Override - public Response> geosearch(String key, GeoCoordinate coord, double radius, GeoUnit unit) { - return appendCommand(commandObjects.geosearch(key, coord, radius, unit)); - } - - @Override - public Response> geosearch(String key, String member, double width, double height, GeoUnit unit) { - return appendCommand(commandObjects.geosearch(key, member, width, height, unit)); - } - - @Override - public Response> geosearch(String key, GeoCoordinate coord, double width, double height, GeoUnit unit) { - return appendCommand(commandObjects.geosearch(key, coord, width, height, unit)); - } - - @Override - public Response> geosearch(String key, GeoSearchParam params) { - return appendCommand(commandObjects.geosearch(key, params)); - } - - @Override - public Response geosearchStore(String dest, String src, String member, double radius, GeoUnit unit) { - return appendCommand(commandObjects.geosearchStore(dest, src, member, radius, unit)); - } - - @Override - public Response geosearchStore(String dest, String src, GeoCoordinate coord, double radius, GeoUnit unit) { - return appendCommand(commandObjects.geosearchStore(dest, src, coord, radius, unit)); - } - - @Override - public Response geosearchStore(String dest, String src, String member, double width, double height, GeoUnit unit) { - return appendCommand(commandObjects.geosearchStore(dest, src, member, width, height, unit)); - } - - @Override - public Response geosearchStore(String dest, String src, GeoCoordinate coord, double width, double height, GeoUnit unit) { - return appendCommand(commandObjects.geosearchStore(dest, src, coord, width, height, unit)); - } - - @Override - public Response geosearchStore(String dest, String src, GeoSearchParam params) { - return appendCommand(commandObjects.geosearchStore(dest, src, params)); - } - - @Override - public Response geosearchStoreStoreDist(String dest, String src, GeoSearchParam params) { - return appendCommand(commandObjects.geosearchStoreStoreDist(dest, src, params)); - } - - @Override - public Response pfadd(String key, String... elements) { - return appendCommand(commandObjects.pfadd(key, elements)); - } - - @Override - public Response pfmerge(String destkey, String... sourcekeys) { - return appendCommand(commandObjects.pfmerge(destkey, sourcekeys)); - } - - @Override - public Response pfcount(String key) { - return appendCommand(commandObjects.pfcount(key)); - } - - @Override - public Response pfcount(String... keys) { - return appendCommand(commandObjects.pfcount(keys)); - } - - @Override - public Response xadd(String key, StreamEntryID id, Map hash) { - return appendCommand(commandObjects.xadd(key, id, hash)); - } - - @Override - public Response xadd(String key, XAddParams params, Map hash) { - return appendCommand(commandObjects.xadd(key, params, hash)); - } - - @Override - public Response xlen(String key) { - return appendCommand(commandObjects.xlen(key)); - } - - @Override - public Response> xrange(String key, StreamEntryID start, StreamEntryID end) { - return appendCommand(commandObjects.xrange(key, start, end)); - } - - @Override - public Response> xrange(String key, StreamEntryID start, StreamEntryID end, int count) { - return appendCommand(commandObjects.xrange(key, start, end, count)); - } - - @Override - public Response> xrevrange(String key, StreamEntryID end, StreamEntryID start) { - return appendCommand(commandObjects.xrevrange(key, start, end)); - } - - @Override - public Response> xrevrange(String key, StreamEntryID end, StreamEntryID start, int count) { - return appendCommand(commandObjects.xrevrange(key, start, end, count)); - } - - @Override - public Response> xrange(String key, String start, String end) { - return appendCommand(commandObjects.xrange(key, start, end)); - } - - @Override - public Response> xrange(String key, String start, String end, int count) { - return appendCommand(commandObjects.xrange(key, start, end, count)); - } - - @Override - public Response> xrevrange(String key, String end, String start) { - return appendCommand(commandObjects.xrevrange(key, start, end)); - } - - @Override - public Response> xrevrange(String key, String end, String start, int count) { - return appendCommand(commandObjects.xrevrange(key, start, end, count)); - } - - @Override - public Response xack(String key, String group, StreamEntryID... ids) { - return appendCommand(commandObjects.xack(key, group, ids)); - } - - @Override - public Response xgroupCreate(String key, String groupName, StreamEntryID id, boolean makeStream) { - return appendCommand(commandObjects.xgroupCreate(key, groupName, id, makeStream)); - } - - @Override - public Response xgroupSetID(String key, String groupName, StreamEntryID id) { - return appendCommand(commandObjects.xgroupSetID(key, groupName, id)); - } - - @Override - public Response xgroupDestroy(String key, String groupName) { - return appendCommand(commandObjects.xgroupDestroy(key, groupName)); - } - - @Override - public Response xgroupCreateConsumer(String key, String groupName, String consumerName) { - return appendCommand(commandObjects.xgroupCreateConsumer(key, groupName, consumerName)); - } - - @Override - public Response xgroupDelConsumer(String key, String groupName, String consumerName) { - return appendCommand(commandObjects.xgroupDelConsumer(key, groupName, consumerName)); - } - - @Override - public Response xpending(String key, String groupName) { - return appendCommand(commandObjects.xpending(key, groupName)); - } - - @Override - public Response> xpending(String key, String groupName, StreamEntryID start, StreamEntryID end, int count, String consumerName) { - return appendCommand(commandObjects.xpending(key, groupName, start, end, count, consumerName)); - } - - @Override - public Response> xpending(String key, String groupName, XPendingParams params) { - return appendCommand(commandObjects.xpending(key, groupName, params)); - } - - @Override - public Response xdel(String key, StreamEntryID... ids) { - return appendCommand(commandObjects.xdel(key, ids)); - } - - @Override - public Response xtrim(String key, long maxLen, boolean approximate) { - return appendCommand(commandObjects.xtrim(key, maxLen, approximate)); - } - - @Override - public Response xtrim(String key, XTrimParams params) { - return appendCommand(commandObjects.xtrim(key, params)); - } - - @Override - public Response> xclaim(String key, String group, String consumerName, long minIdleTime, XClaimParams params, StreamEntryID... ids) { - return appendCommand(commandObjects.xclaim(key, group, consumerName, minIdleTime, params, ids)); - } - - @Override - public Response> xclaimJustId(String key, String group, String consumerName, long minIdleTime, XClaimParams params, StreamEntryID... ids) { - return appendCommand(commandObjects.xclaimJustId(key, group, consumerName, minIdleTime, params, ids)); - } - - @Override - public Response>> xautoclaim(String key, String group, String consumerName, long minIdleTime, StreamEntryID start, XAutoClaimParams params) { - return appendCommand(commandObjects.xautoclaim(key, group, consumerName, minIdleTime, start, params)); - } - - @Override - public Response>> xautoclaimJustId(String key, String group, String consumerName, long minIdleTime, StreamEntryID start, XAutoClaimParams params) { - return appendCommand(commandObjects.xautoclaimJustId(key, group, consumerName, minIdleTime, start, params)); - } - - @Override - public Response xinfoStream(String key) { - return appendCommand(commandObjects.xinfoStream(key)); - } - - @Override - public Response xinfoStreamFull(String key) { - return appendCommand(commandObjects.xinfoStreamFull(key)); - } - - @Override - public Response xinfoStreamFull(String key, int count) { - return appendCommand(commandObjects.xinfoStreamFull(key, count)); - } - - @Override - @Deprecated - public Response> xinfoGroup(String key) { - return appendCommand(commandObjects.xinfoGroup(key)); - } - - @Override - public Response> xinfoGroups(String key) { - return appendCommand(commandObjects.xinfoGroups(key)); - } - - @Override - public Response> xinfoConsumers(String key, String group) { - return appendCommand(commandObjects.xinfoConsumers(key, group)); - } - - @Override - public Response>>> xread(XReadParams xReadParams, Map streams) { - return appendCommand(commandObjects.xread(xReadParams, streams)); - } - - @Override - public Response>>> xreadGroup(String groupName, String consumer, XReadGroupParams xReadGroupParams, Map streams) { - return appendCommand(commandObjects.xreadGroup(groupName, consumer, xReadGroupParams, streams)); - } - - @Override - public Response eval(String script) { - return appendCommand(commandObjects.eval(script)); - } - - @Override - public Response eval(String script, int keyCount, String... params) { - return appendCommand(commandObjects.eval(script, keyCount, params)); - } - - @Override - public Response eval(String script, List keys, List args) { - return appendCommand(commandObjects.eval(script, keys, args)); - } - - @Override - public Response evalReadonly(String script, List keys, List args) { - return appendCommand(commandObjects.evalReadonly(script, keys, args)); - } - - @Override - public Response evalsha(String sha1) { - return appendCommand(commandObjects.evalsha(sha1)); - } - - @Override - public Response evalsha(String sha1, int keyCount, String... params) { - return appendCommand(commandObjects.evalsha(sha1, keyCount, params)); - } - - @Override - public Response evalsha(String sha1, List keys, List args) { - return appendCommand(commandObjects.evalsha(sha1, keys, args)); - } - - @Override - public Response evalshaReadonly(String sha1, List keys, List args) { - return appendCommand(commandObjects.evalshaReadonly(sha1, keys, args)); - } - - @Override - public Response waitReplicas(String sampleKey, int replicas, long timeout) { - return appendCommand(commandObjects.waitReplicas(sampleKey, replicas, timeout)); - } - - @Override - public Response eval(String script, String sampleKey) { - return appendCommand(commandObjects.eval(script, sampleKey)); - } - - @Override - public Response evalsha(String sha1, String sampleKey) { - return appendCommand(commandObjects.evalsha(sha1, sampleKey)); - } - - @Override - public Response> scriptExists(String sampleKey, String... sha1) { - return appendCommand(commandObjects.scriptExists(sampleKey, sha1)); - } - - @Override - public Response scriptLoad(String script, String sampleKey) { - return appendCommand(commandObjects.scriptLoad(script, sampleKey)); - } - - @Override - public Response scriptFlush(String sampleKey) { - return appendCommand(commandObjects.scriptFlush(sampleKey)); - } - - @Override - public Response scriptFlush(String sampleKey, FlushMode flushMode) { - return appendCommand(commandObjects.scriptFlush(sampleKey, flushMode)); - } - - @Override - public Response scriptKill(String sampleKey) { - return appendCommand(commandObjects.scriptKill(sampleKey)); - } - - @Override - public Response fcall(byte[] name, List keys, List args) { - return appendCommand(commandObjects.fcall(name, keys, args)); - } - - @Override - public Response fcall(String name, List keys, List args) { - return appendCommand(commandObjects.fcall(name, keys, args)); - } - - @Override - public Response fcallReadonly(byte[] name, List keys, List args) { - return appendCommand(commandObjects.fcallReadonly(name, keys, args)); - } - - @Override - public Response fcallReadonly(String name, List keys, List args) { - return appendCommand(commandObjects.fcallReadonly(name, keys, args)); - } - - @Override - public Response functionDelete(byte[] libraryName) { - return appendCommand(commandObjects.functionDelete(libraryName)); - } - - @Override - public Response functionDelete(String libraryName) { - return appendCommand(commandObjects.functionDelete(libraryName)); - } - - @Override - public Response functionDump() { - return appendCommand(commandObjects.functionDump()); - } - - @Override - public Response> functionList(String libraryNamePattern) { - return appendCommand(commandObjects.functionList(libraryNamePattern)); - } - - @Override - public Response> functionList() { - return appendCommand(commandObjects.functionList()); - } - - @Override - public Response> functionListWithCode(String libraryNamePattern) { - return appendCommand(commandObjects.functionListWithCode(libraryNamePattern)); - } - - @Override - public Response> functionListWithCode() { - return appendCommand(commandObjects.functionListWithCode()); - } - - @Override - public Response> functionListBinary() { - return appendCommand(commandObjects.functionListBinary()); - } - - @Override - public Response> functionList(final byte[] libraryNamePattern) { - return appendCommand(commandObjects.functionList(libraryNamePattern)); - } - - @Override - public Response> functionListWithCodeBinary() { - return appendCommand(commandObjects.functionListWithCodeBinary()); - } - - @Override - public Response> functionListWithCode(final byte[] libraryNamePattern) { - return appendCommand(commandObjects.functionListWithCode(libraryNamePattern)); - } - - @Override - public Response functionLoad(byte[] functionCode) { - return appendCommand(commandObjects.functionLoad(functionCode)); - } - - @Override - public Response functionLoad(String functionCode) { - return appendCommand(commandObjects.functionLoad(functionCode)); - } - - @Override - public Response functionLoadReplace(byte[] functionCode) { - return appendCommand(commandObjects.functionLoadReplace(functionCode)); - } - - @Override - public Response functionLoadReplace(String functionCode) { - return appendCommand(commandObjects.functionLoadReplace(functionCode)); - } - - @Override - public Response functionRestore(byte[] serializedValue) { - return appendCommand(commandObjects.functionRestore(serializedValue)); - } - - @Override - public Response functionRestore(byte[] serializedValue, FunctionRestorePolicy policy) { - return appendCommand(commandObjects.functionRestore(serializedValue, policy)); - } - - @Override - public Response functionFlush() { - return appendCommand(commandObjects.functionFlush()); - } - - @Override - public Response functionFlush(FlushMode mode) { - return appendCommand(commandObjects.functionFlush(mode)); - } - - @Override - public Response functionKill() { - return appendCommand(commandObjects.functionKill()); - } - - @Override - public Response functionStats() { - return appendCommand(commandObjects.functionStats()); - } - - @Override - public Response functionStatsBinary() { - return appendCommand(commandObjects.functionStatsBinary()); - } - - public Response publish(String channel, String message) { - return appendCommand(commandObjects.publish(channel, message)); - } - - public Response strAlgoLCSStrings(String strA, String strB, StrAlgoLCSParams params) { - return appendCommand(commandObjects.strAlgoLCSStrings(strA, strB, params)); - } - - @Override - public Response geoadd(byte[] key, double longitude, double latitude, byte[] member) { - return appendCommand(commandObjects.geoadd(key, longitude, latitude, member)); - } - - @Override - public Response geoadd(byte[] key, Map memberCoordinateMap) { - return appendCommand(commandObjects.geoadd(key, memberCoordinateMap)); - } - - @Override - public Response geoadd(byte[] key, GeoAddParams params, Map memberCoordinateMap) { - return appendCommand(commandObjects.geoadd(key, params, memberCoordinateMap)); - } - - @Override - public Response geodist(byte[] key, byte[] member1, byte[] member2) { - return appendCommand(commandObjects.geodist(key, member1, member2)); - } - - @Override - public Response geodist(byte[] key, byte[] member1, byte[] member2, GeoUnit unit) { - return appendCommand(commandObjects.geodist(key, member1, member2, unit)); - } - - @Override - public Response> geohash(byte[] key, byte[]... members) { - return appendCommand(commandObjects.geohash(key, members)); - } - - @Override - public Response> geopos(byte[] key, byte[]... members) { - return appendCommand(commandObjects.geopos(key, members)); - } - - @Override - public Response> georadius(byte[] key, double longitude, double latitude, double radius, GeoUnit unit) { - return appendCommand(commandObjects.georadius(key, longitude, latitude, radius, unit)); - } - - @Override - public Response> georadiusReadonly(byte[] key, double longitude, double latitude, double radius, GeoUnit unit) { - return appendCommand(commandObjects.georadiusReadonly(key, longitude, latitude, radius, unit)); - } - - @Override - public Response> georadius(byte[] key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param) { - return appendCommand(commandObjects.georadius(key, longitude, latitude, radius, unit, param)); - } - - @Override - public Response> georadiusReadonly(byte[] key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param) { - return appendCommand(commandObjects.georadiusReadonly(key, longitude, latitude, radius, unit, param)); - } - - @Override - public Response> georadiusByMember(byte[] key, byte[] member, double radius, GeoUnit unit) { - return appendCommand(commandObjects.georadiusByMember(key, member, radius, unit)); - } - - @Override - public Response> georadiusByMemberReadonly(byte[] key, byte[] member, double radius, GeoUnit unit) { - return appendCommand(commandObjects.georadiusByMemberReadonly(key, member, radius, unit)); - } - - @Override - public Response> georadiusByMember(byte[] key, byte[] member, double radius, GeoUnit unit, GeoRadiusParam param) { - return appendCommand(commandObjects.georadiusByMember(key, member, radius, unit, param)); - } - - @Override - public Response> georadiusByMemberReadonly(byte[] key, byte[] member, double radius, GeoUnit unit, GeoRadiusParam param) { - return appendCommand(commandObjects.georadiusByMemberReadonly(key, member, radius, unit, param)); - } - - @Override - public Response georadiusStore(byte[] key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param, GeoRadiusStoreParam storeParam) { - return appendCommand(commandObjects.georadiusStore(key, longitude, latitude, radius, unit, param, storeParam)); - } - - @Override - public Response georadiusByMemberStore(byte[] key, byte[] member, double radius, GeoUnit unit, GeoRadiusParam param, GeoRadiusStoreParam storeParam) { - return appendCommand(commandObjects.georadiusByMemberStore(key, member, radius, unit, param, storeParam)); - } - - @Override - public Response> geosearch(byte[] key, byte[] member, double radius, GeoUnit unit) { - return appendCommand(commandObjects.geosearch(key, member, radius, unit)); - } - - @Override - public Response> geosearch(byte[] key, GeoCoordinate coord, double radius, GeoUnit unit) { - return appendCommand(commandObjects.geosearch(key, coord, radius, unit)); - } - - @Override - public Response> geosearch(byte[] key, byte[] member, double width, double height, GeoUnit unit) { - return appendCommand(commandObjects.geosearch(key, member, width, height, unit)); - } - - @Override - public Response> geosearch(byte[] key, GeoCoordinate coord, double width, double height, GeoUnit unit) { - return appendCommand(commandObjects.geosearch(key, coord, width, height, unit)); - } - - @Override - public Response> geosearch(byte[] key, GeoSearchParam params) { - return appendCommand(commandObjects.geosearch(key, params)); - } - - @Override - public Response geosearchStore(byte[] dest, byte[] src, byte[] member, double radius, GeoUnit unit) { - return appendCommand(commandObjects.geosearchStore(dest, src, member, radius, unit)); - } - - @Override - public Response geosearchStore(byte[] dest, byte[] src, GeoCoordinate coord, double radius, GeoUnit unit) { - return appendCommand(commandObjects.geosearchStore(dest, src, coord, radius, unit)); - } - - @Override - public Response geosearchStore(byte[] dest, byte[] src, byte[] member, double width, double height, GeoUnit unit) { - return appendCommand(commandObjects.geosearchStore(dest, src, member, width, height, unit)); - } - - @Override - public Response geosearchStore(byte[] dest, byte[] src, GeoCoordinate coord, double width, double height, GeoUnit unit) { - return appendCommand(commandObjects.geosearchStore(dest, src, coord, width, height, unit)); - } - - @Override - public Response geosearchStore(byte[] dest, byte[] src, GeoSearchParam params) { - return appendCommand(commandObjects.geosearchStore(dest, src, params)); - } - - @Override - public Response geosearchStoreStoreDist(byte[] dest, byte[] src, GeoSearchParam params) { - return appendCommand(commandObjects.geosearchStoreStoreDist(dest, src, params)); - } - - @Override - public Response hset(byte[] key, byte[] field, byte[] value) { - return appendCommand(commandObjects.hset(key, field, value)); - } - - @Override - public Response hset(byte[] key, Map hash) { - return appendCommand(commandObjects.hset(key, hash)); - } - - @Override - public Response hget(byte[] key, byte[] field) { - return appendCommand(commandObjects.hget(key, field)); - } - - @Override - public Response hsetnx(byte[] key, byte[] field, byte[] value) { - return appendCommand(commandObjects.hsetnx(key, field, value)); - } - - @Override - public Response hmset(byte[] key, Map hash) { - return appendCommand(commandObjects.hmset(key, hash)); - } - - @Override - public Response> hmget(byte[] key, byte[]... fields) { - return appendCommand(commandObjects.hmget(key, fields)); - } - - @Override - public Response hincrBy(byte[] key, byte[] field, long value) { - return appendCommand(commandObjects.hincrBy(key, field, value)); - } - - @Override - public Response hincrByFloat(byte[] key, byte[] field, double value) { - return appendCommand(commandObjects.hincrByFloat(key, field, value)); - } - - @Override - public Response hexists(byte[] key, byte[] field) { - return appendCommand(commandObjects.hexists(key, field)); - } - - @Override - public Response hdel(byte[] key, byte[]... field) { - return appendCommand(commandObjects.hdel(key, field)); - } - - @Override - public Response hlen(byte[] key) { - return appendCommand(commandObjects.hlen(key)); - } - - @Override - public Response> hkeys(byte[] key) { - return appendCommand(commandObjects.hkeys(key)); - } - - @Override - public Response> hvals(byte[] key) { - return appendCommand(commandObjects.hvals(key)); - } - - @Override - public Response> hgetAll(byte[] key) { - return appendCommand(commandObjects.hgetAll(key)); - } - - @Override - public Response hrandfield(byte[] key) { - return appendCommand(commandObjects.hrandfield(key)); - } - - @Override - public Response> hrandfield(byte[] key, long count) { - return appendCommand(commandObjects.hrandfield(key, count)); - } - - @Override - public Response> hrandfieldWithValues(byte[] key, long count) { - return appendCommand(commandObjects.hrandfieldWithValues(key, count)); - } - - @Override - public Response>> hscan(byte[] key, byte[] cursor, ScanParams params) { - return appendCommand(commandObjects.hscan(key, cursor, params)); - } - - @Override - public Response hstrlen(byte[] key, byte[] field) { - return appendCommand(commandObjects.hstrlen(key, field)); - } - - @Override - public Response pfadd(byte[] key, byte[]... elements) { - return appendCommand(commandObjects.pfadd(key, elements)); - } - - @Override - public Response pfmerge(byte[] destkey, byte[]... sourcekeys) { - return appendCommand(commandObjects.pfmerge(destkey, sourcekeys)); - } - - @Override - public Response pfcount(byte[] key) { - return appendCommand(commandObjects.pfcount(key)); - } - - @Override - public Response pfcount(byte[]... keys) { - return appendCommand(commandObjects.pfcount(keys)); - } - - @Override - public Response exists(byte[] key) { - return appendCommand(commandObjects.exists(key)); - } - - @Override - public Response exists(byte[]... keys) { - return appendCommand(commandObjects.exists(keys)); - } - - @Override - public Response persist(byte[] key) { - return appendCommand(commandObjects.persist(key)); - } - - @Override - public Response type(byte[] key) { - return appendCommand(commandObjects.type(key)); - } - - @Override - public Response dump(byte[] key) { - return appendCommand(commandObjects.dump(key)); - } - - @Override - public Response restore(byte[] key, long ttl, byte[] serializedValue) { - return appendCommand(commandObjects.restore(key, ttl, serializedValue)); - } - - @Override - public Response restore(byte[] key, long ttl, byte[] serializedValue, RestoreParams params) { - return appendCommand(commandObjects.restore(key, ttl, serializedValue, params)); - } - - @Override - public Response expire(byte[] key, long seconds) { - return appendCommand(commandObjects.expire(key, seconds)); - } - - @Override - public Response expire(byte[] key, long seconds, ExpiryOption expiryOption) { - return appendCommand(commandObjects.expire(key, seconds, expiryOption)); - } - - @Override - public Response pexpire(byte[] key, long milliseconds) { - return appendCommand(commandObjects.pexpire(key, milliseconds)); - } - - @Override - public Response pexpire(byte[] key, long milliseconds, ExpiryOption expiryOption) { - return appendCommand(commandObjects.pexpire(key, milliseconds, expiryOption)); - } - - @Override - public Response expireTime(byte[] key) { - return appendCommand(commandObjects.expireTime(key)); - } - - @Override - public Response pexpireTime(byte[] key) { - return appendCommand(commandObjects.pexpireTime(key)); - } - - @Override - public Response expireAt(byte[] key, long unixTime) { - return appendCommand(commandObjects.expireAt(key, unixTime)); - } - - @Override - public Response expireAt(byte[] key, long unixTime, ExpiryOption expiryOption) { - return appendCommand(commandObjects.expireAt(key, unixTime, expiryOption)); - } - - @Override - public Response pexpireAt(byte[] key, long millisecondsTimestamp) { - return appendCommand(commandObjects.pexpireAt(key, millisecondsTimestamp)); - } - - @Override - public Response pexpireAt(byte[] key, long millisecondsTimestamp, ExpiryOption expiryOption) { - return appendCommand(commandObjects.pexpireAt(key, millisecondsTimestamp, expiryOption)); - } - - @Override - public Response ttl(byte[] key) { - return appendCommand(commandObjects.ttl(key)); - } - - @Override - public Response pttl(byte[] key) { - return appendCommand(commandObjects.pttl(key)); - } - - @Override - public Response touch(byte[] key) { - return appendCommand(commandObjects.touch(key)); - } - - @Override - public Response touch(byte[]... keys) { - return appendCommand(commandObjects.touch(keys)); - } - - @Override - public Response> sort(byte[] key) { - return appendCommand(commandObjects.sort(key)); - } - - @Override - public Response> sort(byte[] key, SortingParams sortingParams) { - return appendCommand(commandObjects.sort(key, sortingParams)); - } - - @Override - public Response> sortReadonly(byte[] key, SortingParams sortingParams) { - return appendCommand(commandObjects.sortReadonly(key, sortingParams)); - } - - @Override - public Response del(byte[] key) { - return appendCommand(commandObjects.del(key)); - } - - @Override - public Response del(byte[]... keys) { - return appendCommand(commandObjects.del(keys)); - } - - @Override - public Response unlink(byte[] key) { - return appendCommand(commandObjects.unlink(key)); - } - - @Override - public Response unlink(byte[]... keys) { - return appendCommand(commandObjects.unlink(keys)); - } - - @Override - public Response copy(byte[] srcKey, byte[] dstKey, boolean replace) { - return appendCommand(commandObjects.copy(srcKey, dstKey, replace)); - } - - @Override - public Response rename(byte[] oldkey, byte[] newkey) { - return appendCommand(commandObjects.rename(oldkey, newkey)); - } - - @Override - public Response renamenx(byte[] oldkey, byte[] newkey) { - return appendCommand(commandObjects.renamenx(oldkey, newkey)); - } - - @Override - public Response sort(byte[] key, SortingParams sortingParams, byte[] dstkey) { - return appendCommand(commandObjects.sort(key, sortingParams, dstkey)); - } - - @Override - public Response sort(byte[] key, byte[] dstkey) { - return appendCommand(commandObjects.sort(key, dstkey)); - } - - @Override - public Response memoryUsage(byte[] key) { - return appendCommand(commandObjects.memoryUsage(key)); - } - - @Override - public Response memoryUsage(byte[] key, int samples) { - return appendCommand(commandObjects.memoryUsage(key, samples)); - } - - @Override - public Response objectRefcount(byte[] key) { - return appendCommand(commandObjects.objectRefcount(key)); - } - - @Override - public Response objectEncoding(byte[] key) { - return appendCommand(commandObjects.objectEncoding(key)); - } - - @Override - public Response objectIdletime(byte[] key) { - return appendCommand(commandObjects.objectIdletime(key)); - } - - @Override - public Response objectFreq(byte[] key) { - return appendCommand(commandObjects.objectFreq(key)); - } - - @Override - public Response migrate(String host, int port, byte[] key, int timeout) { - return appendCommand(commandObjects.migrate(host, port, key, timeout)); - } - - @Override - public Response migrate(String host, int port, int timeout, MigrateParams params, byte[]... keys) { - return appendCommand(commandObjects.migrate(host, port, timeout, params, keys)); - } - - @Override - public Response> keys(byte[] pattern) { - return appendCommand(commandObjects.keys(pattern)); - } - - @Override - public Response> scan(byte[] cursor) { - return appendCommand(commandObjects.scan(cursor)); - } - - @Override - public Response> scan(byte[] cursor, ScanParams params) { - return appendCommand(commandObjects.scan(cursor, params)); - } - - @Override - public Response> scan(byte[] cursor, ScanParams params, byte[] type) { - return appendCommand(commandObjects.scan(cursor, params, type)); - } - - @Override - public Response randomBinaryKey() { - return appendCommand(commandObjects.randomBinaryKey()); - } - - @Override - public Response rpush(byte[] key, byte[]... args) { - return appendCommand(commandObjects.rpush(key, args)); - } - - @Override - public Response lpush(byte[] key, byte[]... args) { - return appendCommand(commandObjects.lpush(key, args)); - } - - @Override - public Response llen(byte[] key) { - return appendCommand(commandObjects.llen(key)); - } - - @Override - public Response> lrange(byte[] key, long start, long stop) { - return appendCommand(commandObjects.lrange(key, start, stop)); - } - - @Override - public Response ltrim(byte[] key, long start, long stop) { - return appendCommand(commandObjects.ltrim(key, start, stop)); - } - - @Override - public Response lindex(byte[] key, long index) { - return appendCommand(commandObjects.lindex(key, index)); - } - - @Override - public Response lset(byte[] key, long index, byte[] value) { - return appendCommand(commandObjects.lset(key, index, value)); - } - - @Override - public Response lrem(byte[] key, long count, byte[] value) { - return appendCommand(commandObjects.lrem(key, count, value)); - } - - @Override - public Response lpop(byte[] key) { - return appendCommand(commandObjects.lpop(key)); - } - - @Override - public Response> lpop(byte[] key, int count) { - return appendCommand(commandObjects.lpop(key, count)); - } - - @Override - public Response lpos(byte[] key, byte[] element) { - return appendCommand(commandObjects.lpos(key, element)); - } - - @Override - public Response lpos(byte[] key, byte[] element, LPosParams params) { - return appendCommand(commandObjects.lpos(key, element, params)); - } - - @Override - public Response> lpos(byte[] key, byte[] element, LPosParams params, long count) { - return appendCommand(commandObjects.lpos(key, element, params, count)); - } - - @Override - public Response rpop(byte[] key) { - return appendCommand(commandObjects.rpop(key)); - } - - @Override - public Response> rpop(byte[] key, int count) { - return appendCommand(commandObjects.rpop(key, count)); - } - - @Override - public Response linsert(byte[] key, ListPosition where, byte[] pivot, byte[] value) { - return appendCommand(commandObjects.linsert(key, where, pivot, value)); - } - - @Override - public Response lpushx(byte[] key, byte[]... args) { - return appendCommand(commandObjects.lpushx(key, args)); - } - - @Override - public Response rpushx(byte[] key, byte[]... args) { - return appendCommand(commandObjects.rpushx(key, args)); - } - - @Override - public Response> blpop(int timeout, byte[]... keys) { - return appendCommand(commandObjects.blpop(timeout, keys)); - } - - @Override - public Response> blpop(double timeout, byte[]... keys) { - return appendCommand(commandObjects.blpop(timeout, keys)); - } - - @Override - public Response> brpop(int timeout, byte[]... keys) { - return appendCommand(commandObjects.brpop(timeout, keys)); - } - - @Override - public Response> brpop(double timeout, byte[]... keys) { - return appendCommand(commandObjects.brpop(timeout, keys)); - } - - @Override - public Response rpoplpush(byte[] srckey, byte[] dstkey) { - return appendCommand(commandObjects.rpoplpush(srckey, dstkey)); - } - - @Override - public Response brpoplpush(byte[] source, byte[] destination, int timeout) { - return appendCommand(commandObjects.brpoplpush(source, destination, timeout)); - } - - @Override - public Response lmove(byte[] srcKey, byte[] dstKey, ListDirection from, ListDirection to) { - return appendCommand(commandObjects.lmove(srcKey, dstKey, from, to)); - } - - @Override - public Response blmove(byte[] srcKey, byte[] dstKey, ListDirection from, ListDirection to, double timeout) { - return appendCommand(commandObjects.blmove(srcKey, dstKey, from, to, timeout)); - } - - @Override - public Response>> lmpop(ListDirection direction, byte[]... keys) { - return appendCommand(commandObjects.lmpop(direction, keys)); - } - - @Override - public Response>> lmpop(ListDirection direction, int count, byte[]... keys) { - return appendCommand(commandObjects.lmpop(direction, count, keys)); - } - - @Override - public Response>> blmpop(long timeout, ListDirection direction, byte[]... keys) { - return appendCommand(commandObjects.blmpop(timeout, direction, keys)); - } - - @Override - public Response>> blmpop(long timeout, ListDirection direction, int count, byte[]... keys) { - return appendCommand(commandObjects.blmpop(timeout, direction, count, keys)); - } - - public Response publish(byte[] channel, byte[] message) { - return appendCommand(commandObjects.publish(channel, message)); - } - - public Response strAlgoLCSStrings(byte[] strA, byte[] strB, StrAlgoLCSParams params) { - return appendCommand(commandObjects.strAlgoLCSStrings(strA, strB, params)); - } - - @Override - public Response waitReplicas(byte[] sampleKey, int replicas, long timeout) { - return appendCommand(commandObjects.waitReplicas(sampleKey, replicas, timeout)); - } - - @Override - public Response eval(byte[] script, byte[] sampleKey) { - return appendCommand(commandObjects.eval(script, sampleKey)); - } - - @Override - public Response evalsha(byte[] sha1, byte[] sampleKey) { - return appendCommand(commandObjects.evalsha(sha1, sampleKey)); - } - - @Override - public Response> scriptExists(byte[] sampleKey, byte[]... sha1s) { - return appendCommand(commandObjects.scriptExists(sampleKey, sha1s)); - } - - @Override - public Response scriptLoad(byte[] script, byte[] sampleKey) { - return appendCommand(commandObjects.scriptLoad(script, sampleKey)); - } - - @Override - public Response scriptFlush(byte[] sampleKey) { - return appendCommand(commandObjects.scriptFlush(sampleKey)); - } - - @Override - public Response scriptFlush(byte[] sampleKey, FlushMode flushMode) { - return appendCommand(commandObjects.scriptFlush(sampleKey, flushMode)); - } - - @Override - public Response scriptKill(byte[] sampleKey) { - return appendCommand(commandObjects.scriptKill(sampleKey)); - } - - @Override - public Response eval(byte[] script) { - return appendCommand(commandObjects.eval(script)); - } - - @Override - public Response eval(byte[] script, int keyCount, byte[]... params) { - return appendCommand(commandObjects.eval(script, keyCount, params)); - } - - @Override - public Response eval(byte[] script, List keys, List args) { - return appendCommand(commandObjects.eval(script, keys, args)); - } - - @Override - public Response evalReadonly(byte[] script, List keys, List args) { - return appendCommand(commandObjects.evalReadonly(script, keys, args)); - } - - @Override - public Response evalsha(byte[] sha1) { - return appendCommand(commandObjects.evalsha(sha1)); - } - - @Override - public Response evalsha(byte[] sha1, int keyCount, byte[]... params) { - return appendCommand(commandObjects.evalsha(sha1, keyCount, params)); - } - - @Override - public Response evalsha(byte[] sha1, List keys, List args) { - return appendCommand(commandObjects.evalsha(sha1, keys, args)); - } - - @Override - public Response evalshaReadonly(byte[] sha1, List keys, List args) { - return appendCommand(commandObjects.evalshaReadonly(sha1, keys, args)); - } - - @Override - public Response sadd(byte[] key, byte[]... members) { - return appendCommand(commandObjects.sadd(key, members)); - } - - @Override - public Response> smembers(byte[] key) { - return appendCommand(commandObjects.smembers(key)); - } - - @Override - public Response srem(byte[] key, byte[]... members) { - return appendCommand(commandObjects.srem(key, members)); - } - - @Override - public Response spop(byte[] key) { - return appendCommand(commandObjects.spop(key)); - } - - @Override - public Response> spop(byte[] key, long count) { - return appendCommand(commandObjects.spop(key, count)); - } - - @Override - public Response scard(byte[] key) { - return appendCommand(commandObjects.scard(key)); - } - - @Override - public Response sismember(byte[] key, byte[] member) { - return appendCommand(commandObjects.sismember(key, member)); - } - - @Override - public Response> smismember(byte[] key, byte[]... members) { - return appendCommand(commandObjects.smismember(key, members)); - } - - @Override - public Response srandmember(byte[] key) { - return appendCommand(commandObjects.srandmember(key)); - } - - @Override - public Response> srandmember(byte[] key, int count) { - return appendCommand(commandObjects.srandmember(key, count)); - } - - @Override - public Response> sscan(byte[] key, byte[] cursor, ScanParams params) { - return appendCommand(commandObjects.sscan(key, cursor, params)); - } - - @Override - public Response> sdiff(byte[]... keys) { - return appendCommand(commandObjects.sdiff(keys)); - } - - @Override - public Response sdiffstore(byte[] dstkey, byte[]... keys) { - return appendCommand(commandObjects.sdiffstore(dstkey, keys)); - } - - @Override - public Response> sinter(byte[]... keys) { - return appendCommand(commandObjects.sinter(keys)); - } - - @Override - public Response sinterstore(byte[] dstkey, byte[]... keys) { - return appendCommand(commandObjects.sinterstore(dstkey, keys)); - } - - @Override - public Response sintercard(byte[]... keys){ - return appendCommand(commandObjects.sintercard(keys)); - } - - @Override - public Response sintercard(int limit, byte[]... keys){ - return appendCommand(commandObjects.sintercard(limit, keys)); - } - - @Override - public Response> sunion(byte[]... keys) { - return appendCommand(commandObjects.sunion(keys)); - } - - @Override - public Response sunionstore(byte[] dstkey, byte[]... keys) { - return appendCommand(commandObjects.sunionstore(dstkey, keys)); - } - - @Override - public Response smove(byte[] srckey, byte[] dstkey, byte[] member) { - return appendCommand(commandObjects.smove(srckey, dstkey, member)); - } - - @Override - public Response zadd(byte[] key, double score, byte[] member) { - return appendCommand(commandObjects.zadd(key, score, member)); - } - - @Override - public Response zadd(byte[] key, double score, byte[] member, ZAddParams params) { - return appendCommand(commandObjects.zadd(key, score, member, params)); - } - - @Override - public Response zadd(byte[] key, Map scoreMembers) { - return appendCommand(commandObjects.zadd(key, scoreMembers)); - } - - @Override - public Response zadd(byte[] key, Map scoreMembers, ZAddParams params) { - return appendCommand(commandObjects.zadd(key, scoreMembers, params)); - } - - @Override - public Response zaddIncr(byte[] key, double score, byte[] member, ZAddParams params) { - return appendCommand(commandObjects.zaddIncr(key, score, member, params)); - } - - @Override - public Response zrem(byte[] key, byte[]... members) { - return appendCommand(commandObjects.zrem(key, members)); - } - - @Override - public Response zincrby(byte[] key, double increment, byte[] member) { - return appendCommand(commandObjects.zincrby(key, increment, member)); - } - - @Override - public Response zincrby(byte[] key, double increment, byte[] member, ZIncrByParams params) { - return appendCommand(commandObjects.zincrby(key, increment, member, params)); - } - - @Override - public Response zrank(byte[] key, byte[] member) { - return appendCommand(commandObjects.zrank(key, member)); - } - - @Override - public Response zrevrank(byte[] key, byte[] member) { - return appendCommand(commandObjects.zrevrank(key, member)); - } - - @Override - public Response> zrange(byte[] key, long start, long stop) { - return appendCommand(commandObjects.zrange(key, start, stop)); - } - - @Override - public Response> zrevrange(byte[] key, long start, long stop) { - return appendCommand(commandObjects.zrevrange(key, start, stop)); - } - - @Override - public Response> zrangeWithScores(byte[] key, long start, long stop) { - return appendCommand(commandObjects.zrangeWithScores(key, start, stop)); - } - - @Override - public Response> zrevrangeWithScores(byte[] key, long start, long stop) { - return appendCommand(commandObjects.zrevrangeWithScores(key, start, stop)); - } - - @Override - public Response> zrange(byte[] key, ZRangeParams zRangeParams) { - return appendCommand(commandObjects.zrange(key, zRangeParams)); - } - - @Override - public Response> zrangeWithScores(byte[] key, ZRangeParams zRangeParams) { - return appendCommand(commandObjects.zrangeWithScores(key, zRangeParams)); - } - - @Override - public Response zrangestore(byte[] dest, byte[] src, ZRangeParams zRangeParams) { - return appendCommand(commandObjects.zrangestore(dest, src, zRangeParams)); - } - - @Override - public Response zrandmember(byte[] key) { - return appendCommand(commandObjects.zrandmember(key)); - } - - @Override - public Response> zrandmember(byte[] key, long count) { - return appendCommand(commandObjects.zrandmember(key, count)); - } - - @Override - public Response> zrandmemberWithScores(byte[] key, long count) { - return appendCommand(commandObjects.zrandmemberWithScores(key, count)); - } - - @Override - public Response zcard(byte[] key) { - return appendCommand(commandObjects.zcard(key)); - } - - @Override - public Response zscore(byte[] key, byte[] member) { - return appendCommand(commandObjects.zscore(key, member)); - } - - @Override - public Response> zmscore(byte[] key, byte[]... members) { - return appendCommand(commandObjects.zmscore(key, members)); - } - - @Override - public Response zpopmax(byte[] key) { - return appendCommand(commandObjects.zpopmax(key)); - } - - @Override - public Response> zpopmax(byte[] key, int count) { - return appendCommand(commandObjects.zpopmax(key, count)); - } - - @Override - public Response zpopmin(byte[] key) { - return appendCommand(commandObjects.zpopmin(key)); - } - - @Override - public Response> zpopmin(byte[] key, int count) { - return appendCommand(commandObjects.zpopmin(key, count)); - } - - @Override - public Response zcount(byte[] key, double min, double max) { - return appendCommand(commandObjects.zcount(key, min, max)); - } - - @Override - public Response zcount(byte[] key, byte[] min, byte[] max) { - return appendCommand(commandObjects.zcount(key, min, max)); - } - - @Override - public Response> zrangeByScore(byte[] key, double min, double max) { - return appendCommand(commandObjects.zrangeByScore(key, min, max)); - } - - @Override - public Response> zrangeByScore(byte[] key, byte[] min, byte[] max) { - return appendCommand(commandObjects.zrangeByScore(key, min, max)); - } - - @Override - public Response> zrevrangeByScore(byte[] key, double max, double min) { - return appendCommand(commandObjects.zrevrangeByScore(key, min, max)); - } - - @Override - public Response> zrangeByScore(byte[] key, double min, double max, int offset, int count) { - return appendCommand(commandObjects.zrangeByScore(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByScore(byte[] key, byte[] max, byte[] min) { - return appendCommand(commandObjects.zrevrangeByScore(key, min, max)); - } - - @Override - public Response> zrangeByScore(byte[] key, byte[] min, byte[] max, int offset, int count) { - return appendCommand(commandObjects.zrangeByScore(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByScore(byte[] key, double max, double min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByScore(key, min, max, offset, count)); - } - - @Override - public Response> zrangeByScoreWithScores(byte[] key, double min, double max) { - return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max)); - } - - @Override - public Response> zrevrangeByScoreWithScores(byte[] key, double max, double min) { - return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min)); - } - - @Override - public Response> zrangeByScoreWithScores(byte[] key, double min, double max, int offset, int count) { - return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByScore(byte[] key, byte[] max, byte[] min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByScore(key, min, max, offset, count)); - } - - @Override - public Response> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max) { - return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max)); - } - - @Override - public Response> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min) { - return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min)); - } - - @Override - public Response> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max, int offset, int count) { - return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByScoreWithScores(byte[] key, double max, double min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min, offset, count)); - } - - @Override - public Response> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min, offset, count)); - } - - @Override - public Response zremrangeByRank(byte[] key, long start, long stop) { - return appendCommand(commandObjects.zremrangeByRank(key, start, stop)); - } - - @Override - public Response zremrangeByScore(byte[] key, double min, double max) { - return appendCommand(commandObjects.zremrangeByScore(key, min, max)); - } - - @Override - public Response zremrangeByScore(byte[] key, byte[] min, byte[] max) { - return appendCommand(commandObjects.zremrangeByScore(key, min, max)); - } - - @Override - public Response zlexcount(byte[] key, byte[] min, byte[] max) { - return appendCommand(commandObjects.zlexcount(key, min, max)); - } - - @Override - public Response> zrangeByLex(byte[] key, byte[] min, byte[] max) { - return appendCommand(commandObjects.zrangeByLex(key, min, max)); - } - - @Override - public Response> zrangeByLex(byte[] key, byte[] min, byte[] max, int offset, int count) { - return appendCommand(commandObjects.zrangeByLex(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByLex(byte[] key, byte[] max, byte[] min) { - return appendCommand(commandObjects.zrevrangeByLex(key, min, max)); - } - - @Override - public Response> zrevrangeByLex(byte[] key, byte[] max, byte[] min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByLex(key, min, max, offset, count)); - } - - @Override - public Response zremrangeByLex(byte[] key, byte[] min, byte[] max) { - return appendCommand(commandObjects.zremrangeByLex(key, min, max)); - } - - @Override - public Response> zscan(byte[] key, byte[] cursor, ScanParams params) { - return appendCommand(commandObjects.zscan(key, cursor, params)); - } - - @Override - public Response> bzpopmax(double timeout, byte[]... keys) { - return appendCommand(commandObjects.bzpopmax(timeout, keys)); - } - - @Override - public Response> bzpopmin(double timeout, byte[]... keys) { - return appendCommand(commandObjects.bzpopmin(timeout, keys)); - } - - @Override - public Response>> zmpop(SortedSetOption option, byte[]... keys) { - return appendCommand(commandObjects.zmpop(option, keys)); - } - - @Override - public Response>> zmpop(SortedSetOption option, int count, byte[]... keys) { - return appendCommand(commandObjects.zmpop(option, count, keys)); - } - - @Override - public Response>> bzmpop(long timeout, SortedSetOption option, byte[]... keys) { - return appendCommand(commandObjects.bzmpop(timeout, option, keys)); - } - - @Override - public Response>> bzmpop(long timeout, SortedSetOption option, int count, byte[]... keys) { - return appendCommand(commandObjects.bzmpop(timeout, option, count, keys)); - } - - @Override - public Response> zdiff(byte[]... keys) { - return appendCommand(commandObjects.zdiff(keys)); - } - - @Override - public Response> zdiffWithScores(byte[]... keys) { - return appendCommand(commandObjects.zdiffWithScores(keys)); - } - - @Override - public Response zdiffStore(byte[] dstkey, byte[]... keys) { - return appendCommand(commandObjects.zdiffStore(dstkey, keys)); - } - - @Override - public Response> zinter(ZParams params, byte[]... keys) { - return appendCommand(commandObjects.zinter(params, keys)); - } - - @Override - public Response> zinterWithScores(ZParams params, byte[]... keys) { - return appendCommand(commandObjects.zinterWithScores(params, keys)); - } - - @Override - public Response zinterstore(byte[] dstkey, byte[]... sets) { - return appendCommand(commandObjects.zinterstore(dstkey, sets)); - } - - @Override - public Response zinterstore(byte[] dstkey, ZParams params, byte[]... sets) { - return appendCommand(commandObjects.zinterstore(dstkey, params, sets)); - } - - @Override - public Response zintercard(byte[]... keys) { - return appendCommand(commandObjects.zintercard(keys)); - } - - @Override - public Response zintercard(long limit, byte[]... keys) { - return appendCommand(commandObjects.zintercard(limit, keys)); - } - - @Override - public Response> zunion(ZParams params, byte[]... keys) { - return appendCommand(commandObjects.zunion(params, keys)); - } - - @Override - public Response> zunionWithScores(ZParams params, byte[]... keys) { - return appendCommand(commandObjects.zunionWithScores(params, keys)); - } - - @Override - public Response zunionstore(byte[] dstkey, byte[]... sets) { - return appendCommand(commandObjects.zunionstore(dstkey, sets)); - } - - @Override - public Response zunionstore(byte[] dstkey, ZParams params, byte[]... sets) { - return appendCommand(commandObjects.zunionstore(dstkey, params, sets)); - } - - @Override - public Response xadd(byte[] key, XAddParams params, Map hash) { - return appendCommand(commandObjects.xadd(key, params, hash)); - } - - @Override - public Response xlen(byte[] key) { - return appendCommand(commandObjects.xlen(key)); - } - - @Override - public Response> xrange(byte[] key, byte[] start, byte[] end) { - return appendCommand(commandObjects.xrange(key, start, end)); - } - - @Override - public Response> xrange(byte[] key, byte[] start, byte[] end, int count) { - return appendCommand(commandObjects.xrange(key, start, end, count)); - } - - @Override - public Response> xrevrange(byte[] key, byte[] end, byte[] start) { - return appendCommand(commandObjects.xrevrange(key, end, start)); - } - - @Override - public Response> xrevrange(byte[] key, byte[] end, byte[] start, int count) { - return appendCommand(commandObjects.xrevrange(key, end, start, count)); - } - - @Override - public Response xack(byte[] key, byte[] group, byte[]... ids) { - return appendCommand(commandObjects.xack(key, group, ids)); - } - - @Override - public Response xgroupCreate(byte[] key, byte[] groupName, byte[] id, boolean makeStream) { - return appendCommand(commandObjects.xgroupCreate(key, groupName, id, makeStream)); - } - - @Override - public Response xgroupSetID(byte[] key, byte[] groupName, byte[] id) { - return appendCommand(commandObjects.xgroupSetID(key, groupName, id)); - } - - @Override - public Response xgroupDestroy(byte[] key, byte[] groupName) { - return appendCommand(commandObjects.xgroupDestroy(key, groupName)); - } - - @Override - public Response xgroupCreateConsumer(byte[] key, byte[] groupName, byte[] consumerName) { - return appendCommand(commandObjects.xgroupCreateConsumer(key, groupName, consumerName)); - } - - @Override - public Response xgroupDelConsumer(byte[] key, byte[] groupName, byte[] consumerName) { - return appendCommand(commandObjects.xgroupDelConsumer(key, groupName, consumerName)); - } - - @Override - public Response xdel(byte[] key, byte[]... ids) { - return appendCommand(commandObjects.xdel(key, ids)); - } - - @Override - public Response xtrim(byte[] key, long maxLen, boolean approximateLength) { - return appendCommand(commandObjects.xtrim(key, maxLen, approximateLength)); - } - - @Override - public Response xtrim(byte[] key, XTrimParams params) { - return appendCommand(commandObjects.xtrim(key, params)); - } - - @Override - public Response xpending(byte[] key, byte[] groupName) { - return appendCommand(commandObjects.xpending(key, groupName)); - } - - @Override - public Response> xpending(byte[] key, byte[] groupName, byte[] start, byte[] end, int count, byte[] consumerName) { - return appendCommand(commandObjects.xpending(key, groupName, start, end, count, consumerName)); - } - - @Override - public Response> xpending(byte[] key, byte[] groupName, XPendingParams params) { - return appendCommand(commandObjects.xpending(key, groupName, params)); - } - - @Override - public Response> xclaim(byte[] key, byte[] group, byte[] consumerName, long minIdleTime, XClaimParams params, byte[]... ids) { - return appendCommand(commandObjects.xclaim(key, group, consumerName, minIdleTime, params, ids)); - } - - @Override - public Response> xclaimJustId(byte[] key, byte[] group, byte[] consumerName, long minIdleTime, XClaimParams params, byte[]... ids) { - return appendCommand(commandObjects.xclaimJustId(key, group, consumerName, minIdleTime, params, ids)); - } - - @Override - public Response> xautoclaim(byte[] key, byte[] groupName, byte[] consumerName, long minIdleTime, byte[] start, XAutoClaimParams params) { - return appendCommand(commandObjects.xautoclaim(key, groupName, consumerName, minIdleTime, start, params)); - } - - @Override - public Response> xautoclaimJustId(byte[] key, byte[] groupName, byte[] consumerName, long minIdleTime, byte[] start, XAutoClaimParams params) { - return appendCommand(commandObjects.xautoclaimJustId(key, groupName, consumerName, minIdleTime, start, params)); - } - - @Override - public Response xinfoStream(byte[] key) { - return appendCommand(commandObjects.xinfoStream(key)); - } - - @Override - public Response xinfoStreamFull(byte[] key) { - return appendCommand(commandObjects.xinfoStreamFull(key)); - } - - @Override - public Response xinfoStreamFull(byte[] key, int count) { - return appendCommand(commandObjects.xinfoStreamFull(key, count)); - } - - @Override - @Deprecated - public Response> xinfoGroup(byte[] key) { - return appendCommand(commandObjects.xinfoGroup(key)); - } - - @Override - public Response> xinfoGroups(byte[] key) { - return appendCommand(commandObjects.xinfoGroups(key)); - } - - @Override - public Response> xinfoConsumers(byte[] key, byte[] group) { - return appendCommand(commandObjects.xinfoConsumers(key, group)); - } - - @Override - public Response> xread(XReadParams xReadParams, Map.Entry... streams) { - return appendCommand(commandObjects.xread(xReadParams, streams)); - } - - @Override - public Response> xreadGroup(byte[] groupName, byte[] consumer, XReadGroupParams xReadGroupParams, Map.Entry... streams) { - return appendCommand(commandObjects.xreadGroup(groupName, consumer, xReadGroupParams, streams)); - } - - @Override - public Response set(byte[] key, byte[] value) { - return appendCommand(commandObjects.set(key, value)); - } - - @Override - public Response set(byte[] key, byte[] value, SetParams params) { - return appendCommand(commandObjects.set(key, value, params)); - } - - @Override - public Response get(byte[] key) { - return appendCommand(commandObjects.get(key)); - } - - @Override - public Response setGet(byte[] key, byte[] value, SetParams params) { - return appendCommand(commandObjects.setGet(key, value, params)); - } - - @Override - public Response getDel(byte[] key) { - return appendCommand(commandObjects.getDel(key)); - } - - @Override - public Response getEx(byte[] key, GetExParams params) { - return appendCommand(commandObjects.getEx(key, params)); - } - - @Override - public Response setbit(byte[] key, long offset, boolean value) { - return appendCommand(commandObjects.setbit(key, offset, value)); - } - - @Override - public Response getbit(byte[] key, long offset) { - return appendCommand(commandObjects.getbit(key, offset)); - } - - @Override - public Response setrange(byte[] key, long offset, byte[] value) { - return appendCommand(commandObjects.setrange(key, offset, value)); - } - - @Override - public Response getrange(byte[] key, long startOffset, long endOffset) { - return appendCommand(commandObjects.getrange(key, startOffset, endOffset)); - } - - @Override - public Response getSet(byte[] key, byte[] value) { - return appendCommand(commandObjects.getSet(key, value)); - } - - @Override - public Response setnx(byte[] key, byte[] value) { - return appendCommand(commandObjects.setnx(key, value)); - } - - @Override - public Response setex(byte[] key, long seconds, byte[] value) { - return appendCommand(commandObjects.setex(key, seconds, value)); - } - - @Override - public Response psetex(byte[] key, long milliseconds, byte[] value) { - return appendCommand(commandObjects.psetex(key, milliseconds, value)); - } - - @Override - public Response> mget(byte[]... keys) { - return appendCommand(commandObjects.mget(keys)); - } - - @Override - public Response mset(byte[]... keysvalues) { - return appendCommand(commandObjects.mset(keysvalues)); - } - - @Override - public Response msetnx(byte[]... keysvalues) { - return appendCommand(commandObjects.msetnx(keysvalues)); - } - - @Override - public Response incr(byte[] key) { - return appendCommand(commandObjects.incr(key)); - } - - @Override - public Response incrBy(byte[] key, long increment) { - return appendCommand(commandObjects.incrBy(key, increment)); - } - - @Override - public Response incrByFloat(byte[] key, double increment) { - return appendCommand(commandObjects.incrByFloat(key, increment)); - } - - @Override - public Response decr(byte[] key) { - return appendCommand(commandObjects.decr(key)); - } - - @Override - public Response decrBy(byte[] key, long decrement) { - return appendCommand(commandObjects.decrBy(key, decrement)); - } - - @Override - public Response append(byte[] key, byte[] value) { - return appendCommand(commandObjects.append(key, value)); - } - - @Override - public Response substr(byte[] key, int start, int end) { - return appendCommand(commandObjects.substr(key, start, end)); - } - - @Override - public Response strlen(byte[] key) { - return appendCommand(commandObjects.strlen(key)); - } - - @Override - public Response bitcount(byte[] key) { - return appendCommand(commandObjects.bitcount(key)); - } - - @Override - public Response bitcount(byte[] key, long start, long end) { - return appendCommand(commandObjects.bitcount(key, start, end)); - } - - @Override - public Response bitcount(byte[] key, long start, long end, BitCountOption option) { - return appendCommand(commandObjects.bitcount(key, start, end, option)); - } - - @Override - public Response bitpos(byte[] key, boolean value) { - return appendCommand(commandObjects.bitpos(key, value)); - } - - @Override - public Response bitpos(byte[] key, boolean value, BitPosParams params) { - return appendCommand(commandObjects.bitpos(key, value, params)); - } - - @Override - public Response> bitfield(byte[] key, byte[]... arguments) { - return appendCommand(commandObjects.bitfield(key, arguments)); - } - - @Override - public Response> bitfieldReadonly(byte[] key, byte[]... arguments) { - return appendCommand(commandObjects.bitfieldReadonly(key, arguments)); - } - - @Override - public Response bitop(BitOP op, byte[] destKey, byte[]... srcKeys) { - return appendCommand(commandObjects.bitop(op, destKey, srcKeys)); - } - - @Override - public Response strAlgoLCSKeys(byte[] keyA, byte[] keyB, StrAlgoLCSParams params) { - return appendCommand(commandObjects.strAlgoLCSKeys(keyA, keyB, params)); - } - - // RediSearch commands - @Override - public Response ftCreate(String indexName, IndexOptions indexOptions, Schema schema) { - return appendCommand(commandObjects.ftCreate(indexName, indexOptions, schema)); - } - - @Override - public Response ftCreate(String indexName, FTCreateParams createParams, Iterable schemaFields) { - return appendCommand(commandObjects.ftCreate(indexName, createParams, schemaFields)); - } - - @Override - public Response ftAlter(String indexName, Schema schema) { - return appendCommand(commandObjects.ftAlter(indexName, schema)); - } - - @Override - public Response ftAlter(String indexName, Iterable schemaFields) { - return appendCommand(commandObjects.ftAlter(indexName, schemaFields)); - } - - @Override - public Response ftSearch(String indexName, String query) { - return appendCommand(commandObjects.ftSearch(indexName, query)); - } - - @Override - public Response ftSearch(String indexName, String query, FTSearchParams searchParams) { - return appendCommand(commandObjects.ftSearch(indexName, query, searchParams)); - } - - @Override - public Response ftSearch(String indexName, Query query) { - return appendCommand(commandObjects.ftSearch(indexName, query)); - } - - @Override - public Response ftSearch(byte[] indexName, Query query) { - return appendCommand(commandObjects.ftSearch(indexName, query)); - } - - @Override - public Response ftExplain(String indexName, Query query) { - return appendCommand(commandObjects.ftExplain(indexName, query)); - } - - @Override - public Response> ftExplainCLI(String indexName, Query query) { - return appendCommand(commandObjects.ftExplainCLI(indexName, query)); - } - - @Override - public Response ftAggregate(String indexName, AggregationBuilder aggr) { - return appendCommand(commandObjects.ftAggregate(indexName, aggr)); - } - - @Override - public Response ftCursorRead(String indexName, long cursorId, int count) { - return appendCommand(commandObjects.ftCursorRead(indexName, cursorId, count)); - } - - @Override - public Response ftCursorDel(String indexName, long cursorId) { - return appendCommand(commandObjects.ftCursorDel(indexName, cursorId)); - } - - @Override - public Response ftDropIndex(String indexName) { - return appendCommand(commandObjects.ftDropIndex(indexName)); - } - - @Override - public Response ftDropIndexDD(String indexName) { - return appendCommand(commandObjects.ftDropIndexDD(indexName)); - } - - @Override - public Response ftSynUpdate(String indexName, String synonymGroupId, String... terms) { - return appendCommand(commandObjects.ftSynUpdate(indexName, synonymGroupId, terms)); - } - - @Override - public Response>> ftSynDump(String indexName) { - return appendCommand(commandObjects.ftSynDump(indexName)); - } - - @Override - public Response ftDictAdd(String dictionary, String... terms) { - return appendCommand(commandObjects.ftDictAdd(dictionary, terms)); - } - - @Override - public Response ftDictDel(String dictionary, String... terms) { - return appendCommand(commandObjects.ftDictDel(dictionary, terms)); - } - - @Override - public Response> ftDictDump(String dictionary) { - return appendCommand(commandObjects.ftDictDump(dictionary)); - } - - @Override - public Response ftDictAddBySampleKey(String indexName, String dictionary, String... terms) { - return appendCommand(commandObjects.ftDictAddBySampleKey(indexName, dictionary, terms)); - } - - @Override - public Response ftDictDelBySampleKey(String indexName, String dictionary, String... terms) { - return appendCommand(commandObjects.ftDictDelBySampleKey(indexName, dictionary, terms)); - } - - @Override - public Response> ftDictDumpBySampleKey(String indexName, String dictionary) { - return appendCommand(commandObjects.ftDictDumpBySampleKey(indexName, dictionary)); - } - - @Override - public Response>> ftSpellCheck(String index, String query) { - return appendCommand(commandObjects.ftSpellCheck(index, query)); - } - - @Override - public Response>> ftSpellCheck(String index, String query, FTSpellCheckParams spellCheckParams) { - return appendCommand(commandObjects.ftSpellCheck(index, query, spellCheckParams)); - } - - @Override - public Response> ftInfo(String indexName) { - return appendCommand(commandObjects.ftInfo(indexName)); - } - - @Override - public Response> ftTagVals(String indexName, String fieldName) { - return appendCommand(commandObjects.ftTagVals(indexName, fieldName)); - } - - @Override - public Response ftAliasAdd(String aliasName, String indexName) { - return appendCommand(commandObjects.ftAliasAdd(aliasName, indexName)); - } - - @Override - public Response ftAliasUpdate(String aliasName, String indexName) { - return appendCommand(commandObjects.ftAliasUpdate(aliasName, indexName)); - } - - @Override - public Response ftAliasDel(String aliasName) { - return appendCommand(commandObjects.ftAliasDel(aliasName)); - } - - @Override - public Response> ftConfigGet(String option) { - return appendCommand(commandObjects.ftConfigGet(option)); - } - - @Override - public Response> ftConfigGet(String indexName, String option) { - return appendCommand(commandObjects.ftConfigGet(indexName, option)); - } - - @Override - public Response ftConfigSet(String option, String value) { - return appendCommand(commandObjects.ftConfigSet(option, value)); - } - - @Override - public Response ftConfigSet(String indexName, String option, String value) { - return appendCommand(commandObjects.ftConfigSet(indexName, option, value)); - } - - @Override - public Response ftSugAdd(String key, String string, double score) { - return appendCommand(commandObjects.ftSugAdd(key, string, score)); - } - - @Override - public Response ftSugAddIncr(String key, String string, double score) { - return appendCommand(commandObjects.ftSugAddIncr(key, string, score)); - } - - @Override - public Response> ftSugGet(String key, String prefix) { - return appendCommand(commandObjects.ftSugGet(key, prefix)); - } - - @Override - public Response> ftSugGet(String key, String prefix, boolean fuzzy, int max) { - return appendCommand(commandObjects.ftSugGet(key, prefix, fuzzy, max)); - } - - @Override - public Response> ftSugGetWithScores(String key, String prefix) { - return appendCommand(commandObjects.ftSugGetWithScores(key, prefix)); - } - - @Override - public Response> ftSugGetWithScores(String key, String prefix, boolean fuzzy, int max) { - return appendCommand(commandObjects.ftSugGetWithScores(key, prefix, fuzzy, max)); - } - - @Override - public Response ftSugDel(String key, String string) { - return appendCommand(commandObjects.ftSugDel(key, string)); - } - - @Override - public Response ftSugLen(String key) { - return appendCommand(commandObjects.ftSugLen(key)); - } - // RediSearch commands - - // RedisJSON commands - @Override - public Response lcs(byte[] keyA, byte[] keyB, LCSParams params) { - return appendCommand(commandObjects.lcs(keyA, keyB, params)); - } - - @Override - public Response jsonSet(String key, Path2 path, Object object) { - return appendCommand(commandObjects.jsonSet(key, path, object)); - } - - @Override - public Response jsonSetWithEscape(String key, Path2 path, Object object) { - return appendCommand(commandObjects.jsonSetWithEscape(key, path, object)); - } - - @Override - public Response jsonSet(String key, Path path, Object object) { - return appendCommand(commandObjects.jsonSet(key, path, object)); - } - - @Override - public Response jsonSet(String key, Path2 path, Object object, JsonSetParams params) { - return appendCommand(commandObjects.jsonSet(key, path, object, params)); - } - - @Override - public Response jsonSetWithEscape(String key, Path2 path, Object object, JsonSetParams params) { - return appendCommand(commandObjects.jsonSetWithEscape(key, path, object, params)); - } - - @Override - public Response jsonSet(String key, Path path, Object object, JsonSetParams params) { - return appendCommand(commandObjects.jsonSet(key, path, object, params)); - } - - @Override - public Response jsonGet(String key) { - return appendCommand(commandObjects.jsonGet(key)); - } - - @Override - public Response jsonGet(String key, Class clazz) { - return appendCommand(commandObjects.jsonGet(key, clazz)); - } - - @Override - public Response jsonGet(String key, Path2... paths) { - return appendCommand(commandObjects.jsonGet(key, paths)); - } - - @Override - public Response jsonGet(String key, Path... paths) { - return appendCommand(commandObjects.jsonGet(key, paths)); - } - - @Override - public Response jsonGet(String key, Class clazz, Path... paths) { - return appendCommand(commandObjects.jsonGet(key, clazz, paths)); - } - - @Override - public Response> jsonMGet(Path2 path, String... keys) { - return appendCommand(commandObjects.jsonMGet(path, keys)); - } - - @Override - public Response> jsonMGet(Path path, Class clazz, String... keys) { - return appendCommand(commandObjects.jsonMGet(path, clazz, keys)); - } - - @Override - public Response jsonDel(String key) { - return appendCommand(commandObjects.jsonDel(key)); - } - - @Override - public Response jsonDel(String key, Path2 path) { - return appendCommand(commandObjects.jsonDel(key, path)); - } - - @Override - public Response jsonDel(String key, Path path) { - return appendCommand(commandObjects.jsonDel(key, path)); - } - - @Override - public Response jsonClear(String key) { - return appendCommand(commandObjects.jsonClear(key)); - } - - @Override - public Response jsonClear(String key, Path2 path) { - return appendCommand(commandObjects.jsonClear(key, path)); - } - - @Override - public Response jsonClear(String key, Path path) { - return appendCommand(commandObjects.jsonClear(key, path)); - } - - @Override - public Response> jsonToggle(String key, Path2 path) { - return appendCommand(commandObjects.jsonToggle(key, path)); - } - - @Override - public Response jsonToggle(String key, Path path) { - return appendCommand(commandObjects.jsonToggle(key, path)); - } - - @Override - public Response> jsonType(String key) { - return appendCommand(commandObjects.jsonType(key)); - } - - @Override - public Response>> jsonType(String key, Path2 path) { - return appendCommand(commandObjects.jsonType(key, path)); - } - - @Override - public Response> jsonType(String key, Path path) { - return appendCommand(commandObjects.jsonType(key, path)); - } - - @Override - public Response jsonStrAppend(String key, Object string) { - return appendCommand(commandObjects.jsonStrAppend(key, string)); - } - - @Override - public Response> jsonStrAppend(String key, Path2 path, Object string) { - return appendCommand(commandObjects.jsonStrAppend(key, path, string)); - } - - @Override - public Response jsonStrAppend(String key, Path path, Object string) { - return appendCommand(commandObjects.jsonStrAppend(key, path, string)); - } - - @Override - public Response jsonStrLen(String key) { - return appendCommand(commandObjects.jsonStrLen(key)); - } - - @Override - public Response> jsonStrLen(String key, Path2 path) { - return appendCommand(commandObjects.jsonStrLen(key, path)); - } - - @Override - public Response jsonStrLen(String key, Path path) { - return appendCommand(commandObjects.jsonStrLen(key, path)); - } - - @Override - public Response jsonNumIncrBy(String key, Path2 path, double value) { - return appendCommand(commandObjects.jsonNumIncrBy(key, path, value)); - } - - @Override - public Response jsonNumIncrBy(String key, Path path, double value) { - return appendCommand(commandObjects.jsonNumIncrBy(key, path, value)); - } - - @Override - public Response> jsonArrAppend(String key, Path2 path, Object... objects) { - return appendCommand(commandObjects.jsonArrAppend(key, path, objects)); - } - - @Override - public Response> jsonArrAppendWithEscape(String key, Path2 path, Object... objects) { - return appendCommand(commandObjects.jsonArrAppendWithEscape(key, path, objects)); - } - - @Override - public Response jsonArrAppend(String key, Path path, Object... objects) { - return appendCommand(commandObjects.jsonArrAppend(key, path, objects)); - } - - @Override - public Response> jsonArrIndex(String key, Path2 path, Object scalar) { - return appendCommand(commandObjects.jsonArrIndex(key, path, scalar)); - } - - @Override - public Response> jsonArrIndexWithEscape(String key, Path2 path, Object scalar) { - return appendCommand(commandObjects.jsonArrIndexWithEscape(key, path, scalar)); - } - - @Override - public Response jsonArrIndex(String key, Path path, Object scalar) { - return appendCommand(commandObjects.jsonArrIndex(key, path, scalar)); - } - - @Override - public Response> jsonArrInsert(String key, Path2 path, int index, Object... objects) { - return appendCommand(commandObjects.jsonArrInsert(key, path, index, objects)); - } - - @Override - public Response> jsonArrInsertWithEscape(String key, Path2 path, int index, Object... objects) { - return appendCommand(commandObjects.jsonArrInsertWithEscape(key, path, index, objects)); - } - - @Override - public Response jsonArrInsert(String key, Path path, int index, Object... pojos) { - return appendCommand(commandObjects.jsonArrInsert(key, path, index, pojos)); - } - - @Override - public Response jsonArrPop(String key) { - return appendCommand(commandObjects.jsonArrPop(key)); - } - - @Override - public Response jsonArrLen(String key, Path path) { - return appendCommand(commandObjects.jsonArrLen(key, path)); - } - - @Override - public Response> jsonArrTrim(String key, Path2 path, int start, int stop) { - return appendCommand(commandObjects.jsonArrTrim(key, path, start, stop)); - } - - @Override - public Response jsonArrTrim(String key, Path path, int start, int stop) { - return appendCommand(commandObjects.jsonArrTrim(key, path, start, stop)); - } - - @Override - public Response jsonArrPop(String key, Class clazz, Path path) { - return appendCommand(commandObjects.jsonArrPop(key, clazz, path)); - } - - @Override - public Response> jsonArrPop(String key, Path2 path, int index) { - return appendCommand(commandObjects.jsonArrPop(key, path, index)); - } - - @Override - public Response jsonArrPop(String key, Path path, int index) { - return appendCommand(commandObjects.jsonArrPop(key, path, index)); - } - - @Override - public Response jsonArrPop(String key, Class clazz, Path path, int index) { - return appendCommand(commandObjects.jsonArrPop(key, clazz, path, index)); - } - - @Override - public Response jsonArrLen(String key) { - return appendCommand(commandObjects.jsonArrLen(key)); - } - - @Override - public Response> jsonArrLen(String key, Path2 path) { - return appendCommand(commandObjects.jsonArrLen(key, path)); - } - - @Override - public Response jsonArrPop(String key, Class clazz) { - return appendCommand(commandObjects.jsonArrPop(key, clazz)); - } - - @Override - public Response> jsonArrPop(String key, Path2 path) { - return appendCommand(commandObjects.jsonArrPop(key, path)); - } - - @Override - public Response jsonArrPop(String key, Path path) { - return appendCommand(commandObjects.jsonArrPop(key, path)); - } - // RedisJSON commands - - // RedisTimeSeries commands - @Override - public Response tsCreate(String key) { - return appendCommand(commandObjects.tsCreate(key)); - } - - @Override - public Response tsCreate(String key, TSCreateParams createParams) { - return appendCommand(commandObjects.tsCreate(key, createParams)); - } - - @Override - public Response tsDel(String key, long fromTimestamp, long toTimestamp) { - return appendCommand(commandObjects.tsDel(key, fromTimestamp, toTimestamp)); - } - - @Override - public Response tsAlter(String key, TSAlterParams alterParams) { - return appendCommand(commandObjects.tsAlter(key, alterParams)); - } - - @Override - public Response tsAdd(String key, double value) { - return appendCommand(commandObjects.tsAdd(key, value)); - } - - @Override - public Response tsAdd(String key, long timestamp, double value) { - return appendCommand(commandObjects.tsAdd(key, timestamp, value)); - } - - @Override - public Response tsAdd(String key, long timestamp, double value, TSCreateParams createParams) { - return appendCommand(commandObjects.tsAdd(key, timestamp, value, createParams)); - } - - @Override - public Response> tsMAdd(Map.Entry... entries) { - return appendCommand(commandObjects.tsMAdd(entries)); - } - - @Override - public Response tsIncrBy(String key, double value) { - return appendCommand(commandObjects.tsIncrBy(key, value)); - } - - @Override - public Response tsIncrBy(String key, double value, long timestamp) { - return appendCommand(commandObjects.tsIncrBy(key, value, timestamp)); - } - - @Override - public Response tsDecrBy(String key, double value) { - return appendCommand(commandObjects.tsDecrBy(key, value)); - } - - @Override - public Response tsDecrBy(String key, double value, long timestamp) { - return appendCommand(commandObjects.tsDecrBy(key, value, timestamp)); - } - - @Override - public Response> tsRange(String key, long fromTimestamp, long toTimestamp) { - return appendCommand(commandObjects.tsRange(key, fromTimestamp, toTimestamp)); - } - - @Override - public Response> tsRange(String key, TSRangeParams rangeParams) { - return appendCommand(commandObjects.tsRange(key, rangeParams)); - } - - @Override - public Response> tsRevRange(String key, long fromTimestamp, long toTimestamp) { - return appendCommand(commandObjects.tsRevRange(key, fromTimestamp, toTimestamp)); - } - - @Override - public Response> tsRevRange(String key, TSRangeParams rangeParams) { - return appendCommand(commandObjects.tsRevRange(key, rangeParams)); - } - - @Override - public Response> tsMRange(long fromTimestamp, long toTimestamp, String... filters) { - return appendCommand(commandObjects.tsMRange(fromTimestamp, toTimestamp, filters)); - } - - @Override - public Response> tsMRange(TSMRangeParams multiRangeParams) { - return appendCommand(commandObjects.tsMRange(multiRangeParams)); - } - - @Override - public Response> tsMRevRange(long fromTimestamp, long toTimestamp, String... filters) { - return appendCommand(commandObjects.tsMRevRange(fromTimestamp, toTimestamp, filters)); - } - - @Override - public Response> tsMRevRange(TSMRangeParams multiRangeParams) { - return appendCommand(commandObjects.tsMRevRange(multiRangeParams)); - } - - @Override - public Response tsGet(String key) { - return appendCommand(commandObjects.tsGet(key)); - } - - @Override - public Response tsGet(String key, TSGetParams getParams) { - return appendCommand(commandObjects.tsGet(key, getParams)); - } - - @Override - public Response>> tsMGet(TSMGetParams multiGetParams, String... filters) { - return appendCommand(commandObjects.tsMGet(multiGetParams, filters)); - } - - @Override - public Response tsCreateRule(String sourceKey, String destKey, AggregationType aggregationType, long timeBucket) { - return appendCommand(commandObjects.tsCreateRule(sourceKey, destKey, aggregationType, timeBucket)); - } - - @Override - public Response tsCreateRule(String sourceKey, String destKey, AggregationType aggregationType, long bucketDuration, long alignTimestamp) { - return appendCommand(commandObjects.tsCreateRule(sourceKey, destKey, aggregationType, bucketDuration, alignTimestamp)); - } - - @Override - public Response tsDeleteRule(String sourceKey, String destKey) { - return appendCommand(commandObjects.tsDeleteRule(sourceKey, destKey)); - } - - @Override - public Response> tsQueryIndex(String... filters) { - return appendCommand(commandObjects.tsQueryIndex(filters)); - } - // RedisTimeSeries commands - - // RedisBloom commands - @Override - public Response bfReserve(String key, double errorRate, long capacity) { - return appendCommand(commandObjects.bfReserve(key, errorRate, capacity)); - } - - @Override - public Response bfReserve(String key, double errorRate, long capacity, BFReserveParams reserveParams) { - return appendCommand(commandObjects.bfReserve(key, errorRate, capacity, reserveParams)); - } - - @Override - public Response bfAdd(String key, String item) { - return appendCommand(commandObjects.bfAdd(key, item)); - } - - @Override - public Response> bfMAdd(String key, String... items) { - return appendCommand(commandObjects.bfMAdd(key, items)); - } - - @Override - public Response> bfInsert(String key, String... items) { - return appendCommand(commandObjects.bfInsert(key, items)); - } - - @Override - public Response> bfInsert(String key, BFInsertParams insertParams, String... items) { - return appendCommand(commandObjects.bfInsert(key, insertParams, items)); - } - - @Override - public Response bfExists(String key, String item) { - return appendCommand(commandObjects.bfExists(key, item)); - } - - @Override - public Response> bfMExists(String key, String... items) { - return appendCommand(commandObjects.bfMExists(key, items)); - } - - @Override - public Response> bfScanDump(String key, long iterator) { - return appendCommand(commandObjects.bfScanDump(key, iterator)); - } - - @Override - public Response bfLoadChunk(String key, long iterator, byte[] data) { - return appendCommand(commandObjects.bfLoadChunk(key, iterator, data)); - } - - @Override - public Response bfCard(String key) { - return appendCommand(commandObjects.bfCard(key)); - } - - @Override - public Response> bfInfo(String key) { - return appendCommand(commandObjects.bfInfo(key)); - } - - @Override - public Response cfReserve(String key, long capacity) { - return appendCommand(commandObjects.cfReserve(key, capacity)); - } - - @Override - public Response cfReserve(String key, long capacity, CFReserveParams reserveParams) { - return appendCommand(commandObjects.cfReserve(key, capacity, reserveParams)); - } - - @Override - public Response cfAdd(String key, String item) { - return appendCommand(commandObjects.cfAdd(key, item)); - } - - @Override - public Response cfAddNx(String key, String item) { - return appendCommand(commandObjects.cfAddNx(key, item)); - } - - @Override - public Response> cfInsert(String key, String... items) { - return appendCommand(commandObjects.cfInsert(key, items)); - } - - @Override - public Response> cfInsert(String key, CFInsertParams insertParams, String... items) { - return appendCommand(commandObjects.cfInsert(key, insertParams, items)); - } - - @Override - public Response> cfInsertNx(String key, String... items) { - return appendCommand(commandObjects.cfInsertNx(key, items)); - } - - @Override - public Response> cfInsertNx(String key, CFInsertParams insertParams, String... items) { - return appendCommand(commandObjects.cfInsertNx(key, insertParams, items)); - } - - @Override - public Response cfExists(String key, String item) { - return appendCommand(commandObjects.cfExists(key, item)); - } - - @Override - public Response cfDel(String key, String item) { - return appendCommand(commandObjects.cfDel(key, item)); - } - - @Override - public Response cfCount(String key, String item) { - return appendCommand(commandObjects.cfCount(key, item)); - } - - @Override - public Response> cfScanDump(String key, long iterator) { - return appendCommand(commandObjects.cfScanDump(key, iterator)); - } - - @Override - public Response cfLoadChunk(String key, long iterator, byte[] data) { - return appendCommand(commandObjects.cfLoadChunk(key, iterator, data)); - } - - @Override - public Response> cfInfo(String key) { - return appendCommand(commandObjects.cfInfo(key)); - } - - @Override - public Response cmsInitByDim(String key, long width, long depth) { - return appendCommand(commandObjects.cmsInitByDim(key, width, depth)); - } - - @Override - public Response cmsInitByProb(String key, double error, double probability) { - return appendCommand(commandObjects.cmsInitByProb(key, error, probability)); - } - - @Override - public Response> cmsIncrBy(String key, Map itemIncrements) { - return appendCommand(commandObjects.cmsIncrBy(key, itemIncrements)); - } - - @Override - public Response> cmsQuery(String key, String... items) { - return appendCommand(commandObjects.cmsQuery(key, items)); - } - - @Override - public Response cmsMerge(String destKey, String... keys) { - return appendCommand(commandObjects.cmsMerge(destKey, keys)); - } - - @Override - public Response cmsMerge(String destKey, Map keysAndWeights) { - return appendCommand(commandObjects.cmsMerge(destKey, keysAndWeights)); - } - - @Override - public Response> cmsInfo(String key) { - return appendCommand(commandObjects.cmsInfo(key)); - } - - @Override - public Response topkReserve(String key, long topk) { - return appendCommand(commandObjects.topkReserve(key, topk)); - } - - @Override - public Response topkReserve(String key, long topk, long width, long depth, double decay) { - return appendCommand(commandObjects.topkReserve(key, topk, width, depth, decay)); - } - - @Override - public Response> topkAdd(String key, String... items) { - return appendCommand(commandObjects.topkAdd(key, items)); - } - - @Override - public Response> topkIncrBy(String key, Map itemIncrements) { - return appendCommand(commandObjects.topkIncrBy(key, itemIncrements)); - } - - @Override - public Response> topkQuery(String key, String... items) { - return appendCommand(commandObjects.topkQuery(key, items)); - } - - @Override - public Response> topkCount(String key, String... items) { - return appendCommand(commandObjects.topkCount(key, items)); - } - - @Override - public Response> topkList(String key) { - return appendCommand(commandObjects.topkList(key)); - } - - @Override - public Response> topkInfo(String key) { - return appendCommand(commandObjects.topkInfo(key)); - } - - @Override - public Response tdigestCreate(String key) { - return appendCommand(commandObjects.tdigestCreate(key)); - } - - @Override - public Response tdigestCreate(String key, int compression) { - return appendCommand(commandObjects.tdigestCreate(key, compression)); - } - - @Override - public Response tdigestReset(String key) { - return appendCommand(commandObjects.tdigestReset(key)); - } - - @Override - public Response tdigestMerge(String destinationKey, String... sourceKeys) { - return appendCommand(commandObjects.tdigestMerge(destinationKey, sourceKeys)); - } - - @Override - public Response tdigestMerge(TDigestMergeParams mergeParams, String destinationKey, String... sourceKeys) { - return appendCommand(commandObjects.tdigestMerge(mergeParams, destinationKey, sourceKeys)); - } - - @Override - public Response> tdigestInfo(String key) { - return appendCommand(commandObjects.tdigestInfo(key)); - } - - @Override - public Response tdigestAdd(String key, double... values) { - return appendCommand(commandObjects.tdigestAdd(key, values)); - } - - @Override - public Response> tdigestCDF(String key, double... values) { - return appendCommand(commandObjects.tdigestCDF(key, values)); - } - - @Override - public Response> tdigestQuantile(String key, double... quantiles) { - return appendCommand(commandObjects.tdigestQuantile(key, quantiles)); - } - - @Override - public Response tdigestMin(String key) { - return appendCommand(commandObjects.tdigestMin(key)); - } - - @Override - public Response tdigestMax(String key) { - return appendCommand(commandObjects.tdigestMax(key)); - } - - @Override - public Response tdigestTrimmedMean(String key, double lowCutQuantile, double highCutQuantile) { - return appendCommand(commandObjects.tdigestTrimmedMean(key, lowCutQuantile, highCutQuantile)); - } - - @Override - public Response> tdigestRank(String key, double... values) { - return appendCommand(commandObjects.tdigestRank(key, values)); - } - - @Override - public Response> tdigestRevRank(String key, double... values) { - return appendCommand(commandObjects.tdigestRevRank(key, values)); - } - - @Override - public Response> tdigestByRank(String key, long... ranks) { - return appendCommand(commandObjects.tdigestByRank(key, ranks)); - } - - @Override - public Response> tdigestByRevRank(String key, long... ranks) { - return appendCommand(commandObjects.tdigestByRevRank(key, ranks)); - } - // RedisBloom commands - - // RedisGraph commands - @Override - public Response graphQuery(String name, String query) { - return appendCommand(graphCommandObjects.graphQuery(name, query)); - } - - @Override - public Response graphReadonlyQuery(String name, String query) { - return appendCommand(graphCommandObjects.graphReadonlyQuery(name, query)); - } - - @Override - public Response graphQuery(String name, String query, long timeout) { - return appendCommand(graphCommandObjects.graphQuery(name, query, timeout)); - } - - @Override - public Response graphReadonlyQuery(String name, String query, long timeout) { - return appendCommand(graphCommandObjects.graphReadonlyQuery(name, query, timeout)); - } - - @Override - public Response graphQuery(String name, String query, Map params) { - return appendCommand(graphCommandObjects.graphQuery(name, query, params)); - } - - @Override - public Response graphReadonlyQuery(String name, String query, Map params) { - return appendCommand(graphCommandObjects.graphReadonlyQuery(name, query, params)); - } - - @Override - public Response graphQuery(String name, String query, Map params, long timeout) { - return appendCommand(graphCommandObjects.graphQuery(name, query, params, timeout)); - } - - @Override - public Response graphReadonlyQuery(String name, String query, Map params, long timeout) { - return appendCommand(graphCommandObjects.graphReadonlyQuery(name, query, params, timeout)); - } - - @Override - public Response graphDelete(String name) { - return appendCommand(graphCommandObjects.graphDelete(name)); - } - - @Override - public Response> graphProfile(String graphName, String query) { - return appendCommand(commandObjects.graphProfile(graphName, query)); - } - // RedisGraph commands - + @Deprecated public Response waitReplicas(int replicas, long timeout) { return appendCommand(commandObjects.waitReplicas(replicas, timeout)); } diff --git a/src/main/java/redis/clients/jedis/Pipeline.java b/src/main/java/redis/clients/jedis/Pipeline.java index df93db1314..36fab65602 100644 --- a/src/main/java/redis/clients/jedis/Pipeline.java +++ b/src/main/java/redis/clients/jedis/Pipeline.java @@ -2,40 +2,22 @@ import java.io.Closeable; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; -import java.util.Map; -import java.util.Set; -import org.json.JSONArray; +import java.util.Queue; -import redis.clients.jedis.args.*; -import redis.clients.jedis.bloom.*; import redis.clients.jedis.commands.DatabasePipelineCommands; -import redis.clients.jedis.commands.PipelineBinaryCommands; -import redis.clients.jedis.commands.PipelineCommands; -import redis.clients.jedis.commands.ProtocolCommand; -import redis.clients.jedis.commands.RedisModulePipelineCommands; import redis.clients.jedis.exceptions.JedisDataException; import redis.clients.jedis.graph.GraphCommandObjects; -import redis.clients.jedis.graph.ResultSet; -import redis.clients.jedis.json.JsonSetParams; -import redis.clients.jedis.json.Path; -import redis.clients.jedis.json.Path2; import redis.clients.jedis.params.*; -import redis.clients.jedis.resps.*; -import redis.clients.jedis.search.*; -import redis.clients.jedis.search.aggr.AggregationBuilder; -import redis.clients.jedis.search.aggr.AggregationResult; -import redis.clients.jedis.search.schemafields.SchemaField; -import redis.clients.jedis.timeseries.*; import redis.clients.jedis.util.KeyValue; -public class Pipeline extends Queable implements PipelineCommands, PipelineBinaryCommands, - DatabasePipelineCommands, RedisModulePipelineCommands, Closeable { +public class Pipeline extends PipelineBase implements DatabasePipelineCommands, Closeable { + private final Queue> pipelinedResponses = new LinkedList<>(); protected final Connection connection; private final boolean closeConnection; - private final CommandObjects commandObjects; - private final GraphCommandObjects graphCommandObjects; + //private final CommandObjects commandObjects; public Pipeline(Jedis jedis) { this(jedis.getConnection(), false); @@ -46,15 +28,20 @@ public Pipeline(Connection connection) { } public Pipeline(Connection connection, boolean closeConnection) { + super(new CommandObjects()); this.connection = connection; this.closeConnection = closeConnection; - this.commandObjects = new CommandObjects(); - this.graphCommandObjects = new GraphCommandObjects(this.connection); + RedisProtocol proto = this.connection.getRedisProtocol(); + if (proto != null) this.commandObjects.setProtocol(proto); + setGraphCommands(new GraphCommandObjects(this.connection)); } + @Override public final Response appendCommand(CommandObject commandObject) { connection.sendCommand(commandObject.getArguments()); - return enqueResponse(commandObject.getBuilder()); + Response response = new Response<>(commandObject.getBuilder()); + pipelinedResponses.add(response); + return response; } @Override @@ -71,11 +58,12 @@ public void close() { * get return values from pipelined commands, capture the different Response<?> of the * commands you execute. */ + @Override public void sync() { if (!hasPipelinedResponse()) return; - List unformatted = connection.getMany(getPipelinedResponseLength()); - for (Object o : unformatted) { - generateResponse(o); + List unformatted = connection.getMany(pipelinedResponses.size()); + for (Object rawReply : unformatted) { + pipelinedResponses.poll().set(rawReply); } } @@ -87,11 +75,13 @@ public void sync() { */ public List syncAndReturnAll() { if (hasPipelinedResponse()) { - List unformatted = connection.getMany(getPipelinedResponseLength()); + List unformatted = connection.getMany(pipelinedResponses.size()); List formatted = new ArrayList<>(); - for (Object o : unformatted) { + for (Object rawReply : unformatted) { try { - formatted.add(generateResponse(o).get()); + Response response = pipelinedResponses.poll(); + response.set(rawReply); + formatted.add(response.get()); } catch (JedisDataException e) { formatted.add(e); } @@ -103,4262 +93,76 @@ public List syncAndReturnAll() { } public final boolean hasPipelinedResponse() { - return getPipelinedResponseLength() > 0; - } - - @Override - public Response exists(String key) { - return appendCommand(commandObjects.exists(key)); - } - - @Override - public Response exists(String... keys) { - return appendCommand(commandObjects.exists(keys)); - } - - @Override - public Response persist(String key) { - return appendCommand(commandObjects.persist(key)); - } - - @Override - public Response type(String key) { - return appendCommand(commandObjects.type(key)); - } - - @Override - public Response dump(String key) { - return appendCommand(commandObjects.dump(key)); - } - - @Override - public Response restore(String key, long ttl, byte[] serializedValue) { - return appendCommand(commandObjects.restore(key, ttl, serializedValue)); - } - - @Override - public Response restore(String key, long ttl, byte[] serializedValue, RestoreParams params) { - return appendCommand(commandObjects.restore(key, ttl, serializedValue, params)); - } - - @Override - public Response expire(String key, long seconds) { - return appendCommand(commandObjects.expire(key, seconds)); - } - - @Override - public Response expire(String key, long seconds, ExpiryOption expiryOption) { - return appendCommand(commandObjects.expire(key, seconds, expiryOption)); - } - - @Override - public Response pexpire(String key, long milliseconds) { - return appendCommand(commandObjects.pexpire(key, milliseconds)); - } - - @Override - public Response pexpire(String key, long milliseconds, ExpiryOption expiryOption) { - return appendCommand(commandObjects.pexpire(key, milliseconds, expiryOption)); - } - - @Override - public Response expireTime(String key) { - return appendCommand(commandObjects.expireTime(key)); - } - - @Override - public Response pexpireTime(String key) { - return appendCommand(commandObjects.pexpireTime(key)); - } - - @Override - public Response expireAt(String key, long unixTime) { - return appendCommand(commandObjects.expireAt(key, unixTime)); - } - - @Override - public Response expireAt(String key, long unixTime, ExpiryOption expiryOption) { - return appendCommand(commandObjects.expireAt(key, unixTime, expiryOption)); - } - - @Override - public Response pexpireAt(String key, long millisecondsTimestamp) { - return appendCommand(commandObjects.pexpireAt(key, millisecondsTimestamp)); - } - - @Override - public Response pexpireAt(String key, long millisecondsTimestamp, ExpiryOption expiryOption) { - return appendCommand(commandObjects.pexpireAt(key, millisecondsTimestamp, expiryOption)); - } - - @Override - public Response ttl(String key) { - return appendCommand(commandObjects.ttl(key)); - } - - @Override - public Response pttl(String key) { - return appendCommand(commandObjects.pttl(key)); - } - - @Override - public Response touch(String key) { - return appendCommand(commandObjects.touch(key)); - } - - @Override - public Response touch(String... keys) { - return appendCommand(commandObjects.touch(keys)); - } - - @Override - public Response> sort(String key) { - return appendCommand(commandObjects.sort(key)); - } - - @Override - public Response sort(String key, String dstKey) { - return appendCommand(commandObjects.sort(key, dstKey)); - } - - @Override - public Response> sort(String key, SortingParams sortingParams) { - return appendCommand(commandObjects.sort(key, sortingParams)); - } - - @Override - public Response sort(String key, SortingParams sortingParams, String dstKey) { - return appendCommand(commandObjects.sort(key, sortingParams, dstKey)); - } - - @Override - public Response> sortReadonly(String key, SortingParams sortingParams) { - return appendCommand(commandObjects.sortReadonly(key, sortingParams)); - } - - @Override - public Response del(String key) { - return appendCommand(commandObjects.del(key)); - } - - @Override - public Response del(String... keys) { - return appendCommand(commandObjects.del(keys)); - } - - @Override - public Response unlink(String key) { - return appendCommand(commandObjects.unlink(key)); - } - - @Override - public Response unlink(String... keys) { - return appendCommand(commandObjects.unlink(keys)); - } - - @Override - public Response copy(String srcKey, String dstKey, boolean replace) { - return appendCommand(commandObjects.copy(srcKey, dstKey, replace)); - } - - @Override - public Response rename(String oldkey, String newkey) { - return appendCommand(commandObjects.rename(oldkey, newkey)); - } - - @Override - public Response renamenx(String oldkey, String newkey) { - return appendCommand(commandObjects.renamenx(oldkey, newkey)); - } - - @Override - public Response memoryUsage(String key) { - return appendCommand(commandObjects.memoryUsage(key)); - } - - @Override - public Response memoryUsage(String key, int samples) { - return appendCommand(commandObjects.memoryUsage(key, samples)); - } - - @Override - public Response objectRefcount(String key) { - return appendCommand(commandObjects.objectRefcount(key)); - } - - @Override - public Response objectEncoding(String key) { - return appendCommand(commandObjects.objectEncoding(key)); - } - - @Override - public Response objectIdletime(String key) { - return appendCommand(commandObjects.objectIdletime(key)); - } - - @Override - public Response objectFreq(String key) { - return appendCommand(commandObjects.objectFreq(key)); - } - - @Override - public Response migrate(String host, int port, String key, int timeout) { - return appendCommand(commandObjects.migrate(host, port, key, timeout)); - } - - @Override - public Response migrate(String host, int port, int timeout, MigrateParams params, String... keys) { - return appendCommand(commandObjects.migrate(host, port, timeout, params, keys)); - } - - @Override - public Response> keys(String pattern) { - return appendCommand(commandObjects.keys(pattern)); + return pipelinedResponses.size() > 0; } - @Override - public Response> scan(String cursor) { - return appendCommand(commandObjects.scan(cursor)); - } - - @Override - public Response> scan(String cursor, ScanParams params) { - return appendCommand(commandObjects.scan(cursor, params)); - } - - @Override - public Response> scan(String cursor, ScanParams params, String type) { - return appendCommand(commandObjects.scan(cursor, params, type)); - } - - @Override - public Response randomKey() { - return appendCommand(commandObjects.randomKey()); - } - - @Override - public Response get(String key) { - return appendCommand(commandObjects.get(key)); - } - - @Override - public Response setGet(String key, String value, SetParams params) { - return appendCommand(commandObjects.setGet(key, value, params)); - } - - @Override - public Response getDel(String key) { - return appendCommand(commandObjects.getDel(key)); - } - - @Override - public Response getEx(String key, GetExParams params) { - return appendCommand(commandObjects.getEx(key, params)); - } - - @Override - public Response setbit(String key, long offset, boolean value) { - return appendCommand(commandObjects.setbit(key, offset, value)); - } - - @Override - public Response getbit(String key, long offset) { - return appendCommand(commandObjects.getbit(key, offset)); - } - - @Override - public Response setrange(String key, long offset, String value) { - return appendCommand(commandObjects.setrange(key, offset, value)); - } - - @Override - public Response getrange(String key, long startOffset, long endOffset) { - return appendCommand(commandObjects.getrange(key, startOffset, endOffset)); - } - - @Override - public Response getSet(String key, String value) { - return appendCommand(commandObjects.getSet(key, value)); - } - - @Override - public Response setnx(String key, String value) { - return appendCommand(commandObjects.setnx(key, value)); - } - - @Override - public Response setex(String key, long seconds, String value) { - return appendCommand(commandObjects.setex(key, seconds, value)); - } - - @Override - public Response psetex(String key, long milliseconds, String value) { - return appendCommand(commandObjects.psetex(key, milliseconds, value)); - } - - @Override - public Response> mget(String... keys) { - return appendCommand(commandObjects.mget(keys)); - } - - @Override - public Response mset(String... keysvalues) { - return appendCommand(commandObjects.mset(keysvalues)); - } - - @Override - public Response msetnx(String... keysvalues) { - return appendCommand(commandObjects.msetnx(keysvalues)); - } - - @Override - public Response incr(String key) { - return appendCommand(commandObjects.incr(key)); - } - - @Override - public Response incrBy(String key, long increment) { - return appendCommand(commandObjects.incrBy(key, increment)); - } - - @Override - public Response incrByFloat(String key, double increment) { - return appendCommand(commandObjects.incrByFloat(key, increment)); - } - - @Override - public Response decr(String key) { - return appendCommand(commandObjects.decr(key)); - } - - @Override - public Response decrBy(String key, long decrement) { - return appendCommand(commandObjects.decrBy(key, decrement)); - } - - @Override - public Response append(String key, String value) { - return appendCommand(commandObjects.append(key, value)); - } - - @Override - public Response substr(String key, int start, int end) { - return appendCommand(commandObjects.substr(key, start, end)); - } - - @Override - public Response strlen(String key) { - return appendCommand(commandObjects.strlen(key)); - } - - @Override - public Response bitcount(String key) { - return appendCommand(commandObjects.bitcount(key)); - } - - @Override - public Response bitcount(String key, long start, long end) { - return appendCommand(commandObjects.bitcount(key, start, end)); - } - - @Override - public Response bitcount(String key, long start, long end, BitCountOption option) { - return appendCommand(commandObjects.bitcount(key, start, end, option)); - } - - @Override - public Response bitpos(String key, boolean value) { - return appendCommand(commandObjects.bitpos(key, value)); - } - - @Override - public Response bitpos(String key, boolean value, BitPosParams params) { - return appendCommand(commandObjects.bitpos(key, value, params)); - } - - @Override - public Response> bitfield(String key, String... arguments) { - return appendCommand(commandObjects.bitfield(key, arguments)); + public Response waitReplicas(int replicas, long timeout) { + return appendCommand(commandObjects.waitReplicas(replicas, timeout)); } - @Override - public Response> bitfieldReadonly(String key, String... arguments) { - return appendCommand(commandObjects.bitfieldReadonly(key, arguments)); + public Response> waitAOF(long numLocal, long numReplicas, long timeout) { + return appendCommand(commandObjects.waitAOF(numLocal, numReplicas, timeout)); } - @Override - public Response bitop(BitOP op, String destKey, String... srcKeys) { - return appendCommand(commandObjects.bitop(op, destKey, srcKeys)); + public Response> time() { + return appendCommand(new CommandObject<>(commandObjects.commandArguments(Protocol.Command.TIME), BuilderFactory.STRING_LIST)); } @Override - public Response strAlgoLCSKeys(String keyA, String keyB, StrAlgoLCSParams params) { - return appendCommand(commandObjects.strAlgoLCSKeys(keyA, keyB, params)); + public Response select(final int index) { + return appendCommand(new CommandObject<>(commandObjects.commandArguments(Protocol.Command.SELECT).add(index), BuilderFactory.STRING)); } @Override - public Response lcs(String keyA, String keyB, LCSParams params) { - return appendCommand(commandObjects.lcs(keyA, keyB, params)); + public Response dbSize() { + return appendCommand(new CommandObject<>(commandObjects.commandArguments(Protocol.Command.DBSIZE), BuilderFactory.LONG)); } @Override - public Response set(String key, String value) { - return appendCommand(commandObjects.set(key, value)); + public Response swapDB(final int index1, final int index2) { + return appendCommand(new CommandObject<>(commandObjects.commandArguments(Protocol.Command.SWAPDB) + .add(index1).add(index2), BuilderFactory.STRING)); } @Override - public Response set(String key, String value, SetParams params) { - return appendCommand(commandObjects.set(key, value, params)); + public Response move(String key, int dbIndex) { + return appendCommand(new CommandObject<>(commandObjects.commandArguments(Protocol.Command.MOVE) + .key(key).add(dbIndex), BuilderFactory.LONG)); } @Override - public Response rpush(String key, String... string) { - return appendCommand(commandObjects.rpush(key, string)); - + public Response move(final byte[] key, final int dbIndex) { + return appendCommand(new CommandObject<>(commandObjects.commandArguments(Protocol.Command.MOVE) + .key(key).add(dbIndex), BuilderFactory.LONG)); } @Override - public Response lpush(String key, String... string) { - return appendCommand(commandObjects.lpush(key, string)); + public Response copy(String srcKey, String dstKey, int db, boolean replace) { + return appendCommand(commandObjects.copy(srcKey, dstKey, db, replace)); } @Override - public Response llen(String key) { - return appendCommand(commandObjects.llen(key)); + public Response copy(byte[] srcKey, byte[] dstKey, int db, boolean replace) { + return appendCommand(commandObjects.copy(srcKey, dstKey, db, replace)); } @Override - public Response> lrange(String key, long start, long stop) { - return appendCommand(commandObjects.lrange(key, start, stop)); + public Response migrate(String host, int port, byte[] key, int destinationDB, int timeout) { + return appendCommand(commandObjects.migrate(host, port, key, destinationDB, timeout)); } @Override - public Response ltrim(String key, long start, long stop) { - return appendCommand(commandObjects.ltrim(key, start, stop)); + public Response migrate(String host, int port, String key, int destinationDB, int timeout) { + return appendCommand(commandObjects.migrate(host, port, key, destinationDB, timeout)); } @Override - public Response lindex(String key, long index) { - return appendCommand(commandObjects.lindex(key, index)); - } - - @Override - public Response lset(String key, long index, String value) { - return appendCommand(commandObjects.lset(key, index, value)); - } - - @Override - public Response lrem(String key, long count, String value) { - return appendCommand(commandObjects.lrem(key, count, value)); - } - - @Override - public Response lpop(String key) { - return appendCommand(commandObjects.lpop(key)); - } - - @Override - public Response> lpop(String key, int count) { - return appendCommand(commandObjects.lpop(key, count)); - } - - @Override - public Response lpos(String key, String element) { - return appendCommand(commandObjects.lpos(key, element)); - } - - @Override - public Response lpos(String key, String element, LPosParams params) { - return appendCommand(commandObjects.lpos(key, element, params)); - } - - @Override - public Response> lpos(String key, String element, LPosParams params, long count) { - return appendCommand(commandObjects.lpos(key, element, params, count)); - } - - @Override - public Response rpop(String key) { - return appendCommand(commandObjects.rpop(key)); - } - - @Override - public Response> rpop(String key, int count) { - return appendCommand(commandObjects.rpop(key, count)); - } - - @Override - public Response linsert(String key, ListPosition where, String pivot, String value) { - return appendCommand(commandObjects.linsert(key, where, pivot, value)); - } - - @Override - public Response lpushx(String key, String... strings) { - return appendCommand(commandObjects.lpushx(key, strings)); - } - - @Override - public Response rpushx(String key, String... strings) { - return appendCommand(commandObjects.rpushx(key, strings)); - } - - @Override - public Response> blpop(int timeout, String key) { - return appendCommand(commandObjects.blpop(timeout, key)); - } - - @Override - public Response blpop(double timeout, String key) { - return appendCommand(commandObjects.blpop(timeout, key)); - } - - @Override - public Response> brpop(int timeout, String key) { - return appendCommand(commandObjects.brpop(timeout, key)); - } - - @Override - public Response brpop(double timeout, String key) { - return appendCommand(commandObjects.brpop(timeout, key)); - } - - @Override - public Response> blpop(int timeout, String... keys) { - return appendCommand(commandObjects.blpop(timeout, keys)); - } - - @Override - public Response blpop(double timeout, String... keys) { - return appendCommand(commandObjects.blpop(timeout, keys)); - } - - @Override - public Response> brpop(int timeout, String... keys) { - return appendCommand(commandObjects.brpop(timeout, keys)); - } - - @Override - public Response brpop(double timeout, String... keys) { - return appendCommand(commandObjects.brpop(timeout, keys)); - } - - @Override - public Response rpoplpush(String srcKey, String dstKey) { - return appendCommand(commandObjects.rpoplpush(srcKey, dstKey)); - } - - @Override - public Response brpoplpush(String source, String destination, int timeout) { - return appendCommand(commandObjects.brpoplpush(source, destination, timeout)); - } - - @Override - public Response lmove(String srcKey, String dstKey, ListDirection from, ListDirection to) { - return appendCommand(commandObjects.lmove(srcKey, dstKey, from, to)); - } - - @Override - public Response blmove(String srcKey, String dstKey, ListDirection from, ListDirection to, double timeout) { - return appendCommand(commandObjects.blmove(srcKey, dstKey, from, to, timeout)); - } - - @Override - public Response>> lmpop(ListDirection direction, String... keys) { - return appendCommand(commandObjects.lmpop(direction, keys)); - } - - @Override - public Response>> lmpop(ListDirection direction, int count, String... keys) { - return appendCommand(commandObjects.lmpop(direction, count, keys)); - } - - @Override - public Response>> blmpop(long timeout, ListDirection direction, String... keys) { - return appendCommand(commandObjects.blmpop(timeout, direction, keys)); - } - - @Override - public Response>> blmpop(long timeout, ListDirection direction, int count, String... keys) { - return appendCommand(commandObjects.blmpop(timeout, direction, count, keys)); - } - - @Override - public Response hset(String key, String field, String value) { - return appendCommand(commandObjects.hset(key, field, value)); - } - - @Override - public Response hset(String key, Map hash) { - return appendCommand(commandObjects.hset(key, hash)); - } - - @Override - public Response hget(String key, String field) { - return appendCommand(commandObjects.hget(key, field)); - } - - @Override - public Response hsetnx(String key, String field, String value) { - return appendCommand(commandObjects.hsetnx(key, field, value)); - } - - @Override - public Response hmset(String key, Map hash) { - return appendCommand(commandObjects.hmset(key, hash)); - } - - @Override - public Response> hmget(String key, String... fields) { - return appendCommand(commandObjects.hmget(key, fields)); - } - - @Override - public Response hincrBy(String key, String field, long value) { - return appendCommand(commandObjects.hincrBy(key, field, value)); - } - - @Override - public Response hincrByFloat(String key, String field, double value) { - return appendCommand(commandObjects.hincrByFloat(key, field, value)); - } - - @Override - public Response hexists(String key, String field) { - return appendCommand(commandObjects.hexists(key, field)); - } - - @Override - public Response hdel(String key, String... field) { - return appendCommand(commandObjects.hdel(key, field)); - } - - @Override - public Response hlen(String key) { - return appendCommand(commandObjects.hlen(key)); - } - - @Override - public Response> hkeys(String key) { - return appendCommand(commandObjects.hkeys(key)); - } - - @Override - public Response> hvals(String key) { - return appendCommand(commandObjects.hvals(key)); - } - - @Override - public Response> hgetAll(String key) { - return appendCommand(commandObjects.hgetAll(key)); - } - - @Override - public Response hrandfield(String key) { - return appendCommand(commandObjects.hrandfield(key)); - } - - @Override - public Response> hrandfield(String key, long count) { - return appendCommand(commandObjects.hrandfield(key, count)); - } - - @Override - public Response> hrandfieldWithValues(String key, long count) { - return appendCommand(commandObjects.hrandfieldWithValues(key, count)); - } - - @Override - public Response>> hscan(String key, String cursor, ScanParams params) { - return appendCommand(commandObjects.hscan(key, cursor, params)); - } - - @Override - public Response hstrlen(String key, String field) { - return appendCommand(commandObjects.hstrlen(key, field)); - } - - @Override - public Response sadd(String key, String... members) { - return appendCommand(commandObjects.sadd(key, members)); - } - - @Override - public Response> smembers(String key) { - return appendCommand(commandObjects.smembers(key)); - } - - @Override - public Response srem(String key, String... members) { - return appendCommand(commandObjects.srem(key, members)); - } - - @Override - public Response spop(String key) { - return appendCommand(commandObjects.spop(key)); - } - - @Override - public Response> spop(String key, long count) { - return appendCommand(commandObjects.spop(key, count)); - } - - @Override - public Response scard(String key) { - return appendCommand(commandObjects.scard(key)); - } - - @Override - public Response sismember(String key, String member) { - return appendCommand(commandObjects.sismember(key, member)); - } - - @Override - public Response> smismember(String key, String... members) { - return appendCommand(commandObjects.smismember(key, members)); - } - - @Override - public Response srandmember(String key) { - return appendCommand(commandObjects.srandmember(key)); - } - - @Override - public Response> srandmember(String key, int count) { - return appendCommand(commandObjects.srandmember(key, count)); - } - - @Override - public Response> sscan(String key, String cursor, ScanParams params) { - return appendCommand(commandObjects.sscan(key, cursor, params)); - } - - @Override - public Response> sdiff(String... keys) { - return appendCommand(commandObjects.sdiff(keys)); - } - - @Override - public Response sdiffstore(String dstKey, String... keys) { - return appendCommand(commandObjects.sdiffstore(dstKey, keys)); - } - - @Override - public Response> sinter(String... keys) { - return appendCommand(commandObjects.sinter(keys)); - } - - @Override - public Response sinterstore(String dstKey, String... keys) { - return appendCommand(commandObjects.sinterstore(dstKey, keys)); - } - - @Override - public Response sintercard(String... keys) { - return appendCommand(commandObjects.sintercard(keys)); - } - - @Override - public Response sintercard(int limit, String... keys) { - return appendCommand(commandObjects.sintercard(limit, keys)); - } - - @Override - public Response> sunion(String... keys) { - return appendCommand(commandObjects.sunion(keys)); - } - - @Override - public Response sunionstore(String dstKey, String... keys) { - return appendCommand(commandObjects.sunionstore(dstKey, keys)); - } - - @Override - public Response smove(String srcKey, String dstKey, String member) { - return appendCommand(commandObjects.smove(srcKey, dstKey, member)); - } - - @Override - public Response zadd(String key, double score, String member) { - return appendCommand(commandObjects.zadd(key, score, member)); - } - - @Override - public Response zadd(String key, double score, String member, ZAddParams params) { - return appendCommand(commandObjects.zadd(key, score, member, params)); - } - - @Override - public Response zadd(String key, Map scoreMembers) { - return appendCommand(commandObjects.zadd(key, scoreMembers)); - } - - @Override - public Response zadd(String key, Map scoreMembers, ZAddParams params) { - return appendCommand(commandObjects.zadd(key, scoreMembers, params)); - } - - @Override - public Response zaddIncr(String key, double score, String member, ZAddParams params) { - return appendCommand(commandObjects.zaddIncr(key, score, member, params)); - } - - @Override - public Response zrem(String key, String... members) { - return appendCommand(commandObjects.zrem(key, members)); - } - - @Override - public Response zincrby(String key, double increment, String member) { - return appendCommand(commandObjects.zincrby(key, increment, member)); - } - - @Override - public Response zincrby(String key, double increment, String member, ZIncrByParams params) { - return appendCommand(commandObjects.zincrby(key, increment, member, params)); - } - - @Override - public Response zrank(String key, String member) { - return appendCommand(commandObjects.zrank(key, member)); - } - - @Override - public Response zrevrank(String key, String member) { - return appendCommand(commandObjects.zrevrank(key, member)); - } - - @Override - public Response> zrange(String key, long start, long stop) { - return appendCommand(commandObjects.zrange(key, start, stop)); - } - - @Override - public Response> zrevrange(String key, long start, long stop) { - return appendCommand(commandObjects.zrevrange(key, start, stop)); - } - - @Override - public Response> zrangeWithScores(String key, long start, long stop) { - return appendCommand(commandObjects.zrangeWithScores(key, start, stop)); - } - - @Override - public Response> zrevrangeWithScores(String key, long start, long stop) { - return appendCommand(commandObjects.zrevrangeWithScores(key, start, stop)); - } - - @Override - public Response zrandmember(String key) { - return appendCommand(commandObjects.zrandmember(key)); - } - - @Override - public Response> zrandmember(String key, long count) { - return appendCommand(commandObjects.zrandmember(key, count)); - } - - @Override - public Response> zrandmemberWithScores(String key, long count) { - return appendCommand(commandObjects.zrandmemberWithScores(key, count)); - } - - @Override - public Response zcard(String key) { - return appendCommand(commandObjects.zcard(key)); - } - - @Override - public Response zscore(String key, String member) { - return appendCommand(commandObjects.zscore(key, member)); - } - - @Override - public Response> zmscore(String key, String... members) { - return appendCommand(commandObjects.zmscore(key, members)); - } - - @Override - public Response zpopmax(String key) { - return appendCommand(commandObjects.zpopmax(key)); - } - - @Override - public Response> zpopmax(String key, int count) { - return appendCommand(commandObjects.zpopmax(key, count)); - } - - @Override - public Response zpopmin(String key) { - return appendCommand(commandObjects.zpopmin(key)); - } - - @Override - public Response> zpopmin(String key, int count) { - return appendCommand(commandObjects.zpopmin(key, count)); - } - - @Override - public Response zcount(String key, double min, double max) { - return appendCommand(commandObjects.zcount(key, min, max)); - } - - @Override - public Response zcount(String key, String min, String max) { - return appendCommand(commandObjects.zcount(key, min, max)); - } - - @Override - public Response> zrangeByScore(String key, double min, double max) { - return appendCommand(commandObjects.zrangeByScore(key, min, max)); - } - - @Override - public Response> zrangeByScore(String key, String min, String max) { - return appendCommand(commandObjects.zrangeByScore(key, min, max)); - } - - @Override - public Response> zrevrangeByScore(String key, double max, double min) { - return appendCommand(commandObjects.zrevrangeByScore(key, max, min)); - - } - - @Override - public Response> zrangeByScore(String key, double min, double max, int offset, int count) { - return appendCommand(commandObjects.zrangeByScore(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByScore(String key, String max, String min) { - return appendCommand(commandObjects.zrevrangeByScore(key, max, min)); - } - - @Override - public Response> zrangeByScore(String key, String min, String max, int offset, int count) { - return appendCommand(commandObjects.zrangeByScore(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByScore(String key, double max, double min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByScore(key, max, min, offset, count)); - } - - @Override - public Response> zrangeByScoreWithScores(String key, double min, double max) { - return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max)); - } - - @Override - public Response> zrevrangeByScoreWithScores(String key, double max, double min) { - return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min)); - } - - @Override - public Response> zrangeByScoreWithScores(String key, double min, double max, int offset, int count) { - return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByScore(String key, String max, String min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByScore(key, max, min, offset, count)); - } - - @Override - public Response> zrangeByScoreWithScores(String key, String min, String max) { - return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max)); - } - - @Override - public Response> zrevrangeByScoreWithScores(String key, String max, String min) { - return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min)); - } - - @Override - public Response> zrangeByScoreWithScores(String key, String min, String max, int offset, int count) { - return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByScoreWithScores(String key, double max, double min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min, offset, count)); - } - - @Override - public Response> zrevrangeByScoreWithScores(String key, String max, String min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min, offset, count)); - } - - @Override - public Response> zrange(String key, ZRangeParams zRangeParams) { - return appendCommand(commandObjects.zrange(key, zRangeParams)); - } - - @Override - public Response> zrangeWithScores(String key, ZRangeParams zRangeParams) { - return appendCommand(commandObjects.zrangeWithScores(key, zRangeParams)); - } - - @Override - public Response zrangestore(String dest, String src, ZRangeParams zRangeParams) { - return appendCommand(commandObjects.zrangestore(dest, src, zRangeParams)); - } - - @Override - public Response zremrangeByRank(String key, long start, long stop) { - return appendCommand(commandObjects.zremrangeByRank(key, start, stop)); - } - - @Override - public Response zremrangeByScore(String key, double min, double max) { - return appendCommand(commandObjects.zremrangeByScore(key, min, max)); - } - - @Override - public Response zremrangeByScore(String key, String min, String max) { - return appendCommand(commandObjects.zremrangeByScore(key, min, max)); - } - - @Override - public Response zlexcount(String key, String min, String max) { - return appendCommand(commandObjects.zlexcount(key, min, max)); - } - - @Override - public Response> zrangeByLex(String key, String min, String max) { - return appendCommand(commandObjects.zrangeByLex(key, min, max)); - } - - @Override - public Response> zrangeByLex(String key, String min, String max, int offset, int count) { - return appendCommand(commandObjects.zrangeByLex(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByLex(String key, String max, String min) { - return appendCommand(commandObjects.zrevrangeByLex(key, max, min)); - } - - @Override - public Response> zrevrangeByLex(String key, String max, String min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByLex(key, max, min, offset, count)); - } - - @Override - public Response zremrangeByLex(String key, String min, String max) { - return appendCommand(commandObjects.zremrangeByLex(key, min, max)); - } - - @Override - public Response> zscan(String key, String cursor, ScanParams params) { - return appendCommand(commandObjects.zscan(key, cursor, params)); - } - - @Override - public Response bzpopmax(double timeout, String... keys) { - return appendCommand(commandObjects.bzpopmax(timeout, keys)); - } - - @Override - public Response bzpopmin(double timeout, String... keys) { - return appendCommand(commandObjects.bzpopmin(timeout, keys)); - } - - @Override - public Response>> zmpop(SortedSetOption option, String... keys) { - return appendCommand(commandObjects.zmpop(option, keys)); - } - - @Override - public Response>> zmpop(SortedSetOption option, int count, String... keys) { - return appendCommand(commandObjects.zmpop(option, count, keys)); - } - - @Override - public Response>> bzmpop(long timeout, SortedSetOption option, String... keys) { - return appendCommand(commandObjects.bzmpop(timeout, option, keys)); - } - - @Override - public Response>> bzmpop(long timeout, SortedSetOption option, int count, String... keys) { - return appendCommand(commandObjects.bzmpop(timeout, option, count, keys)); - } - - @Override - public Response> zdiff(String... keys) { - return appendCommand(commandObjects.zdiff(keys)); - } - - @Override - public Response> zdiffWithScores(String... keys) { - return appendCommand(commandObjects.zdiffWithScores(keys)); - } - - @Override - public Response zdiffStore(String dstKey, String... keys) { - return appendCommand(commandObjects.zdiffStore(dstKey, keys)); - } - - @Override - public Response zinterstore(String dstKey, String... sets) { - return appendCommand(commandObjects.zinterstore(dstKey, sets)); - } - - @Override - public Response zinterstore(String dstKey, ZParams params, String... sets) { - return appendCommand(commandObjects.zinterstore(dstKey, params, sets)); - } - - @Override - public Response> zinter(ZParams params, String... keys) { - return appendCommand(commandObjects.zinter(params, keys)); - } - - @Override - public Response> zinterWithScores(ZParams params, String... keys) { - return appendCommand(commandObjects.zinterWithScores(params, keys)); - } - @Override - public Response zintercard(String... keys) { - return appendCommand(commandObjects.zintercard(keys)); - } - - @Override - public Response zintercard(long limit, String... keys) { - return appendCommand(commandObjects.zintercard(limit, keys)); - } - - @Override - public Response> zunion(ZParams params, String... keys) { - return appendCommand(commandObjects.zunion(params, keys)); - } - - @Override - public Response> zunionWithScores(ZParams params, String... keys) { - return appendCommand(commandObjects.zunionWithScores(params, keys)); - } - - @Override - public Response zunionstore(String dstKey, String... sets) { - return appendCommand(commandObjects.zunionstore(dstKey, sets)); - } - - @Override - public Response zunionstore(String dstKey, ZParams params, String... sets) { - return appendCommand(commandObjects.zunionstore(dstKey, params, sets)); - } - - @Override - public Response geoadd(String key, double longitude, double latitude, String member) { - return appendCommand(commandObjects.geoadd(key, longitude, latitude, member)); - } - - @Override - public Response geoadd(String key, Map memberCoordinateMap) { - return appendCommand(commandObjects.geoadd(key, memberCoordinateMap)); - } - - @Override - public Response geoadd(String key, GeoAddParams params, Map memberCoordinateMap) { - return appendCommand(commandObjects.geoadd(key, params, memberCoordinateMap)); - } - - @Override - public Response geodist(String key, String member1, String member2) { - return appendCommand(commandObjects.geodist(key, member1, member2)); - } - - @Override - public Response geodist(String key, String member1, String member2, GeoUnit unit) { - return appendCommand(commandObjects.geodist(key, member1, member2, unit)); - } - - @Override - public Response> geohash(String key, String... members) { - return appendCommand(commandObjects.geohash(key, members)); - } - - @Override - public Response> geopos(String key, String... members) { - return appendCommand(commandObjects.geopos(key, members)); - } - - @Override - public Response> georadius(String key, double longitude, double latitude, double radius, GeoUnit unit) { - return appendCommand(commandObjects.georadius(key, longitude, latitude, radius, unit)); - } - - @Override - public Response> georadiusReadonly(String key, double longitude, double latitude, double radius, GeoUnit unit) { - return appendCommand(commandObjects.georadiusReadonly(key, longitude, latitude, radius, unit)); - } - - @Override - public Response> georadius(String key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param) { - return appendCommand(commandObjects.georadius(key, longitude, latitude, radius, unit, param)); - } - - @Override - public Response> georadiusReadonly(String key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param) { - return appendCommand(commandObjects.georadiusReadonly(key, longitude, latitude, radius, unit, param)); - } - - @Override - public Response> georadiusByMember(String key, String member, double radius, GeoUnit unit) { - return appendCommand(commandObjects.georadiusByMember(key, member, radius, unit)); - } - - @Override - public Response> georadiusByMemberReadonly(String key, String member, double radius, GeoUnit unit) { - return appendCommand(commandObjects.georadiusByMemberReadonly(key, member, radius, unit)); - } - - @Override - public Response> georadiusByMember(String key, String member, double radius, GeoUnit unit, GeoRadiusParam param) { - return appendCommand(commandObjects.georadiusByMember(key, member, radius, unit, param)); - } - - @Override - public Response> georadiusByMemberReadonly(String key, String member, double radius, GeoUnit unit, GeoRadiusParam param) { - return appendCommand(commandObjects.georadiusByMemberReadonly(key, member, radius, unit, param)); - } - - @Override - public Response georadiusStore(String key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param, GeoRadiusStoreParam storeParam) { - return appendCommand(commandObjects.georadiusStore(key, longitude, latitude, radius, unit, param, storeParam)); - } - - @Override - public Response georadiusByMemberStore(String key, String member, double radius, GeoUnit unit, GeoRadiusParam param, GeoRadiusStoreParam storeParam) { - return appendCommand(commandObjects.georadiusByMemberStore(key, member, radius, unit, param, storeParam)); - } - - @Override - public Response> geosearch(String key, String member, double radius, GeoUnit unit) { - return appendCommand(commandObjects.geosearch(key, member, radius, unit)); - } - - @Override - public Response> geosearch(String key, GeoCoordinate coord, double radius, GeoUnit unit) { - return appendCommand(commandObjects.geosearch(key, coord, radius, unit)); - } - - @Override - public Response> geosearch(String key, String member, double width, double height, GeoUnit unit) { - return appendCommand(commandObjects.geosearch(key, member, width, height, unit)); - } - - @Override - public Response> geosearch(String key, GeoCoordinate coord, double width, double height, GeoUnit unit) { - return appendCommand(commandObjects.geosearch(key, coord, width, height, unit)); - } - - @Override - public Response> geosearch(String key, GeoSearchParam params) { - return appendCommand(commandObjects.geosearch(key, params)); - } - - @Override - public Response geosearchStore(String dest, String src, String member, double radius, GeoUnit unit) { - return appendCommand(commandObjects.geosearchStore(dest, src, member, radius, unit)); - } - - @Override - public Response geosearchStore(String dest, String src, GeoCoordinate coord, double radius, GeoUnit unit) { - return appendCommand(commandObjects.geosearchStore(dest, src, coord, radius, unit)); - } - - @Override - public Response geosearchStore(String dest, String src, String member, double width, double height, GeoUnit unit) { - return appendCommand(commandObjects.geosearchStore(dest, src, member, width, height, unit)); - } - - @Override - public Response geosearchStore(String dest, String src, GeoCoordinate coord, double width, double height, GeoUnit unit) { - return appendCommand(commandObjects.geosearchStore(dest, src, coord, width, height, unit)); - } - - @Override - public Response geosearchStore(String dest, String src, GeoSearchParam params) { - return appendCommand(commandObjects.geosearchStore(dest, src, params)); - } - - @Override - public Response geosearchStoreStoreDist(String dest, String src, GeoSearchParam params) { - return appendCommand(commandObjects.geosearchStoreStoreDist(dest, src, params)); - } - - @Override - public Response pfadd(String key, String... elements) { - return appendCommand(commandObjects.pfadd(key, elements)); - } - - @Override - public Response pfmerge(String destkey, String... sourcekeys) { - return appendCommand(commandObjects.pfmerge(destkey, sourcekeys)); - } - - @Override - public Response pfcount(String key) { - return appendCommand(commandObjects.pfcount(key)); - } - - @Override - public Response pfcount(String... keys) { - return appendCommand(commandObjects.pfcount(keys)); - } - - @Override - public Response xadd(String key, StreamEntryID id, Map hash) { - return appendCommand(commandObjects.xadd(key, id, hash)); - } - - @Override - public Response xadd(String key, XAddParams params, Map hash) { - return appendCommand(commandObjects.xadd(key, params, hash)); - } - - @Override - public Response xlen(String key) { - return appendCommand(commandObjects.xlen(key)); - } - - @Override - public Response> xrange(String key, StreamEntryID start, StreamEntryID end) { - return appendCommand(commandObjects.xrange(key, start, end)); - } - - @Override - public Response> xrange(String key, StreamEntryID start, StreamEntryID end, int count) { - return appendCommand(commandObjects.xrange(key, start, end, count)); - } - - @Override - public Response> xrevrange(String key, StreamEntryID end, StreamEntryID start) { - return appendCommand(commandObjects.xrevrange(key, end, start)); - } - - @Override - public Response> xrevrange(String key, StreamEntryID end, StreamEntryID start, int count) { - return appendCommand(commandObjects.xrevrange(key, end, start, count)); - } - - @Override - public Response> xrange(String key, String start, String end) { - return appendCommand(commandObjects.xrange(key, start, end)); - } - - @Override - public Response> xrange(String key, String start, String end, int count) { - return appendCommand(commandObjects.xrange(key, start, end, count)); - } - - @Override - public Response> xrevrange(String key, String end, String start) { - return appendCommand(commandObjects.xrevrange(key, end, start)); - } - - @Override - public Response> xrevrange(String key, String end, String start, int count) { - return appendCommand(commandObjects.xrevrange(key, end, start, count)); - } - - @Override - public Response xack(String key, String group, StreamEntryID... ids) { - return appendCommand(commandObjects.xack(key, group, ids)); - } - - @Override - public Response xgroupCreate(String key, String groupName, StreamEntryID id, boolean makeStream) { - return appendCommand(commandObjects.xgroupCreate(key, groupName, id, makeStream)); - } - - @Override - public Response xgroupSetID(String key, String groupName, StreamEntryID id) { - return appendCommand(commandObjects.xgroupSetID(key, groupName, id)); - } - - @Override - public Response xgroupDestroy(String key, String groupName) { - return appendCommand(commandObjects.xgroupDestroy(key, groupName)); - } - - @Override - public Response xgroupCreateConsumer(String key, String groupName, String consumerName) { - return appendCommand(commandObjects.xgroupCreateConsumer(key, groupName, consumerName)); - } - - @Override - public Response xgroupDelConsumer(String key, String groupName, String consumerName) { - return appendCommand(commandObjects.xgroupDelConsumer(key, groupName, consumerName)); - } - - @Override - public Response xpending(String key, String groupName) { - return appendCommand(commandObjects.xpending(key, groupName)); - } - - @Override - public Response> xpending(String key, String groupName, StreamEntryID start, StreamEntryID end, int count, String consumerName) { - return appendCommand(commandObjects.xpending(key, groupName, start, end, count, consumerName)); - } - - @Override - public Response> xpending(String key, String groupName, XPendingParams params) { - return appendCommand(commandObjects.xpending(key, groupName, params)); - } - - @Override - public Response xdel(String key, StreamEntryID... ids) { - return appendCommand(commandObjects.xdel(key, ids)); - } - - @Override - public Response xtrim(String key, long maxLen, boolean approximate) { - return appendCommand(commandObjects.xtrim(key, maxLen, approximate)); - } - - @Override - public Response xtrim(String key, XTrimParams params) { - return appendCommand(commandObjects.xtrim(key, params)); - } - - @Override - public Response> xclaim(String key, String group, String consumerName, long minIdleTime, XClaimParams params, StreamEntryID... ids) { - return appendCommand(commandObjects.xclaim(key, group, consumerName, minIdleTime, params, ids)); - } - - @Override - public Response> xclaimJustId(String key, String group, String consumerName, long minIdleTime, XClaimParams params, StreamEntryID... ids) { - return appendCommand(commandObjects.xclaimJustId(key, group, consumerName, minIdleTime, params, ids)); - } - - @Override - public Response>> xautoclaim(String key, String group, String consumerName, long minIdleTime, StreamEntryID start, XAutoClaimParams params) { - return appendCommand(commandObjects.xautoclaim(key, group, consumerName, minIdleTime, start, params)); - } - - @Override - public Response>> xautoclaimJustId(String key, String group, String consumerName, long minIdleTime, StreamEntryID start, XAutoClaimParams params) { - return appendCommand(commandObjects.xautoclaimJustId(key, group, consumerName, minIdleTime, start, params)); - } - - @Override - public Response xinfoStream(String key) { - return appendCommand(commandObjects.xinfoStream(key)); - } - - @Override - public Response xinfoStreamFull(String key) { - return appendCommand(commandObjects.xinfoStreamFull(key)); - } - - @Override - public Response xinfoStreamFull(String key, int count) { - return appendCommand(commandObjects.xinfoStreamFull(key, count)); - } - - @Override - @Deprecated - public Response> xinfoGroup(String key) { - return appendCommand(commandObjects.xinfoGroup(key)); - } - - @Override - public Response> xinfoGroups(String key) { - return appendCommand(commandObjects.xinfoGroups(key)); - } - - @Override - public Response> xinfoConsumers(String key, String group) { - return appendCommand(commandObjects.xinfoConsumers(key, group)); - } - - @Override - public Response>>> xread(XReadParams xReadParams, Map streams) { - return appendCommand(commandObjects.xread(xReadParams, streams)); - } - - @Override - public Response>>> xreadGroup(String groupName, String consumer, XReadGroupParams xReadGroupParams, Map streams) { - return appendCommand(commandObjects.xreadGroup(groupName, consumer, xReadGroupParams, streams)); - } - - @Override - public Response eval(String script) { - return appendCommand(commandObjects.eval(script)); - } - - @Override - public Response eval(String script, int keyCount, String... params) { - return appendCommand(commandObjects.eval(script, keyCount, params)); - } - - @Override - public Response eval(String script, List keys, List args) { - return appendCommand(commandObjects.eval(script, keys, args)); - } - - @Override - public Response evalReadonly(String script, List keys, List args) { - return appendCommand(commandObjects.evalReadonly(script, keys, args)); - } - - @Override - public Response evalsha(String sha1) { - return appendCommand(commandObjects.evalsha(sha1)); - } - - @Override - public Response evalsha(String sha1, int keyCount, String... params) { - return appendCommand(commandObjects.evalsha(sha1, keyCount, params)); - } - - @Override - public Response evalsha(String sha1, List keys, List args) { - return appendCommand(commandObjects.evalsha(sha1, keys, args)); - } - - @Override - public Response evalshaReadonly(String sha1, List keys, List args) { - return appendCommand(commandObjects.evalshaReadonly(sha1, keys, args)); - } - - @Override - public Response waitReplicas(String sampleKey, int replicas, long timeout) { - return appendCommand(commandObjects.waitReplicas(sampleKey, replicas, timeout)); - } - - @Override - public Response eval(String script, String sampleKey) { - return appendCommand(commandObjects.eval(script, sampleKey)); - } - - @Override - public Response evalsha(String sha1, String sampleKey) { - return appendCommand(commandObjects.evalsha(sha1, sampleKey)); - } - - @Override - public Response> scriptExists(String sampleKey, String... sha1) { - return appendCommand(commandObjects.scriptExists(sampleKey, sha1)); - } - - @Override - public Response scriptLoad(String script, String sampleKey) { - return appendCommand(commandObjects.scriptLoad(script, sampleKey)); - } - - @Override - public Response scriptFlush(String sampleKey) { - return appendCommand(commandObjects.scriptFlush(sampleKey)); - } - - @Override - public Response scriptFlush(String sampleKey, FlushMode flushMode) { - return appendCommand(commandObjects.scriptFlush(sampleKey, flushMode)); - } - - @Override - public Response scriptKill(String sampleKey) { - return appendCommand(commandObjects.scriptKill(sampleKey)); - } - - @Override - public Response fcall(byte[] name, List keys, List args) { - return appendCommand(commandObjects.fcall(name, keys, args)); - } - - @Override - public Response fcall(String name, List keys, List args) { - return appendCommand(commandObjects.fcall(name, keys, args)); - } - - @Override - public Response fcallReadonly(byte[] name, List keys, List args) { - return appendCommand(commandObjects.fcallReadonly(name, keys, args)); - } - - @Override - public Response fcallReadonly(String name, List keys, List args) { - return appendCommand(commandObjects.fcallReadonly(name, keys, args)); - } - - @Override - public Response functionDelete(byte[] libraryName) { - return appendCommand(commandObjects.functionDelete(libraryName)); - } - - @Override - public Response functionDelete(String libraryName) { - return appendCommand(commandObjects.functionDelete(libraryName)); - } - - @Override - public Response functionDump() { - return appendCommand(commandObjects.functionDump()); - } - - @Override - public Response> functionList(String libraryNamePattern) { - return appendCommand(commandObjects.functionList(libraryNamePattern)); - } - - @Override - public Response> functionList() { - return appendCommand(commandObjects.functionList()); - } - - @Override - public Response> functionListWithCode(String libraryNamePattern) { - return appendCommand(commandObjects.functionListWithCode(libraryNamePattern)); - } - - @Override - public Response> functionListWithCode() { - return appendCommand(commandObjects.functionListWithCode()); - } - - @Override - public Response> functionListBinary() { - return appendCommand(commandObjects.functionListBinary()); - } - - @Override - public Response> functionList(final byte[] libraryNamePattern) { - return appendCommand(commandObjects.functionList(libraryNamePattern)); - } - - @Override - public Response> functionListWithCodeBinary() { - return appendCommand(commandObjects.functionListWithCodeBinary()); - } - - @Override - public Response> functionListWithCode(final byte[] libraryNamePattern) { - return appendCommand(commandObjects.functionListWithCode(libraryNamePattern)); - } - - @Override - public Response functionLoad(byte[] functionCode) { - return appendCommand(commandObjects.functionLoad(functionCode)); - } - - @Override - public Response functionLoad(String functionCode) { - return appendCommand(commandObjects.functionLoad(functionCode)); - } - - @Override - public Response functionLoadReplace(byte[] functionCode) { - return appendCommand(commandObjects.functionLoadReplace(functionCode)); - } - - @Override - public Response functionLoadReplace(String functionCode) { - return appendCommand(commandObjects.functionLoadReplace(functionCode)); - } - - @Override - public Response functionRestore(byte[] serializedValue) { - return appendCommand(commandObjects.functionRestore(serializedValue)); - } - - @Override - public Response functionRestore(byte[] serializedValue, FunctionRestorePolicy policy) { - return appendCommand(commandObjects.functionRestore(serializedValue, policy)); - } - - @Override - public Response functionFlush() { - return appendCommand(commandObjects.functionFlush()); - } - - @Override - public Response functionFlush(FlushMode mode) { - return appendCommand(commandObjects.functionFlush(mode)); - } - - @Override - public Response functionKill() { - return appendCommand(commandObjects.functionKill()); - } - - @Override - public Response functionStats() { - return appendCommand(commandObjects.functionStats()); - } - - @Override - public Response functionStatsBinary() { - return appendCommand(commandObjects.functionStatsBinary()); - } - - public Response publish(String channel, String message) { - return appendCommand(commandObjects.publish(channel, message)); - } - - public Response strAlgoLCSStrings(String strA, String strB, StrAlgoLCSParams params) { - return appendCommand(commandObjects.strAlgoLCSStrings(strA, strB, params)); - } - - @Override - public Response geoadd(byte[] key, double longitude, double latitude, byte[] member) { - return appendCommand(commandObjects.geoadd(key, longitude, latitude, member)); - } - - @Override - public Response geoadd(byte[] key, Map memberCoordinateMap) { - return appendCommand(commandObjects.geoadd(key, memberCoordinateMap)); - } - - @Override - public Response geoadd(byte[] key, GeoAddParams params, Map memberCoordinateMap) { - return appendCommand(commandObjects.geoadd(key, params, memberCoordinateMap)); - } - - @Override - public Response geodist(byte[] key, byte[] member1, byte[] member2) { - return appendCommand(commandObjects.geodist(key, member1, member2)); - } - - @Override - public Response geodist(byte[] key, byte[] member1, byte[] member2, GeoUnit unit) { - return appendCommand(commandObjects.geodist(key, member1, member2, unit)); - } - - @Override - public Response> geohash(byte[] key, byte[]... members) { - return appendCommand(commandObjects.geohash(key, members)); - } - - @Override - public Response> geopos(byte[] key, byte[]... members) { - return appendCommand(commandObjects.geopos(key, members)); - } - - @Override - public Response> georadius(byte[] key, double longitude, double latitude, double radius, GeoUnit unit) { - return appendCommand(commandObjects.georadius(key, longitude, latitude, radius, unit)); - } - - @Override - public Response> georadiusReadonly(byte[] key, double longitude, double latitude, double radius, GeoUnit unit) { - return appendCommand(commandObjects.georadiusReadonly(key, longitude, latitude, radius, unit)); - } - - @Override - public Response> georadius(byte[] key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param) { - return appendCommand(commandObjects.georadius(key, longitude, latitude, radius, unit, param)); - } - - @Override - public Response> georadiusReadonly(byte[] key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param) { - return appendCommand(commandObjects.georadiusReadonly(key, longitude, latitude, radius, unit, param)); - } - - @Override - public Response> georadiusByMember(byte[] key, byte[] member, double radius, GeoUnit unit) { - return appendCommand(commandObjects.georadiusByMember(key, member, radius, unit)); - } - - @Override - public Response> georadiusByMemberReadonly(byte[] key, byte[] member, double radius, GeoUnit unit) { - return appendCommand(commandObjects.georadiusByMemberReadonly(key, member, radius, unit)); - } - - @Override - public Response> georadiusByMember(byte[] key, byte[] member, double radius, GeoUnit unit, GeoRadiusParam param) { - return appendCommand(commandObjects.georadiusByMember(key, member, radius, unit, param)); - } - - @Override - public Response> georadiusByMemberReadonly(byte[] key, byte[] member, double radius, GeoUnit unit, GeoRadiusParam param) { - return appendCommand(commandObjects.georadiusByMemberReadonly(key, member, radius, unit, param)); - } - - @Override - public Response georadiusStore(byte[] key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param, GeoRadiusStoreParam storeParam) { - return appendCommand(commandObjects.georadiusStore(key, longitude, latitude, radius, unit, param, storeParam)); - } - - @Override - public Response georadiusByMemberStore(byte[] key, byte[] member, double radius, GeoUnit unit, GeoRadiusParam param, GeoRadiusStoreParam storeParam) { - return appendCommand(commandObjects.georadiusByMemberStore(key, member, radius, unit, param, storeParam)); - } - - @Override - public Response> geosearch(byte[] key, byte[] member, double radius, GeoUnit unit) { - return appendCommand(commandObjects.geosearch(key, member, radius, unit)); - } - - @Override - public Response> geosearch(byte[] key, GeoCoordinate coord, double radius, GeoUnit unit) { - return appendCommand(commandObjects.geosearch(key, coord, radius, unit)); - } - - @Override - public Response> geosearch(byte[] key, byte[] member, double width, double height, GeoUnit unit) { - return appendCommand(commandObjects.geosearch(key, member, width, height, unit)); - } - - @Override - public Response> geosearch(byte[] key, GeoCoordinate coord, double width, double height, GeoUnit unit) { - return appendCommand(commandObjects.geosearch(key, coord, width, height, unit)); - } - - @Override - public Response> geosearch(byte[] key, GeoSearchParam params) { - return appendCommand(commandObjects.geosearch(key, params)); - } - - @Override - public Response geosearchStore(byte[] dest, byte[] src, byte[] member, double radius, GeoUnit unit) { - return appendCommand(commandObjects.geosearchStore(dest, src, member, radius, unit)); - } - - @Override - public Response geosearchStore(byte[] dest, byte[] src, GeoCoordinate coord, double radius, GeoUnit unit) { - return appendCommand(commandObjects.geosearchStore(dest, src, coord, radius, unit)); - } - - @Override - public Response geosearchStore(byte[] dest, byte[] src, byte[] member, double width, double height, GeoUnit unit) { - return appendCommand(commandObjects.geosearchStore(dest, src, member, width, height, unit)); - } - - @Override - public Response geosearchStore(byte[] dest, byte[] src, GeoCoordinate coord, double width, double height, GeoUnit unit) { - return appendCommand(commandObjects.geosearchStore(dest, src, coord, width, height, unit)); - } - - @Override - public Response geosearchStore(byte[] dest, byte[] src, GeoSearchParam params) { - return appendCommand(commandObjects.geosearchStore(dest, src, params)); - } - - @Override - public Response geosearchStoreStoreDist(byte[] dest, byte[] src, GeoSearchParam params) { - return appendCommand(commandObjects.geosearchStoreStoreDist(dest, src, params)); - } - - @Override - public Response hset(byte[] key, byte[] field, byte[] value) { - return appendCommand(commandObjects.hset(key, field, value)); - } - - @Override - public Response hset(byte[] key, Map hash) { - return appendCommand(commandObjects.hset(key, hash)); - } - - @Override - public Response hget(byte[] key, byte[] field) { - return appendCommand(commandObjects.hget(key, field)); - } - - @Override - public Response hsetnx(byte[] key, byte[] field, byte[] value) { - return appendCommand(commandObjects.hsetnx(key, field, value)); - } - - @Override - public Response hmset(byte[] key, Map hash) { - return appendCommand(commandObjects.hmset(key, hash)); - } - - @Override - public Response> hmget(byte[] key, byte[]... fields) { - return appendCommand(commandObjects.hmget(key, fields)); - } - - @Override - public Response hincrBy(byte[] key, byte[] field, long value) { - return appendCommand(commandObjects.hincrBy(key, field, value)); - } - - @Override - public Response hincrByFloat(byte[] key, byte[] field, double value) { - return appendCommand(commandObjects.hincrByFloat(key, field, value)); - } - - @Override - public Response hexists(byte[] key, byte[] field) { - return appendCommand(commandObjects.hexists(key, field)); - } - - @Override - public Response hdel(byte[] key, byte[]... field) { - return appendCommand(commandObjects.hdel(key, field)); - } - - @Override - public Response hlen(byte[] key) { - return appendCommand(commandObjects.hlen(key)); - } - - @Override - public Response> hkeys(byte[] key) { - return appendCommand(commandObjects.hkeys(key)); - } - - @Override - public Response> hvals(byte[] key) { - return appendCommand(commandObjects.hvals(key)); - } - - @Override - public Response> hgetAll(byte[] key) { - return appendCommand(commandObjects.hgetAll(key)); - } - - @Override - public Response hrandfield(byte[] key) { - return appendCommand(commandObjects.hrandfield(key)); - } - - @Override - public Response> hrandfield(byte[] key, long count) { - return appendCommand(commandObjects.hrandfield(key, count)); - } - - @Override - public Response> hrandfieldWithValues(byte[] key, long count) { - return appendCommand(commandObjects.hrandfieldWithValues(key, count)); - } - - @Override - public Response>> hscan(byte[] key, byte[] cursor, ScanParams params) { - return appendCommand(commandObjects.hscan(key, cursor, params)); - } - - @Override - public Response hstrlen(byte[] key, byte[] field) { - return appendCommand(commandObjects.hstrlen(key, field)); - } - - @Override - public Response pfadd(byte[] key, byte[]... elements) { - return appendCommand(commandObjects.pfadd(key, elements)); - } - - @Override - public Response pfmerge(byte[] destkey, byte[]... sourcekeys) { - return appendCommand(commandObjects.pfmerge(destkey, sourcekeys)); - } - - @Override - public Response pfcount(byte[] key) { - return appendCommand(commandObjects.pfcount(key)); - } - - @Override - public Response pfcount(byte[]... keys) { - return appendCommand(commandObjects.pfcount(keys)); - } - - @Override - public Response exists(byte[] key) { - return appendCommand(commandObjects.exists(key)); - } - - @Override - public Response exists(byte[]... keys) { - return appendCommand(commandObjects.exists(keys)); - } - - @Override - public Response persist(byte[] key) { - return appendCommand(commandObjects.persist(key)); - } - - @Override - public Response type(byte[] key) { - return appendCommand(commandObjects.type(key)); - } - - @Override - public Response dump(byte[] key) { - return appendCommand(commandObjects.dump(key)); - } - - @Override - public Response restore(byte[] key, long ttl, byte[] serializedValue) { - return appendCommand(commandObjects.restore(key, ttl, serializedValue)); - } - - @Override - public Response restore(byte[] key, long ttl, byte[] serializedValue, RestoreParams params) { - return appendCommand(commandObjects.restore(key, ttl, serializedValue, params)); - } - - @Override - public Response expire(byte[] key, long seconds) { - return appendCommand(commandObjects.expire(key, seconds)); - } - - @Override - public Response expire(byte[] key, long seconds, ExpiryOption expiryOption) { - return appendCommand(commandObjects.expire(key, seconds, expiryOption)); - } - - @Override - public Response pexpire(byte[] key, long milliseconds) { - return appendCommand(commandObjects.pexpire(key, milliseconds)); - } - - @Override - public Response pexpire(byte[] key, long milliseconds, ExpiryOption expiryOption) { - return appendCommand(commandObjects.pexpire(key, milliseconds, expiryOption)); - } - - @Override - public Response expireTime(byte[] key) { - return appendCommand(commandObjects.expireTime(key)); - } - - @Override - public Response pexpireTime(byte[] key) { - return appendCommand(commandObjects.pexpireTime(key)); - } - - @Override - public Response expireAt(byte[] key, long unixTime) { - return appendCommand(commandObjects.expireAt(key, unixTime)); - } - - @Override - public Response expireAt(byte[] key, long unixTime, ExpiryOption expiryOption) { - return appendCommand(commandObjects.expireAt(key, unixTime)); - } - - @Override - public Response pexpireAt(byte[] key, long millisecondsTimestamp) { - return appendCommand(commandObjects.pexpireAt(key, millisecondsTimestamp)); - } - - @Override - public Response pexpireAt(byte[] key, long millisecondsTimestamp, ExpiryOption expiryOption) { - return appendCommand(commandObjects.pexpireAt(key, millisecondsTimestamp, expiryOption)); - } - - @Override - public Response ttl(byte[] key) { - return appendCommand(commandObjects.ttl(key)); - } - - @Override - public Response pttl(byte[] key) { - return appendCommand(commandObjects.pttl(key)); - } - - @Override - public Response touch(byte[] key) { - return appendCommand(commandObjects.touch(key)); - } - - @Override - public Response touch(byte[]... keys) { - return appendCommand(commandObjects.touch(keys)); - } - - @Override - public Response> sort(byte[] key) { - return appendCommand(commandObjects.sort(key)); - } - - @Override - public Response> sort(byte[] key, SortingParams sortingParams) { - return appendCommand(commandObjects.sort(key, sortingParams)); - } - - @Override - public Response> sortReadonly(byte[] key, SortingParams sortingParams) { - return appendCommand(commandObjects.sortReadonly(key, sortingParams)); - } - - @Override - public Response del(byte[] key) { - return appendCommand(commandObjects.del(key)); - } - - @Override - public Response del(byte[]... keys) { - return appendCommand(commandObjects.del(keys)); - } - - @Override - public Response unlink(byte[] key) { - return appendCommand(commandObjects.unlink(key)); - } - - @Override - public Response unlink(byte[]... keys) { - return appendCommand(commandObjects.unlink(keys)); - } - - @Override - public Response copy(byte[] srcKey, byte[] dstKey, boolean replace) { - return appendCommand(commandObjects.copy(srcKey, dstKey, replace)); - } - - @Override - public Response rename(byte[] oldkey, byte[] newkey) { - return appendCommand(commandObjects.rename(oldkey, newkey)); - } - - @Override - public Response renamenx(byte[] oldkey, byte[] newkey) { - return appendCommand(commandObjects.renamenx(oldkey, newkey)); - } - - @Override - public Response sort(byte[] key, SortingParams sortingParams, byte[] dstkey) { - return appendCommand(commandObjects.sort(key, sortingParams, dstkey)); - } - - @Override - public Response sort(byte[] key, byte[] dstkey) { - return appendCommand(commandObjects.sort(key, dstkey)); - } - - @Override - public Response memoryUsage(byte[] key) { - return appendCommand(commandObjects.memoryUsage(key)); - } - - @Override - public Response memoryUsage(byte[] key, int samples) { - return appendCommand(commandObjects.memoryUsage(key, samples)); - } - - @Override - public Response objectRefcount(byte[] key) { - return appendCommand(commandObjects.objectRefcount(key)); - } - - @Override - public Response objectEncoding(byte[] key) { - return appendCommand(commandObjects.objectEncoding(key)); - } - - @Override - public Response objectIdletime(byte[] key) { - return appendCommand(commandObjects.objectIdletime(key)); - } - - @Override - public Response objectFreq(byte[] key) { - return appendCommand(commandObjects.objectFreq(key)); - } - - @Override - public Response migrate(String host, int port, byte[] key, int timeout) { - return appendCommand(commandObjects.migrate(host, port, key, timeout)); - } - - @Override - public Response migrate(String host, int port, int timeout, MigrateParams params, byte[]... keys) { - return appendCommand(commandObjects.migrate(host, port, timeout, params, keys)); - } - - @Override - public Response> keys(byte[] pattern) { - return appendCommand(commandObjects.keys(pattern)); - } - - @Override - public Response> scan(byte[] cursor) { - return appendCommand(commandObjects.scan(cursor)); - } - - @Override - public Response> scan(byte[] cursor, ScanParams params) { - return appendCommand(commandObjects.scan(cursor, params)); - } - - @Override - public Response> scan(byte[] cursor, ScanParams params, byte[] type) { - return appendCommand(commandObjects.scan(cursor, params, type)); - } - - @Override - public Response randomBinaryKey() { - return appendCommand(commandObjects.randomBinaryKey()); - } - - @Override - public Response rpush(byte[] key, byte[]... args) { - return appendCommand(commandObjects.rpush(key, args)); - } - - @Override - public Response lpush(byte[] key, byte[]... args) { - return appendCommand(commandObjects.lpush(key, args)); - } - - @Override - public Response llen(byte[] key) { - return appendCommand(commandObjects.llen(key)); - } - - @Override - public Response> lrange(byte[] key, long start, long stop) { - return appendCommand(commandObjects.lrange(key, start, stop)); - } - - @Override - public Response ltrim(byte[] key, long start, long stop) { - return appendCommand(commandObjects.ltrim(key, start, stop)); - } - - @Override - public Response lindex(byte[] key, long index) { - return appendCommand(commandObjects.lindex(key, index)); - } - - @Override - public Response lset(byte[] key, long index, byte[] value) { - return appendCommand(commandObjects.lset(key, index, value)); - } - - @Override - public Response lrem(byte[] key, long count, byte[] value) { - return appendCommand(commandObjects.lrem(key, count, value)); - } - - @Override - public Response lpop(byte[] key) { - return appendCommand(commandObjects.lpop(key)); - } - - @Override - public Response> lpop(byte[] key, int count) { - return appendCommand(commandObjects.lpop(key, count)); - } - - @Override - public Response lpos(byte[] key, byte[] element) { - return appendCommand(commandObjects.lpos(key, element)); - } - - @Override - public Response lpos(byte[] key, byte[] element, LPosParams params) { - return appendCommand(commandObjects.lpos(key, element, params)); - } - - @Override - public Response> lpos(byte[] key, byte[] element, LPosParams params, long count) { - return appendCommand(commandObjects.lpos(key, element, params, count)); - } - - @Override - public Response rpop(byte[] key) { - return appendCommand(commandObjects.rpop(key)); - } - - @Override - public Response> rpop(byte[] key, int count) { - return appendCommand(commandObjects.rpop(key, count)); - } - - @Override - public Response linsert(byte[] key, ListPosition where, byte[] pivot, byte[] value) { - return appendCommand(commandObjects.linsert(key, where, pivot, value)); - } - - @Override - public Response lpushx(byte[] key, byte[]... args) { - return appendCommand(commandObjects.lpushx(key, args)); - } - - @Override - public Response rpushx(byte[] key, byte[]... args) { - return appendCommand(commandObjects.rpushx(key, args)); - } - - @Override - public Response> blpop(int timeout, byte[]... keys) { - return appendCommand(commandObjects.blpop(timeout, keys)); - } - - @Override - public Response> blpop(double timeout, byte[]... keys) { - return appendCommand(commandObjects.blpop(timeout, keys)); - } - - @Override - public Response> brpop(int timeout, byte[]... keys) { - return appendCommand(commandObjects.brpop(timeout, keys)); - } - - @Override - public Response> brpop(double timeout, byte[]... keys) { - return appendCommand(commandObjects.brpop(timeout, keys)); - } - - @Override - public Response rpoplpush(byte[] srckey, byte[] dstkey) { - return appendCommand(commandObjects.rpoplpush(srckey, dstkey)); - } - - @Override - public Response brpoplpush(byte[] source, byte[] destination, int timeout) { - return appendCommand(commandObjects.brpoplpush(source, destination, timeout)); - } - - @Override - public Response lmove(byte[] srcKey, byte[] dstKey, ListDirection from, ListDirection to) { - return appendCommand(commandObjects.lmove(srcKey, dstKey, from, to)); - } - - @Override - public Response blmove(byte[] srcKey, byte[] dstKey, ListDirection from, ListDirection to, double timeout) { - return appendCommand(commandObjects.blmove(srcKey, dstKey, from, to, timeout)); - } - - @Override - public Response>> lmpop(ListDirection direction, byte[]... keys) { - return appendCommand(commandObjects.lmpop(direction, keys)); - } - - @Override - public Response>> lmpop(ListDirection direction, int count, byte[]... keys) { - return appendCommand(commandObjects.lmpop(direction, count, keys)); - } - - @Override - public Response>> blmpop(long timeout, ListDirection direction, byte[]... keys) { - return appendCommand(commandObjects.blmpop(timeout, direction, keys)); - } - - @Override - public Response>> blmpop(long timeout, ListDirection direction, int count, byte[]... keys) { - return appendCommand(commandObjects.blmpop(timeout, direction, count, keys)); - } - - public Response publish(byte[] channel, byte[] message) { - return appendCommand(commandObjects.publish(channel, message)); - } - - public Response strAlgoLCSStrings(byte[] strA, byte[] strB, StrAlgoLCSParams params) { - return appendCommand(commandObjects.strAlgoLCSStrings(strA, strB, params)); - } - - @Override - public Response waitReplicas(byte[] sampleKey, int replicas, long timeout) { - return appendCommand(commandObjects.waitReplicas(sampleKey, replicas, timeout)); - } - - @Override - public Response eval(byte[] script, byte[] sampleKey) { - return appendCommand(commandObjects.eval(script, sampleKey)); - } - - @Override - public Response evalsha(byte[] sha1, byte[] sampleKey) { - return appendCommand(commandObjects.evalsha(sha1, sampleKey)); - } - - @Override - public Response> scriptExists(byte[] sampleKey, byte[]... sha1s) { - return appendCommand(commandObjects.scriptExists(sampleKey, sha1s)); - } - - @Override - public Response scriptLoad(byte[] script, byte[] sampleKey) { - return appendCommand(commandObjects.scriptLoad(script, sampleKey)); - } - - @Override - public Response scriptFlush(byte[] sampleKey) { - return appendCommand(commandObjects.scriptFlush(sampleKey)); - } - - @Override - public Response scriptFlush(byte[] sampleKey, FlushMode flushMode) { - return appendCommand(commandObjects.scriptFlush(sampleKey, flushMode)); - } - - @Override - public Response scriptKill(byte[] sampleKey) { - return appendCommand(commandObjects.scriptKill(sampleKey)); - } - - @Override - public Response eval(byte[] script) { - return appendCommand(commandObjects.eval(script)); - } - - @Override - public Response eval(byte[] script, int keyCount, byte[]... params) { - return appendCommand(commandObjects.eval(script, keyCount, params)); - } - - @Override - public Response eval(byte[] script, List keys, List args) { - return appendCommand(commandObjects.eval(script, keys, args)); - } - - @Override - public Response evalReadonly(byte[] script, List keys, List args) { - return appendCommand(commandObjects.evalReadonly(script, keys, args)); - } - - @Override - public Response evalsha(byte[] sha1) { - return appendCommand(commandObjects.evalsha(sha1)); - } - - @Override - public Response evalsha(byte[] sha1, int keyCount, byte[]... params) { - return appendCommand(commandObjects.evalsha(sha1, keyCount, params)); - } - - @Override - public Response evalsha(byte[] sha1, List keys, List args) { - return appendCommand(commandObjects.evalsha(sha1, keys, args)); - } - - @Override - public Response evalshaReadonly(byte[] sha1, List keys, List args) { - return appendCommand(commandObjects.evalshaReadonly(sha1, keys, args)); - } - - @Override - public Response sadd(byte[] key, byte[]... members) { - return appendCommand(commandObjects.sadd(key, members)); - } - - @Override - public Response> smembers(byte[] key) { - return appendCommand(commandObjects.smembers(key)); - } - - @Override - public Response srem(byte[] key, byte[]... members) { - return appendCommand(commandObjects.srem(key, members)); - } - - @Override - public Response spop(byte[] key) { - return appendCommand(commandObjects.spop(key)); - } - - @Override - public Response> spop(byte[] key, long count) { - return appendCommand(commandObjects.spop(key, count)); - } - - @Override - public Response scard(byte[] key) { - return appendCommand(commandObjects.scard(key)); - } - - @Override - public Response sismember(byte[] key, byte[] member) { - return appendCommand(commandObjects.sismember(key, member)); - } - - @Override - public Response> smismember(byte[] key, byte[]... members) { - return appendCommand(commandObjects.smismember(key, members)); - } - - @Override - public Response srandmember(byte[] key) { - return appendCommand(commandObjects.srandmember(key)); - } - - @Override - public Response> srandmember(byte[] key, int count) { - return appendCommand(commandObjects.srandmember(key, count)); - } - - @Override - public Response> sscan(byte[] key, byte[] cursor, ScanParams params) { - return appendCommand(commandObjects.sscan(key, cursor, params)); - } - - @Override - public Response> sdiff(byte[]... keys) { - return appendCommand(commandObjects.sdiff(keys)); - } - - @Override - public Response sdiffstore(byte[] dstkey, byte[]... keys) { - return appendCommand(commandObjects.sdiffstore(dstkey, keys)); - } - - @Override - public Response> sinter(byte[]... keys) { - return appendCommand(commandObjects.sinter(keys)); - } - - @Override - public Response sinterstore(byte[] dstkey, byte[]... keys) { - return appendCommand(commandObjects.sinterstore(dstkey, keys)); - } - - @Override - public Response sintercard(byte[]... keys) { - return appendCommand(commandObjects.sintercard(keys)); - } - - @Override - public Response sintercard(int limit, byte[]... keys) { - return appendCommand(commandObjects.sintercard(limit, keys)); - } - - @Override - public Response> sunion(byte[]... keys) { - return appendCommand(commandObjects.sunion(keys)); - } - - @Override - public Response sunionstore(byte[] dstkey, byte[]... keys) { - return appendCommand(commandObjects.sunionstore(dstkey, keys)); - } - - @Override - public Response smove(byte[] srckey, byte[] dstkey, byte[] member) { - return appendCommand(commandObjects.smove(srckey, dstkey, member)); - } - - @Override - public Response zadd(byte[] key, double score, byte[] member) { - return appendCommand(commandObjects.zadd(key, score, member)); - } - - @Override - public Response zadd(byte[] key, double score, byte[] member, ZAddParams params) { - return appendCommand(commandObjects.zadd(key, score, member, params)); - } - - @Override - public Response zadd(byte[] key, Map scoreMembers) { - return appendCommand(commandObjects.zadd(key, scoreMembers)); - } - - @Override - public Response zadd(byte[] key, Map scoreMembers, ZAddParams params) { - return appendCommand(commandObjects.zadd(key, scoreMembers, params)); - } - - @Override - public Response zaddIncr(byte[] key, double score, byte[] member, ZAddParams params) { - return appendCommand(commandObjects.zaddIncr(key, score, member, params)); - } - - @Override - public Response zrem(byte[] key, byte[]... members) { - return appendCommand(commandObjects.zrem(key, members)); - } - - @Override - public Response zincrby(byte[] key, double increment, byte[] member) { - return appendCommand(commandObjects.zincrby(key, increment, member)); - } - - @Override - public Response zincrby(byte[] key, double increment, byte[] member, ZIncrByParams params) { - return appendCommand(commandObjects.zincrby(key, increment, member, params)); - } - - @Override - public Response zrank(byte[] key, byte[] member) { - return appendCommand(commandObjects.zrank(key, member)); - } - - @Override - public Response zrevrank(byte[] key, byte[] member) { - return appendCommand(commandObjects.zrevrank(key, member)); - } - - @Override - public Response> zrange(byte[] key, long start, long stop) { - return appendCommand(commandObjects.zrange(key, start, stop)); - } - - @Override - public Response> zrevrange(byte[] key, long start, long stop) { - return appendCommand(commandObjects.zrevrange(key, start, stop)); - } - - @Override - public Response> zrangeWithScores(byte[] key, long start, long stop) { - return appendCommand(commandObjects.zrangeWithScores(key, start, stop)); - } - - @Override - public Response> zrevrangeWithScores(byte[] key, long start, long stop) { - return appendCommand(commandObjects.zrevrangeWithScores(key, start, stop)); - } - - @Override - public Response zrandmember(byte[] key) { - return appendCommand(commandObjects.zrandmember(key)); - } - - @Override - public Response> zrandmember(byte[] key, long count) { - return appendCommand(commandObjects.zrandmember(key, count)); - } - - @Override - public Response> zrandmemberWithScores(byte[] key, long count) { - return appendCommand(commandObjects.zrandmemberWithScores(key, count)); - } - - @Override - public Response zcard(byte[] key) { - return appendCommand(commandObjects.zcard(key)); - } - - @Override - public Response zscore(byte[] key, byte[] member) { - return appendCommand(commandObjects.zscore(key, member)); - } - - @Override - public Response> zmscore(byte[] key, byte[]... members) { - return appendCommand(commandObjects.zmscore(key, members)); - } - - @Override - public Response zpopmax(byte[] key) { - return appendCommand(commandObjects.zpopmax(key)); - } - - @Override - public Response> zpopmax(byte[] key, int count) { - return appendCommand(commandObjects.zpopmax(key, count)); - } - - @Override - public Response zpopmin(byte[] key) { - return appendCommand(commandObjects.zpopmin(key)); - } - - @Override - public Response> zpopmin(byte[] key, int count) { - return appendCommand(commandObjects.zpopmin(key, count)); - } - - @Override - public Response zcount(byte[] key, double min, double max) { - return appendCommand(commandObjects.zcount(key, min, max)); - } - - @Override - public Response zcount(byte[] key, byte[] min, byte[] max) { - return appendCommand(commandObjects.zcount(key, min, max)); - } - - @Override - public Response> zrangeByScore(byte[] key, double min, double max) { - return appendCommand(commandObjects.zrangeByScore(key, min, max)); - } - - @Override - public Response> zrangeByScore(byte[] key, byte[] min, byte[] max) { - return appendCommand(commandObjects.zrangeByScore(key, min, max)); - } - - @Override - public Response> zrevrangeByScore(byte[] key, double max, double min) { - return appendCommand(commandObjects.zrevrangeByScore(key, max, min)); - } - - @Override - public Response> zrangeByScore(byte[] key, double min, double max, int offset, int count) { - return appendCommand(commandObjects.zrangeByScore(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByScore(byte[] key, byte[] max, byte[] min) { - return appendCommand(commandObjects.zrevrangeByScore(key, max, min)); - } - - @Override - public Response> zrangeByScore(byte[] key, byte[] min, byte[] max, int offset, int count) { - return appendCommand(commandObjects.zrangeByScore(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByScore(byte[] key, double max, double min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByScore(key, max, min, offset, count)); - } - - @Override - public Response> zrangeByScoreWithScores(byte[] key, double min, double max) { - return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max)); - } - - @Override - public Response> zrevrangeByScoreWithScores(byte[] key, double max, double min) { - return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min)); - } - - @Override - public Response> zrangeByScoreWithScores(byte[] key, double min, double max, int offset, int count) { - return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByScore(byte[] key, byte[] max, byte[] min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByScore(key, max, min, offset, count)); - } - - @Override - public Response> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max) { - return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max)); - } - - @Override - public Response> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min) { - return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min)); - } - - @Override - public Response> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max, int offset, int count) { - return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByScoreWithScores(byte[] key, double max, double min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min, offset, count)); - } - - @Override - public Response> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min, offset, count)); - } - - @Override - public Response zremrangeByRank(byte[] key, long start, long stop) { - return appendCommand(commandObjects.zremrangeByRank(key, start, stop)); - } - - @Override - public Response zremrangeByScore(byte[] key, double min, double max) { - return appendCommand(commandObjects.zremrangeByScore(key, min, max)); - } - - @Override - public Response zremrangeByScore(byte[] key, byte[] min, byte[] max) { - return appendCommand(commandObjects.zremrangeByScore(key, min, max)); - } - - @Override - public Response zlexcount(byte[] key, byte[] min, byte[] max) { - return appendCommand(commandObjects.zlexcount(key, min, max)); - } - - @Override - public Response> zrangeByLex(byte[] key, byte[] min, byte[] max) { - return appendCommand(commandObjects.zrangeByLex(key, min, max)); - } - - @Override - public Response> zrangeByLex(byte[] key, byte[] min, byte[] max, int offset, int count) { - return appendCommand(commandObjects.zrangeByLex(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByLex(byte[] key, byte[] max, byte[] min) { - return appendCommand(commandObjects.zrevrangeByLex(key, max, min)); - } - - @Override - public Response> zrevrangeByLex(byte[] key, byte[] max, byte[] min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByLex(key, max, min, offset, count)); - } - - @Override - public Response> zrange(byte[] key, ZRangeParams zRangeParams) { - return appendCommand(commandObjects.zrange(key, zRangeParams)); - } - - @Override - public Response> zrangeWithScores(byte[] key, ZRangeParams zRangeParams) { - return appendCommand(commandObjects.zrangeWithScores(key, zRangeParams)); - } - - @Override - public Response zrangestore(byte[] dest, byte[] src, ZRangeParams zRangeParams) { - return appendCommand(commandObjects.zrangestore(dest, src, zRangeParams)); - } - - @Override - public Response zremrangeByLex(byte[] key, byte[] min, byte[] max) { - return appendCommand(commandObjects.zremrangeByLex(key, min, max)); - } - - @Override - public Response> zscan(byte[] key, byte[] cursor, ScanParams params) { - return appendCommand(commandObjects.zscan(key, cursor, params)); - } - - @Override - public Response> bzpopmax(double timeout, byte[]... keys) { - return appendCommand(commandObjects.bzpopmax(timeout, keys)); - } - - @Override - public Response> bzpopmin(double timeout, byte[]... keys) { - return appendCommand(commandObjects.bzpopmin(timeout, keys)); - } - - @Override - public Response>> zmpop(SortedSetOption option, byte[]... keys) { - return appendCommand(commandObjects.zmpop(option, keys)); - } - - @Override - public Response>> zmpop(SortedSetOption option, int count, byte[]... keys) { - return appendCommand(commandObjects.zmpop(option, count, keys)); - } - - @Override - public Response>> bzmpop(long timeout, SortedSetOption option, byte[]... keys) { - return appendCommand(commandObjects.bzmpop(timeout, option, keys)); - } - - @Override - public Response>> bzmpop(long timeout, SortedSetOption option, int count, byte[]... keys) { - return appendCommand(commandObjects.bzmpop(timeout, option, count, keys)); - } - - @Override - public Response> zdiff(byte[]... keys) { - return appendCommand(commandObjects.zdiff(keys)); - } - - @Override - public Response> zdiffWithScores(byte[]... keys) { - return appendCommand(commandObjects.zdiffWithScores(keys)); - } - - @Override - public Response zdiffStore(byte[] dstkey, byte[]... keys) { - return appendCommand(commandObjects.zdiffStore(dstkey, keys)); - } - - @Override - public Response> zinter(ZParams params, byte[]... keys) { - return appendCommand(commandObjects.zinter(params, keys)); - } - - @Override - public Response> zinterWithScores(ZParams params, byte[]... keys) { - return appendCommand(commandObjects.zinterWithScores(params, keys)); - } - - @Override - public Response zinterstore(byte[] dstkey, byte[]... sets) { - return appendCommand(commandObjects.zinterstore(dstkey, sets)); - } - - @Override - public Response zinterstore(byte[] dstkey, ZParams params, byte[]... sets) { - return appendCommand(commandObjects.zinterstore(dstkey, params, sets)); - } - - @Override - public Response zintercard(byte[]... keys) { - return appendCommand(commandObjects.zintercard(keys)); - } - - @Override - public Response zintercard(long limit, byte[]... keys) { - return appendCommand(commandObjects.zintercard(limit, keys)); - } - - @Override - public Response> zunion(ZParams params, byte[]... keys) { - return appendCommand(commandObjects.zunion(params, keys)); - } - - @Override - public Response> zunionWithScores(ZParams params, byte[]... keys) { - return appendCommand(commandObjects.zunionWithScores(params, keys)); - } - - @Override - public Response zunionstore(byte[] dstkey, byte[]... sets) { - return appendCommand(commandObjects.zunionstore(dstkey, sets)); - } - - @Override - public Response zunionstore(byte[] dstkey, ZParams params, byte[]... sets) { - return appendCommand(commandObjects.zunionstore(dstkey, params, sets)); - } - - @Override - public Response xadd(byte[] key, XAddParams params, Map hash) { - return appendCommand(commandObjects.xadd(key, params, hash)); - } - - @Override - public Response xlen(byte[] key) { - return appendCommand(commandObjects.xlen(key)); - } - - @Override - public Response> xrange(byte[] key, byte[] start, byte[] end) { - return appendCommand(commandObjects.xrange(key, start, end)); - } - - @Override - public Response> xrange(byte[] key, byte[] start, byte[] end, int count) { - return appendCommand(commandObjects.xrange(key, start, end, count)); - } - - @Override - public Response> xrevrange(byte[] key, byte[] end, byte[] start) { - return appendCommand(commandObjects.xrevrange(key, end, start)); - } - - @Override - public Response> xrevrange(byte[] key, byte[] end, byte[] start, int count) { - return appendCommand(commandObjects.xrevrange(key, end, start, count)); - } - - @Override - public Response xack(byte[] key, byte[] group, byte[]... ids) { - return appendCommand(commandObjects.xack(key, group, ids)); - } - - @Override - public Response xgroupCreate(byte[] key, byte[] groupName, byte[] id, boolean makeStream) { - return appendCommand(commandObjects.xgroupCreate(key, groupName, id, makeStream)); - } - - @Override - public Response xgroupSetID(byte[] key, byte[] groupName, byte[] id) { - return appendCommand(commandObjects.xgroupSetID(key, groupName, id)); - } - - @Override - public Response xgroupDestroy(byte[] key, byte[] groupName) { - return appendCommand(commandObjects.xgroupDestroy(key, groupName)); - } - - @Override - public Response xgroupCreateConsumer(byte[] key, byte[] groupName, byte[] consumerName) { - return appendCommand(commandObjects.xgroupCreateConsumer(key, groupName, consumerName)); - } - - @Override - public Response xgroupDelConsumer(byte[] key, byte[] groupName, byte[] consumerName) { - return appendCommand(commandObjects.xgroupDelConsumer(key, groupName, consumerName)); - } - - @Override - public Response xdel(byte[] key, byte[]... ids) { - return appendCommand(commandObjects.xdel(key, ids)); - } - - @Override - public Response xtrim(byte[] key, long maxLen, boolean approximateLength) { - return appendCommand(commandObjects.xtrim(key, maxLen, approximateLength)); - } - - @Override - public Response xtrim(byte[] key, XTrimParams params) { - return appendCommand(commandObjects.xtrim(key, params)); - } - - @Override - public Response xpending(byte[] key, byte[] groupName) { - return appendCommand(commandObjects.xpending(key, groupName)); - } - - @Override - public Response> xpending(byte[] key, byte[] groupName, byte[] start, byte[] end, int count, byte[] consumerName) { - return appendCommand(commandObjects.xpending(key, groupName, start, end, count, consumerName)); - } - - @Override - public Response> xpending(byte[] key, byte[] groupName, XPendingParams params) { - return appendCommand(commandObjects.xpending(key, groupName, params)); - } - - @Override - public Response> xclaim(byte[] key, byte[] group, byte[] consumerName, long minIdleTime, XClaimParams params, byte[]... ids) { - return appendCommand(commandObjects.xclaim(key, group, consumerName, minIdleTime, params, ids)); - } - - @Override - public Response> xclaimJustId(byte[] key, byte[] group, byte[] consumerName, long minIdleTime, XClaimParams params, byte[]... ids) { - return appendCommand(commandObjects.xclaimJustId(key, group, consumerName, minIdleTime, params, ids)); - } - - @Override - public Response> xautoclaim(byte[] key, byte[] groupName, byte[] consumerName, long minIdleTime, byte[] start, XAutoClaimParams params) { - return appendCommand(commandObjects.xautoclaim(key, groupName, consumerName, minIdleTime, start, params)); - } - - @Override - public Response> xautoclaimJustId(byte[] key, byte[] groupName, byte[] consumerName, long minIdleTime, byte[] start, XAutoClaimParams params) { - return appendCommand(commandObjects.xautoclaimJustId(key, groupName, consumerName, minIdleTime, start, params)); - } - - @Override - public Response xinfoStream(byte[] key) { - return appendCommand(commandObjects.xinfoStream(key)); - } - - @Override - public Response xinfoStreamFull(byte[] key) { - return appendCommand(commandObjects.xinfoStreamFull(key)); - } - - @Override - public Response xinfoStreamFull(byte[] key, int count) { - return appendCommand(commandObjects.xinfoStreamFull(key, count)); - } - - @Override - @Deprecated - public Response> xinfoGroup(byte[] key) { - return appendCommand(commandObjects.xinfoGroup(key)); - } - - @Override - public Response> xinfoGroups(byte[] key) { - return appendCommand(commandObjects.xinfoGroups(key)); - } - - @Override - public Response> xinfoConsumers(byte[] key, byte[] group) { - return appendCommand(commandObjects.xinfoConsumers(key, group)); - } - - @Override - public Response> xread(XReadParams xReadParams, Map.Entry... streams) { - return appendCommand(commandObjects.xread(xReadParams, streams)); - } - - @Override - public Response> xreadGroup(byte[] groupName, byte[] consumer, XReadGroupParams xReadGroupParams, Map.Entry... streams) { - return appendCommand(commandObjects.xreadGroup(groupName, consumer, xReadGroupParams, streams)); - } - - @Override - public Response set(byte[] key, byte[] value) { - return appendCommand(commandObjects.set(key, value)); - } - - @Override - public Response set(byte[] key, byte[] value, SetParams params) { - return appendCommand(commandObjects.set(key, value, params)); - } - - @Override - public Response get(byte[] key) { - return appendCommand(commandObjects.get(key)); - } - - @Override - public Response setGet(byte[] key, byte[] value, SetParams params) { - return appendCommand(commandObjects.setGet(key, value, params)); - } - - @Override - public Response getDel(byte[] key) { - return appendCommand(commandObjects.getDel(key)); - } - - @Override - public Response getEx(byte[] key, GetExParams params) { - return appendCommand(commandObjects.getEx(key, params)); - } - - @Override - public Response setbit(byte[] key, long offset, boolean value) { - return appendCommand(commandObjects.setbit(key, offset, value)); - } - - @Override - public Response getbit(byte[] key, long offset) { - return appendCommand(commandObjects.getbit(key, offset)); - } - - @Override - public Response setrange(byte[] key, long offset, byte[] value) { - return appendCommand(commandObjects.setrange(key, offset, value)); - } - - @Override - public Response getrange(byte[] key, long startOffset, long endOffset) { - return appendCommand(commandObjects.getrange(key, startOffset, endOffset)); - } - - @Override - public Response getSet(byte[] key, byte[] value) { - return appendCommand(commandObjects.getSet(key, value)); - } - - @Override - public Response setnx(byte[] key, byte[] value) { - return appendCommand(commandObjects.setnx(key, value)); - } - - @Override - public Response setex(byte[] key, long seconds, byte[] value) { - return appendCommand(commandObjects.setex(key, seconds, value)); - } - - @Override - public Response psetex(byte[] key, long milliseconds, byte[] value) { - return appendCommand(commandObjects.psetex(key, milliseconds, value)); - } - - @Override - public Response> mget(byte[]... keys) { - return appendCommand(commandObjects.mget(keys)); - } - - @Override - public Response mset(byte[]... keysvalues) { - return appendCommand(commandObjects.mset(keysvalues)); - } - - @Override - public Response msetnx(byte[]... keysvalues) { - return appendCommand(commandObjects.msetnx(keysvalues)); - } - - @Override - public Response incr(byte[] key) { - return appendCommand(commandObjects.incr(key)); - } - - @Override - public Response incrBy(byte[] key, long increment) { - return appendCommand(commandObjects.incrBy(key, increment)); - } - - @Override - public Response incrByFloat(byte[] key, double increment) { - return appendCommand(commandObjects.incrByFloat(key, increment)); - } - - @Override - public Response decr(byte[] key) { - return appendCommand(commandObjects.decr(key)); - } - - @Override - public Response decrBy(byte[] key, long decrement) { - return appendCommand(commandObjects.decrBy(key, decrement)); - } - - @Override - public Response append(byte[] key, byte[] value) { - return appendCommand(commandObjects.append(key, value)); - } - - @Override - public Response substr(byte[] key, int start, int end) { - return appendCommand(commandObjects.substr(key, start, end)); - } - - @Override - public Response strlen(byte[] key) { - return appendCommand(commandObjects.strlen(key)); - } - - @Override - public Response bitcount(byte[] key) { - return appendCommand(commandObjects.bitcount(key)); - } - - @Override - public Response bitcount(byte[] key, long start, long end) { - return appendCommand(commandObjects.bitcount(key, start, end)); - } - - @Override - public Response bitcount(byte[] key, long start, long end, BitCountOption option) { - return appendCommand(commandObjects.bitcount(key, start, end, option)); - } - - @Override - public Response bitpos(byte[] key, boolean value) { - return appendCommand(commandObjects.bitpos(key, value)); - } - - @Override - public Response bitpos(byte[] key, boolean value, BitPosParams params) { - return appendCommand(commandObjects.bitpos(key, value, params)); - } - - @Override - public Response> bitfield(byte[] key, byte[]... arguments) { - return appendCommand(commandObjects.bitfield(key, arguments)); - } - - @Override - public Response> bitfieldReadonly(byte[] key, byte[]... arguments) { - return appendCommand(commandObjects.bitfieldReadonly(key, arguments)); - } - - @Override - public Response bitop(BitOP op, byte[] destKey, byte[]... srcKeys) { - return appendCommand(commandObjects.bitop(op, destKey, srcKeys)); - } - - @Override - public Response strAlgoLCSKeys(byte[] keyA, byte[] keyB, StrAlgoLCSParams params) { - return appendCommand(commandObjects.strAlgoLCSKeys(keyA, keyB, params)); - } - - // RediSearch commands - @Override - public Response ftCreate(String indexName, IndexOptions indexOptions, Schema schema) { - return appendCommand(commandObjects.ftCreate(indexName, indexOptions, schema)); - } - - @Override - public Response ftCreate(String indexName, FTCreateParams createParams, Iterable schemaFields) { - return appendCommand(commandObjects.ftCreate(indexName, createParams, schemaFields)); - } - - @Override - public Response ftAlter(String indexName, Schema schema) { - return appendCommand(commandObjects.ftAlter(indexName, schema)); - } - - @Override - public Response ftAlter(String indexName, Iterable schemaFields) { - return appendCommand(commandObjects.ftAlter(indexName, schemaFields)); - } - - @Override - public Response ftSearch(String indexName, String query) { - return appendCommand(commandObjects.ftSearch(indexName, query)); - } - - @Override - public Response ftSearch(String indexName, String query, FTSearchParams searchParams) { - return appendCommand(commandObjects.ftSearch(indexName, query, searchParams)); - } - - @Override - public Response ftSearch(String indexName, Query query) { - return appendCommand(commandObjects.ftSearch(indexName, query)); - } - - @Override - public Response ftSearch(byte[] indexName, Query query) { - return appendCommand(commandObjects.ftSearch(indexName, query)); - } - - @Override - public Response ftExplain(String indexName, Query query) { - return appendCommand(commandObjects.ftExplain(indexName, query)); - } - - @Override - public Response> ftExplainCLI(String indexName, Query query) { - return appendCommand(commandObjects.ftExplainCLI(indexName, query)); - } - - @Override - public Response ftAggregate(String indexName, AggregationBuilder aggr) { - return appendCommand(commandObjects.ftAggregate(indexName, aggr)); - } - - @Override - public Response ftCursorRead(String indexName, long cursorId, int count) { - return appendCommand(commandObjects.ftCursorRead(indexName, cursorId, count)); - } - - @Override - public Response ftCursorDel(String indexName, long cursorId) { - return appendCommand(commandObjects.ftCursorDel(indexName, cursorId)); - } - - @Override - public Response ftDropIndex(String indexName) { - return appendCommand(commandObjects.ftDropIndex(indexName)); - } - - @Override - public Response ftDropIndexDD(String indexName) { - return appendCommand(commandObjects.ftDropIndexDD(indexName)); - } - - @Override - public Response ftSynUpdate(String indexName, String synonymGroupId, String... terms) { - return appendCommand(commandObjects.ftSynUpdate(indexName, synonymGroupId, terms)); - } - - @Override - public Response>> ftSynDump(String indexName) { - return appendCommand(commandObjects.ftSynDump(indexName)); - } - - @Override - public Response ftDictAdd(String dictionary, String... terms) { - return appendCommand(commandObjects.ftDictAdd(dictionary, terms)); - } - - @Override - public Response ftDictDel(String dictionary, String... terms) { - return appendCommand(commandObjects.ftDictDel(dictionary, terms)); - } - - @Override - public Response> ftDictDump(String dictionary) { - return appendCommand(commandObjects.ftDictDump(dictionary)); - } - - @Override - public Response ftDictAddBySampleKey(String indexName, String dictionary, String... terms) { - return appendCommand(commandObjects.ftDictAddBySampleKey(indexName, dictionary, terms)); - } - - @Override - public Response ftDictDelBySampleKey(String indexName, String dictionary, String... terms) { - return appendCommand(commandObjects.ftDictDelBySampleKey(indexName, dictionary, terms)); - } - - @Override - public Response> ftDictDumpBySampleKey(String indexName, String dictionary) { - return appendCommand(commandObjects.ftDictDumpBySampleKey(indexName, dictionary)); - } - - @Override - public Response>> ftSpellCheck(String index, String query) { - return appendCommand(commandObjects.ftSpellCheck(index, query)); - } - - @Override - public Response>> ftSpellCheck(String index, String query, FTSpellCheckParams spellCheckParams) { - return appendCommand(commandObjects.ftSpellCheck(index, query, spellCheckParams)); - } - - @Override - public Response> ftInfo(String indexName) { - return appendCommand(commandObjects.ftInfo(indexName)); - } - - @Override - public Response> ftTagVals(String indexName, String fieldName) { - return appendCommand(commandObjects.ftTagVals(indexName, fieldName)); - } - - @Override - public Response ftAliasAdd(String aliasName, String indexName) { - return appendCommand(commandObjects.ftAliasAdd(aliasName, indexName)); - } - - @Override - public Response ftAliasUpdate(String aliasName, String indexName) { - return appendCommand(commandObjects.ftAliasUpdate(aliasName, indexName)); - } - - @Override - public Response ftAliasDel(String aliasName) { - return appendCommand(commandObjects.ftAliasDel(aliasName)); - } - - @Override - public Response> ftConfigGet(String option) { - return appendCommand(commandObjects.ftConfigGet(option)); - } - - @Override - public Response> ftConfigGet(String indexName, String option) { - return appendCommand(commandObjects.ftConfigGet(indexName, option)); - } - - @Override - public Response ftConfigSet(String option, String value) { - return appendCommand(commandObjects.ftConfigSet(option, value)); - } - - @Override - public Response ftConfigSet(String indexName, String option, String value) { - return appendCommand(commandObjects.ftConfigSet(indexName, option, value)); - } - - @Override - public Response ftSugAdd(String key, String string, double score) { - return appendCommand(commandObjects.ftSugAdd(key, string, score)); - } - - @Override - public Response ftSugAddIncr(String key, String string, double score) { - return appendCommand(commandObjects.ftSugAddIncr(key, string, score)); - } - - @Override - public Response> ftSugGet(String key, String prefix) { - return appendCommand(commandObjects.ftSugGet(key, prefix)); - } - - @Override - public Response> ftSugGet(String key, String prefix, boolean fuzzy, int max) { - return appendCommand(commandObjects.ftSugGet(key, prefix, fuzzy, max)); - } - - @Override - public Response> ftSugGetWithScores(String key, String prefix) { - return appendCommand(commandObjects.ftSugGetWithScores(key, prefix)); - } - - @Override - public Response> ftSugGetWithScores(String key, String prefix, boolean fuzzy, int max) { - return appendCommand(commandObjects.ftSugGetWithScores(key, prefix, fuzzy, max)); - } - - @Override - public Response ftSugDel(String key, String string) { - return appendCommand(commandObjects.ftSugDel(key, string)); - } - - @Override - public Response ftSugLen(String key) { - return appendCommand(commandObjects.ftSugLen(key)); - } - // RediSearch commands - - // RedisJSON commands - @Override - public Response lcs(byte[] keyA, byte[] keyB, LCSParams params) { - return appendCommand(commandObjects.lcs(keyA, keyB, params)); - } - - @Override - public Response jsonSet(String key, Path2 path, Object object) { - return appendCommand(commandObjects.jsonSet(key, path, object)); - } - - @Override - public Response jsonSetWithEscape(String key, Path2 path, Object object) { - return appendCommand(commandObjects.jsonSetWithEscape(key, path, object)); - } - - @Override - public Response jsonSet(String key, Path path, Object object) { - return appendCommand(commandObjects.jsonSet(key, path, object)); - } - - @Override - public Response jsonSet(String key, Path2 path, Object object, JsonSetParams params) { - return appendCommand(commandObjects.jsonSet(key, path, object, params)); - } - - @Override - public Response jsonSetWithEscape(String key, Path2 path, Object object, JsonSetParams params) { - return appendCommand(commandObjects.jsonSetWithEscape(key, path, object, params)); - } - - @Override - public Response jsonSet(String key, Path path, Object object, JsonSetParams params) { - return appendCommand(commandObjects.jsonSet(key, path, object, params)); - } - - @Override - public Response jsonGet(String key) { - return appendCommand(commandObjects.jsonGet(key)); - } - - @Override - public Response jsonGet(String key, Class clazz) { - return appendCommand(commandObjects.jsonGet(key, clazz)); - } - - @Override - public Response jsonGet(String key, Path2... paths) { - return appendCommand(commandObjects.jsonGet(key, paths)); - } - - @Override - public Response jsonGet(String key, Path... paths) { - return appendCommand(commandObjects.jsonGet(key, paths)); - } - - @Override - public Response jsonGet(String key, Class clazz, Path... paths) { - return appendCommand(commandObjects.jsonGet(key, clazz, paths)); - } - - @Override - public Response> jsonMGet(Path2 path, String... keys) { - return appendCommand(commandObjects.jsonMGet(path, keys)); - } - - @Override - public Response> jsonMGet(Path path, Class clazz, String... keys) { - return appendCommand(commandObjects.jsonMGet(path, clazz, keys)); - } - - @Override - public Response jsonDel(String key) { - return appendCommand(commandObjects.jsonDel(key)); - } - - @Override - public Response jsonDel(String key, Path2 path) { - return appendCommand(commandObjects.jsonDel(key, path)); - } - - @Override - public Response jsonDel(String key, Path path) { - return appendCommand(commandObjects.jsonDel(key, path)); - } - - @Override - public Response jsonClear(String key) { - return appendCommand(commandObjects.jsonClear(key)); - } - - @Override - public Response jsonClear(String key, Path2 path) { - return appendCommand(commandObjects.jsonClear(key, path)); - } - - @Override - public Response jsonClear(String key, Path path) { - return appendCommand(commandObjects.jsonClear(key, path)); - } - - @Override - public Response> jsonToggle(String key, Path2 path) { - return appendCommand(commandObjects.jsonToggle(key, path)); - } - - @Override - public Response jsonToggle(String key, Path path) { - return appendCommand(commandObjects.jsonToggle(key, path)); - } - - @Override - public Response> jsonType(String key) { - return appendCommand(commandObjects.jsonType(key)); - } - - @Override - public Response>> jsonType(String key, Path2 path) { - return appendCommand(commandObjects.jsonType(key, path)); - } - - @Override - public Response> jsonType(String key, Path path) { - return appendCommand(commandObjects.jsonType(key, path)); - } - - @Override - public Response jsonStrAppend(String key, Object string) { - return appendCommand(commandObjects.jsonStrAppend(key, string)); - } - - @Override - public Response> jsonStrAppend(String key, Path2 path, Object string) { - return appendCommand(commandObjects.jsonStrAppend(key, path, string)); - } - - @Override - public Response jsonStrAppend(String key, Path path, Object string) { - return appendCommand(commandObjects.jsonStrAppend(key, path, string)); - } - - @Override - public Response jsonStrLen(String key) { - return appendCommand(commandObjects.jsonStrLen(key)); - } - - @Override - public Response> jsonStrLen(String key, Path2 path) { - return appendCommand(commandObjects.jsonStrLen(key, path)); - } - - @Override - public Response jsonStrLen(String key, Path path) { - return appendCommand(commandObjects.jsonStrLen(key, path)); - } - - @Override - public Response jsonNumIncrBy(String key, Path2 path, double value) { - return appendCommand(commandObjects.jsonNumIncrBy(key, path, value)); - } - - @Override - public Response jsonNumIncrBy(String key, Path path, double value) { - return appendCommand(commandObjects.jsonNumIncrBy(key, path, value)); - } - - @Override - public Response> jsonArrAppend(String key, Path2 path, Object... objects) { - return appendCommand(commandObjects.jsonArrAppend(key, path, objects)); - } - - @Override - public Response> jsonArrAppendWithEscape(String key, Path2 path, Object... objects) { - return appendCommand(commandObjects.jsonArrAppendWithEscape(key, path, objects)); - } - - @Override - public Response jsonArrAppend(String key, Path path, Object... objects) { - return appendCommand(commandObjects.jsonArrAppend(key, path, objects)); - } - - @Override - public Response> jsonArrIndex(String key, Path2 path, Object scalar) { - return appendCommand(commandObjects.jsonArrIndex(key, path, scalar)); - } - - @Override - public Response> jsonArrIndexWithEscape(String key, Path2 path, Object scalar) { - return appendCommand(commandObjects.jsonArrIndexWithEscape(key, path, scalar)); - } - - @Override - public Response jsonArrIndex(String key, Path path, Object scalar) { - return appendCommand(commandObjects.jsonArrIndex(key, path, scalar)); - } - - @Override - public Response> jsonArrInsert(String key, Path2 path, int index, Object... objects) { - return appendCommand(commandObjects.jsonArrInsert(key, path, index, objects)); - } - - @Override - public Response> jsonArrInsertWithEscape(String key, Path2 path, int index, Object... objects) { - return appendCommand(commandObjects.jsonArrInsertWithEscape(key, path, index, objects)); - } - - @Override - public Response jsonArrInsert(String key, Path path, int index, Object... pojos) { - return appendCommand(commandObjects.jsonArrInsert(key, path, index, pojos)); - } - - @Override - public Response jsonArrPop(String key) { - return appendCommand(commandObjects.jsonArrPop(key)); - } - - @Override - public Response jsonArrLen(String key, Path path) { - return appendCommand(commandObjects.jsonArrLen(key, path)); - } - - @Override - public Response> jsonArrTrim(String key, Path2 path, int start, int stop) { - return appendCommand(commandObjects.jsonArrTrim(key, path, start, stop)); - } - - @Override - public Response jsonArrTrim(String key, Path path, int start, int stop) { - return appendCommand(commandObjects.jsonArrTrim(key, path, start, stop)); - } - - @Override - public Response jsonArrPop(String key, Class clazz, Path path) { - return appendCommand(commandObjects.jsonArrPop(key, clazz, path)); - } - - @Override - public Response> jsonArrPop(String key, Path2 path, int index) { - return appendCommand(commandObjects.jsonArrPop(key, path, index)); - } - - @Override - public Response jsonArrPop(String key, Path path, int index) { - return appendCommand(commandObjects.jsonArrPop(key, path, index)); - } - - @Override - public Response jsonArrPop(String key, Class clazz, Path path, int index) { - return appendCommand(commandObjects.jsonArrPop(key, clazz, path, index)); - } - - @Override - public Response jsonArrLen(String key) { - return appendCommand(commandObjects.jsonArrLen(key)); - } - - @Override - public Response> jsonArrLen(String key, Path2 path) { - return appendCommand(commandObjects.jsonArrLen(key, path)); - } - - @Override - public Response jsonArrPop(String key, Class clazz) { - return appendCommand(commandObjects.jsonArrPop(key, clazz)); - } - - @Override - public Response> jsonArrPop(String key, Path2 path) { - return appendCommand(commandObjects.jsonArrPop(key, path)); - } - - @Override - public Response jsonArrPop(String key, Path path) { - return appendCommand(commandObjects.jsonArrPop(key, path)); - } - // RedisJSON commands - - // RedisTimeSeries commands - @Override - public Response tsCreate(String key) { - return appendCommand(commandObjects.tsCreate(key)); - } - - @Override - public Response tsCreate(String key, TSCreateParams createParams) { - return appendCommand(commandObjects.tsCreate(key, createParams)); - } - - @Override - public Response tsDel(String key, long fromTimestamp, long toTimestamp) { - return appendCommand(commandObjects.tsDel(key, fromTimestamp, toTimestamp)); - } - - @Override - public Response tsAlter(String key, TSAlterParams alterParams) { - return appendCommand(commandObjects.tsAlter(key, alterParams)); - } - - @Override - public Response tsAdd(String key, double value) { - return appendCommand(commandObjects.tsAdd(key, value)); - } - - @Override - public Response tsAdd(String key, long timestamp, double value) { - return appendCommand(commandObjects.tsAdd(key, timestamp, value)); - } - - @Override - public Response tsAdd(String key, long timestamp, double value, TSCreateParams createParams) { - return appendCommand(commandObjects.tsAdd(key, timestamp, value, createParams)); - } - - @Override - public Response> tsMAdd(Map.Entry... entries) { - return appendCommand(commandObjects.tsMAdd(entries)); - } - - @Override - public Response tsIncrBy(String key, double value) { - return appendCommand(commandObjects.tsIncrBy(key, value)); - } - - @Override - public Response tsIncrBy(String key, double value, long timestamp) { - return appendCommand(commandObjects.tsIncrBy(key, value, timestamp)); - } - - @Override - public Response tsDecrBy(String key, double value) { - return appendCommand(commandObjects.tsDecrBy(key, value)); - } - - @Override - public Response tsDecrBy(String key, double value, long timestamp) { - return appendCommand(commandObjects.tsDecrBy(key, value, timestamp)); - } - - @Override - public Response> tsRange(String key, long fromTimestamp, long toTimestamp) { - return appendCommand(commandObjects.tsRange(key, fromTimestamp, toTimestamp)); - } - - @Override - public Response> tsRange(String key, TSRangeParams rangeParams) { - return appendCommand(commandObjects.tsRange(key, rangeParams)); - } - - @Override - public Response> tsRevRange(String key, long fromTimestamp, long toTimestamp) { - return appendCommand(commandObjects.tsRevRange(key, fromTimestamp, toTimestamp)); - } - - @Override - public Response> tsRevRange(String key, TSRangeParams rangeParams) { - return appendCommand(commandObjects.tsRevRange(key, rangeParams)); - } - - @Override - public Response> tsMRange(long fromTimestamp, long toTimestamp, String... filters) { - return appendCommand(commandObjects.tsMRange(fromTimestamp, toTimestamp, filters)); - } - - @Override - public Response> tsMRange(TSMRangeParams multiRangeParams) { - return appendCommand(commandObjects.tsMRange(multiRangeParams)); - } - - @Override - public Response> tsMRevRange(long fromTimestamp, long toTimestamp, String... filters) { - return appendCommand(commandObjects.tsMRevRange(fromTimestamp, toTimestamp, filters)); - } - - @Override - public Response> tsMRevRange(TSMRangeParams multiRangeParams) { - return appendCommand(commandObjects.tsMRevRange(multiRangeParams)); - } - - @Override - public Response tsGet(String key) { - return appendCommand(commandObjects.tsGet(key)); - } - - @Override - public Response tsGet(String key, TSGetParams getParams) { - return appendCommand(commandObjects.tsGet(key, getParams)); - } - - @Override - public Response>> tsMGet(TSMGetParams multiGetParams, String... filters) { - return appendCommand(commandObjects.tsMGet(multiGetParams, filters)); - } - - @Override - public Response tsCreateRule(String sourceKey, String destKey, AggregationType aggregationType, long timeBucket) { - return appendCommand(commandObjects.tsCreateRule(sourceKey, destKey, aggregationType, timeBucket)); - } - - @Override - public Response tsCreateRule(String sourceKey, String destKey, AggregationType aggregationType, long bucketDuration, long alignTimestamp) { - return appendCommand(commandObjects.tsCreateRule(sourceKey, destKey, aggregationType, bucketDuration, alignTimestamp)); - } - - @Override - public Response tsDeleteRule(String sourceKey, String destKey) { - return appendCommand(commandObjects.tsDeleteRule(sourceKey, destKey)); - } - - @Override - public Response> tsQueryIndex(String... filters) { - return appendCommand(commandObjects.tsQueryIndex(filters)); - } - // RedisTimeSeries commands - - // RedisBloom commands - @Override - public Response bfReserve(String key, double errorRate, long capacity) { - return appendCommand(commandObjects.bfReserve(key, errorRate, capacity)); - } - - @Override - public Response bfReserve(String key, double errorRate, long capacity, BFReserveParams reserveParams) { - return appendCommand(commandObjects.bfReserve(key, errorRate, capacity, reserveParams)); - } - - @Override - public Response bfAdd(String key, String item) { - return appendCommand(commandObjects.bfAdd(key, item)); - } - - @Override - public Response> bfMAdd(String key, String... items) { - return appendCommand(commandObjects.bfMAdd(key, items)); - } - - @Override - public Response> bfInsert(String key, String... items) { - return appendCommand(commandObjects.bfInsert(key, items)); - } - - @Override - public Response> bfInsert(String key, BFInsertParams insertParams, String... items) { - return appendCommand(commandObjects.bfInsert(key, insertParams, items)); - } - - @Override - public Response bfExists(String key, String item) { - return appendCommand(commandObjects.bfExists(key, item)); - } - - @Override - public Response> bfMExists(String key, String... items) { - return appendCommand(commandObjects.bfMExists(key, items)); - } - - @Override - public Response> bfScanDump(String key, long iterator) { - return appendCommand(commandObjects.bfScanDump(key, iterator)); - } - - @Override - public Response bfLoadChunk(String key, long iterator, byte[] data) { - return appendCommand(commandObjects.bfLoadChunk(key, iterator, data)); - } - - @Override - public Response bfCard(String key) { - return appendCommand(commandObjects.bfCard(key)); - } - - @Override - public Response> bfInfo(String key) { - return appendCommand(commandObjects.bfInfo(key)); - } - - @Override - public Response cfReserve(String key, long capacity) { - return appendCommand(commandObjects.cfReserve(key, capacity)); - } - - @Override - public Response cfReserve(String key, long capacity, CFReserveParams reserveParams) { - return appendCommand(commandObjects.cfReserve(key, capacity, reserveParams)); - } - - @Override - public Response cfAdd(String key, String item) { - return appendCommand(commandObjects.cfAdd(key, item)); - } - - @Override - public Response cfAddNx(String key, String item) { - return appendCommand(commandObjects.cfAddNx(key, item)); - } - - @Override - public Response> cfInsert(String key, String... items) { - return appendCommand(commandObjects.cfInsert(key, items)); - } - - @Override - public Response> cfInsert(String key, CFInsertParams insertParams, String... items) { - return appendCommand(commandObjects.cfInsert(key, insertParams, items)); - } - - @Override - public Response> cfInsertNx(String key, String... items) { - return appendCommand(commandObjects.cfInsertNx(key, items)); - } - - @Override - public Response> cfInsertNx(String key, CFInsertParams insertParams, String... items) { - return appendCommand(commandObjects.cfInsertNx(key, insertParams, items)); - } - - @Override - public Response cfExists(String key, String item) { - return appendCommand(commandObjects.cfExists(key, item)); - } - - @Override - public Response cfDel(String key, String item) { - return appendCommand(commandObjects.cfDel(key, item)); - } - - @Override - public Response cfCount(String key, String item) { - return appendCommand(commandObjects.cfCount(key, item)); - } - - @Override - public Response> cfScanDump(String key, long iterator) { - return appendCommand(commandObjects.cfScanDump(key, iterator)); - } - - @Override - public Response cfLoadChunk(String key, long iterator, byte[] data) { - return appendCommand(commandObjects.cfLoadChunk(key, iterator, data)); - } - - @Override - public Response> cfInfo(String key) { - return appendCommand(commandObjects.cfInfo(key)); - } - - @Override - public Response cmsInitByDim(String key, long width, long depth) { - return appendCommand(commandObjects.cmsInitByDim(key, width, depth)); - } - - @Override - public Response cmsInitByProb(String key, double error, double probability) { - return appendCommand(commandObjects.cmsInitByProb(key, error, probability)); - } - - @Override - public Response> cmsIncrBy(String key, Map itemIncrements) { - return appendCommand(commandObjects.cmsIncrBy(key, itemIncrements)); - } - - @Override - public Response> cmsQuery(String key, String... items) { - return appendCommand(commandObjects.cmsQuery(key, items)); - } - - @Override - public Response cmsMerge(String destKey, String... keys) { - return appendCommand(commandObjects.cmsMerge(destKey, keys)); - } - - @Override - public Response cmsMerge(String destKey, Map keysAndWeights) { - return appendCommand(commandObjects.cmsMerge(destKey, keysAndWeights)); - } - - @Override - public Response> cmsInfo(String key) { - return appendCommand(commandObjects.cmsInfo(key)); - } - - @Override - public Response topkReserve(String key, long topk) { - return appendCommand(commandObjects.topkReserve(key, topk)); - } - - @Override - public Response topkReserve(String key, long topk, long width, long depth, double decay) { - return appendCommand(commandObjects.topkReserve(key, topk, width, depth, decay)); - } - - @Override - public Response> topkAdd(String key, String... items) { - return appendCommand(commandObjects.topkAdd(key, items)); - } - - @Override - public Response> topkIncrBy(String key, Map itemIncrements) { - return appendCommand(commandObjects.topkIncrBy(key, itemIncrements)); - } - - @Override - public Response> topkQuery(String key, String... items) { - return appendCommand(commandObjects.topkQuery(key, items)); - } - - @Override - public Response> topkCount(String key, String... items) { - return appendCommand(commandObjects.topkCount(key, items)); - } - - @Override - public Response> topkList(String key) { - return appendCommand(commandObjects.topkList(key)); - } - - @Override - public Response> topkInfo(String key) { - return appendCommand(commandObjects.topkInfo(key)); - } - - @Override - public Response tdigestCreate(String key) { - return appendCommand(commandObjects.tdigestCreate(key)); - } - - @Override - public Response tdigestCreate(String key, int compression) { - return appendCommand(commandObjects.tdigestCreate(key, compression)); - } - - @Override - public Response tdigestReset(String key) { - return appendCommand(commandObjects.tdigestReset(key)); - } - - @Override - public Response tdigestMerge(String destinationKey, String... sourceKeys) { - return appendCommand(commandObjects.tdigestMerge(destinationKey, sourceKeys)); - } - - @Override - public Response tdigestMerge(TDigestMergeParams mergeParams, String destinationKey, String... sourceKeys) { - return appendCommand(commandObjects.tdigestMerge(mergeParams, destinationKey, sourceKeys)); - } - - @Override - public Response> tdigestInfo(String key) { - return appendCommand(commandObjects.tdigestInfo(key)); - } - - @Override - public Response tdigestAdd(String key, double... values) { - return appendCommand(commandObjects.tdigestAdd(key, values)); - } - - @Override - public Response> tdigestCDF(String key, double... values) { - return appendCommand(commandObjects.tdigestCDF(key, values)); - } - - @Override - public Response> tdigestQuantile(String key, double... quantiles) { - return appendCommand(commandObjects.tdigestQuantile(key, quantiles)); - } - - @Override - public Response tdigestMin(String key) { - return appendCommand(commandObjects.tdigestMin(key)); - } - - @Override - public Response tdigestMax(String key) { - return appendCommand(commandObjects.tdigestMax(key)); - } - - @Override - public Response tdigestTrimmedMean(String key, double lowCutQuantile, double highCutQuantile) { - return appendCommand(commandObjects.tdigestTrimmedMean(key, lowCutQuantile, highCutQuantile)); - } - - @Override - public Response> tdigestRank(String key, double... values) { - return appendCommand(commandObjects.tdigestRank(key, values)); - } - - @Override - public Response> tdigestRevRank(String key, double... values) { - return appendCommand(commandObjects.tdigestRevRank(key, values)); - } - - @Override - public Response> tdigestByRank(String key, long... ranks) { - return appendCommand(commandObjects.tdigestByRank(key, ranks)); - } - - @Override - public Response> tdigestByRevRank(String key, long... ranks) { - return appendCommand(commandObjects.tdigestByRevRank(key, ranks)); - } - // RedisBloom commands - - // RedisGraph commands - @Override - public Response graphQuery(String name, String query) { - return appendCommand(graphCommandObjects.graphQuery(name, query)); - } - - @Override - public Response graphReadonlyQuery(String name, String query) { - return appendCommand(graphCommandObjects.graphReadonlyQuery(name, query)); - } - - @Override - public Response graphQuery(String name, String query, long timeout) { - return appendCommand(graphCommandObjects.graphQuery(name, query, timeout)); - } - - @Override - public Response graphReadonlyQuery(String name, String query, long timeout) { - return appendCommand(graphCommandObjects.graphReadonlyQuery(name, query, timeout)); - } - - @Override - public Response graphQuery(String name, String query, Map params) { - return appendCommand(graphCommandObjects.graphQuery(name, query, params)); - } - - @Override - public Response graphReadonlyQuery(String name, String query, Map params) { - return appendCommand(graphCommandObjects.graphReadonlyQuery(name, query, params)); - } - - @Override - public Response graphQuery(String name, String query, Map params, long timeout) { - return appendCommand(graphCommandObjects.graphQuery(name, query, params, timeout)); - } - - @Override - public Response graphReadonlyQuery(String name, String query, Map params, long timeout) { - return appendCommand(graphCommandObjects.graphReadonlyQuery(name, query, params, timeout)); - } - - @Override - public Response graphDelete(String name) { - return appendCommand(graphCommandObjects.graphDelete(name)); - } - - @Override - public Response> graphProfile(String graphName, String query) { - return appendCommand(commandObjects.graphProfile(graphName, query)); - } - // RedisGraph commands - - public Response waitReplicas(int replicas, long timeout) { - return appendCommand(commandObjects.waitReplicas(replicas, timeout)); - } - - public Response> time() { - return appendCommand(new CommandObject<>(commandObjects.commandArguments(Protocol.Command.TIME), BuilderFactory.STRING_LIST)); - } - - @Override - public Response select(final int index) { - return appendCommand(new CommandObject<>(commandObjects.commandArguments(Protocol.Command.SELECT), BuilderFactory.STRING)); - } - - @Override - public Response dbSize() { - return appendCommand(new CommandObject<>(commandObjects.commandArguments(Protocol.Command.DBSIZE), BuilderFactory.LONG)); - } - - @Override - public Response swapDB(final int index1, final int index2) { - return appendCommand(new CommandObject<>(commandObjects.commandArguments(Protocol.Command.SWAPDB) - .add(index1).add(index2), BuilderFactory.STRING)); - } - - @Override - public Response move(String key, int dbIndex) { - return appendCommand(new CommandObject<>(commandObjects.commandArguments(Protocol.Command.MOVE) - .key(key).add(dbIndex), BuilderFactory.LONG)); - } - - @Override - public Response move(final byte[] key, final int dbIndex) { - return appendCommand(new CommandObject<>(commandObjects.commandArguments(Protocol.Command.MOVE) - .key(key).add(dbIndex), BuilderFactory.LONG)); - } - - @Override - public Response copy(String srcKey, String dstKey, int db, boolean replace) { - return appendCommand(commandObjects.copy(srcKey, dstKey, db, replace)); - } - - @Override - public Response copy(byte[] srcKey, byte[] dstKey, int db, boolean replace) { - return appendCommand(commandObjects.copy(srcKey, dstKey, db, replace)); - } - - @Override - public Response migrate(String host, int port, byte[] key, int destinationDB, int timeout) { - return appendCommand(commandObjects.migrate(host, port, key, destinationDB, timeout)); - } - - @Override - public Response migrate(String host, int port, String key, int destinationDB, int timeout) { - return appendCommand(commandObjects.migrate(host, port, key, destinationDB, timeout)); - } - - @Override - public Response migrate(String host, int port, int destinationDB, int timeout, MigrateParams params, byte[]... keys) { - return appendCommand(commandObjects.migrate(host, port, destinationDB, timeout, params, keys)); + public Response migrate(String host, int port, int destinationDB, int timeout, MigrateParams params, byte[]... keys) { + return appendCommand(commandObjects.migrate(host, port, destinationDB, timeout, params, keys)); } @Override public Response migrate(String host, int port, int destinationDB, int timeout, MigrateParams params, String... keys) { return appendCommand(commandObjects.migrate(host, port, destinationDB, timeout, params, keys)); } - - public Response sendCommand(ProtocolCommand cmd, String... args) { - return sendCommand(new CommandArguments(cmd).addObjects((Object[]) args)); - } - - public Response sendCommand(ProtocolCommand cmd, byte[]... args) { - return sendCommand(new CommandArguments(cmd).addObjects((Object[]) args)); - } - - public Response sendCommand(CommandArguments args) { - return executeCommand(new CommandObject<>(args, BuilderFactory.RAW_OBJECT)); - } - - public Response executeCommand(CommandObject command) { - return appendCommand(command); - } } diff --git a/src/main/java/redis/clients/jedis/PipelineBase.java b/src/main/java/redis/clients/jedis/PipelineBase.java new file mode 100644 index 0000000000..2f4d246929 --- /dev/null +++ b/src/main/java/redis/clients/jedis/PipelineBase.java @@ -0,0 +1,12 @@ +package redis.clients.jedis; + +/** + * @deprecated Use {@link AbstractPipeline}. + */ +@Deprecated +public abstract class PipelineBase extends AbstractPipeline { + + protected PipelineBase(CommandObjects commandObjects) { + super(commandObjects); + } +} diff --git a/src/main/java/redis/clients/jedis/PipeliningBase.java b/src/main/java/redis/clients/jedis/PipeliningBase.java new file mode 100644 index 0000000000..5c6cd45f07 --- /dev/null +++ b/src/main/java/redis/clients/jedis/PipeliningBase.java @@ -0,0 +1,4242 @@ +package redis.clients.jedis; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.json.JSONArray; + +import redis.clients.jedis.args.*; +import redis.clients.jedis.bloom.*; +import redis.clients.jedis.commands.PipelineBinaryCommands; +import redis.clients.jedis.commands.PipelineCommands; +import redis.clients.jedis.commands.ProtocolCommand; +import redis.clients.jedis.commands.RedisModulePipelineCommands; +import redis.clients.jedis.graph.GraphCommandObjects; +import redis.clients.jedis.graph.ResultSet; +import redis.clients.jedis.json.JsonSetParams; +import redis.clients.jedis.json.Path; +import redis.clients.jedis.json.Path2; +import redis.clients.jedis.json.JsonObjectMapper; +import redis.clients.jedis.params.*; +import redis.clients.jedis.resps.*; +import redis.clients.jedis.search.*; +import redis.clients.jedis.search.aggr.AggregationBuilder; +import redis.clients.jedis.search.aggr.AggregationResult; +import redis.clients.jedis.search.schemafields.SchemaField; +import redis.clients.jedis.timeseries.*; +import redis.clients.jedis.util.KeyValue; + +public abstract class PipeliningBase + implements PipelineCommands, PipelineBinaryCommands, RedisModulePipelineCommands { + + protected final CommandObjects commandObjects; + private GraphCommandObjects graphCommandObjects; + + protected PipeliningBase(CommandObjects commandObjects) { + this.commandObjects = commandObjects; + } + + /** + * Sub-classes must call this method, if graph commands are going to be used. + */ + protected final void setGraphCommands(GraphCommandObjects graphCommandObjects) { + this.graphCommandObjects = graphCommandObjects; + } + + protected abstract Response appendCommand(CommandObject commandObject); + + @Override + public Response exists(String key) { + return appendCommand(commandObjects.exists(key)); + } + + @Override + public Response exists(String... keys) { + return appendCommand(commandObjects.exists(keys)); + } + + @Override + public Response persist(String key) { + return appendCommand(commandObjects.persist(key)); + } + + @Override + public Response type(String key) { + return appendCommand(commandObjects.type(key)); + } + + @Override + public Response dump(String key) { + return appendCommand(commandObjects.dump(key)); + } + + @Override + public Response restore(String key, long ttl, byte[] serializedValue) { + return appendCommand(commandObjects.restore(key, ttl, serializedValue)); + } + + @Override + public Response restore(String key, long ttl, byte[] serializedValue, RestoreParams params) { + return appendCommand(commandObjects.restore(key, ttl, serializedValue, params)); + } + + @Override + public Response expire(String key, long seconds) { + return appendCommand(commandObjects.expire(key, seconds)); + } + + @Override + public Response expire(String key, long seconds, ExpiryOption expiryOption) { + return appendCommand(commandObjects.expire(key, seconds, expiryOption)); + } + + @Override + public Response pexpire(String key, long milliseconds) { + return appendCommand(commandObjects.pexpire(key, milliseconds)); + } + + @Override + public Response pexpire(String key, long milliseconds, ExpiryOption expiryOption) { + return appendCommand(commandObjects.pexpire(key, milliseconds, expiryOption)); + } + + @Override + public Response expireTime(String key) { + return appendCommand(commandObjects.expireTime(key)); + } + + @Override + public Response pexpireTime(String key) { + return appendCommand(commandObjects.pexpireTime(key)); + } + + @Override + public Response expireAt(String key, long unixTime) { + return appendCommand(commandObjects.expireAt(key, unixTime)); + } + + @Override + public Response expireAt(String key, long unixTime, ExpiryOption expiryOption) { + return appendCommand(commandObjects.expireAt(key, unixTime, expiryOption)); + } + + @Override + public Response pexpireAt(String key, long millisecondsTimestamp) { + return appendCommand(commandObjects.pexpireAt(key, millisecondsTimestamp)); + } + + @Override + public Response pexpireAt(String key, long millisecondsTimestamp, ExpiryOption expiryOption) { + return appendCommand(commandObjects.pexpireAt(key, millisecondsTimestamp, expiryOption)); + } + + @Override + public Response ttl(String key) { + return appendCommand(commandObjects.ttl(key)); + } + + @Override + public Response pttl(String key) { + return appendCommand(commandObjects.pttl(key)); + } + + @Override + public Response touch(String key) { + return appendCommand(commandObjects.touch(key)); + } + + @Override + public Response touch(String... keys) { + return appendCommand(commandObjects.touch(keys)); + } + + @Override + public Response> sort(String key) { + return appendCommand(commandObjects.sort(key)); + } + + @Override + public Response sort(String key, String dstKey) { + return appendCommand(commandObjects.sort(key, dstKey)); + } + + @Override + public Response> sort(String key, SortingParams sortingParams) { + return appendCommand(commandObjects.sort(key, sortingParams)); + } + + @Override + public Response sort(String key, SortingParams sortingParams, String dstKey) { + return appendCommand(commandObjects.sort(key, sortingParams, dstKey)); + } + + @Override + public Response> sortReadonly(String key, SortingParams sortingParams) { + return appendCommand(commandObjects.sortReadonly(key, sortingParams)); + } + + @Override + public Response del(String key) { + return appendCommand(commandObjects.del(key)); + } + + @Override + public Response del(String... keys) { + return appendCommand(commandObjects.del(keys)); + } + + @Override + public Response unlink(String key) { + return appendCommand(commandObjects.unlink(key)); + } + + @Override + public Response unlink(String... keys) { + return appendCommand(commandObjects.unlink(keys)); + } + + @Override + public Response copy(String srcKey, String dstKey, boolean replace) { + return appendCommand(commandObjects.copy(srcKey, dstKey, replace)); + } + + @Override + public Response rename(String oldkey, String newkey) { + return appendCommand(commandObjects.rename(oldkey, newkey)); + } + + @Override + public Response renamenx(String oldkey, String newkey) { + return appendCommand(commandObjects.renamenx(oldkey, newkey)); + } + + @Override + public Response memoryUsage(String key) { + return appendCommand(commandObjects.memoryUsage(key)); + } + + @Override + public Response memoryUsage(String key, int samples) { + return appendCommand(commandObjects.memoryUsage(key, samples)); + } + + @Override + public Response objectRefcount(String key) { + return appendCommand(commandObjects.objectRefcount(key)); + } + + @Override + public Response objectEncoding(String key) { + return appendCommand(commandObjects.objectEncoding(key)); + } + + @Override + public Response objectIdletime(String key) { + return appendCommand(commandObjects.objectIdletime(key)); + } + + @Override + public Response objectFreq(String key) { + return appendCommand(commandObjects.objectFreq(key)); + } + + @Override + public Response migrate(String host, int port, String key, int timeout) { + return appendCommand(commandObjects.migrate(host, port, key, timeout)); + } + + @Override + public Response migrate(String host, int port, int timeout, MigrateParams params, String... keys) { + return appendCommand(commandObjects.migrate(host, port, timeout, params, keys)); + } + + @Override + public Response> keys(String pattern) { + return appendCommand(commandObjects.keys(pattern)); + } + + @Override + public Response> scan(String cursor) { + return appendCommand(commandObjects.scan(cursor)); + } + + @Override + public Response> scan(String cursor, ScanParams params) { + return appendCommand(commandObjects.scan(cursor, params)); + } + + @Override + public Response> scan(String cursor, ScanParams params, String type) { + return appendCommand(commandObjects.scan(cursor, params, type)); + } + + @Override + public Response randomKey() { + return appendCommand(commandObjects.randomKey()); + } + + @Override + public Response get(String key) { + return appendCommand(commandObjects.get(key)); + } + + @Override + public Response setGet(String key, String value, SetParams params) { + return appendCommand(commandObjects.setGet(key, value, params)); + } + + @Override + public Response getDel(String key) { + return appendCommand(commandObjects.getDel(key)); + } + + @Override + public Response getEx(String key, GetExParams params) { + return appendCommand(commandObjects.getEx(key, params)); + } + + @Override + public Response setbit(String key, long offset, boolean value) { + return appendCommand(commandObjects.setbit(key, offset, value)); + } + + @Override + public Response getbit(String key, long offset) { + return appendCommand(commandObjects.getbit(key, offset)); + } + + @Override + public Response setrange(String key, long offset, String value) { + return appendCommand(commandObjects.setrange(key, offset, value)); + } + + @Override + public Response getrange(String key, long startOffset, long endOffset) { + return appendCommand(commandObjects.getrange(key, startOffset, endOffset)); + } + + @Override + public Response getSet(String key, String value) { + return appendCommand(commandObjects.getSet(key, value)); + } + + @Override + public Response setnx(String key, String value) { + return appendCommand(commandObjects.setnx(key, value)); + } + + @Override + public Response setex(String key, long seconds, String value) { + return appendCommand(commandObjects.setex(key, seconds, value)); + } + + @Override + public Response psetex(String key, long milliseconds, String value) { + return appendCommand(commandObjects.psetex(key, milliseconds, value)); + } + + @Override + public Response> mget(String... keys) { + return appendCommand(commandObjects.mget(keys)); + } + + @Override + public Response mset(String... keysvalues) { + return appendCommand(commandObjects.mset(keysvalues)); + } + + @Override + public Response msetnx(String... keysvalues) { + return appendCommand(commandObjects.msetnx(keysvalues)); + } + + @Override + public Response incr(String key) { + return appendCommand(commandObjects.incr(key)); + } + + @Override + public Response incrBy(String key, long increment) { + return appendCommand(commandObjects.incrBy(key, increment)); + } + + @Override + public Response incrByFloat(String key, double increment) { + return appendCommand(commandObjects.incrByFloat(key, increment)); + } + + @Override + public Response decr(String key) { + return appendCommand(commandObjects.decr(key)); + } + + @Override + public Response decrBy(String key, long decrement) { + return appendCommand(commandObjects.decrBy(key, decrement)); + } + + @Override + public Response append(String key, String value) { + return appendCommand(commandObjects.append(key, value)); + } + + @Override + public Response substr(String key, int start, int end) { + return appendCommand(commandObjects.substr(key, start, end)); + } + + @Override + public Response strlen(String key) { + return appendCommand(commandObjects.strlen(key)); + } + + @Override + public Response bitcount(String key) { + return appendCommand(commandObjects.bitcount(key)); + } + + @Override + public Response bitcount(String key, long start, long end) { + return appendCommand(commandObjects.bitcount(key, start, end)); + } + + @Override + public Response bitcount(String key, long start, long end, BitCountOption option) { + return appendCommand(commandObjects.bitcount(key, start, end, option)); + } + + @Override + public Response bitpos(String key, boolean value) { + return appendCommand(commandObjects.bitpos(key, value)); + } + + @Override + public Response bitpos(String key, boolean value, BitPosParams params) { + return appendCommand(commandObjects.bitpos(key, value, params)); + } + + @Override + public Response> bitfield(String key, String... arguments) { + return appendCommand(commandObjects.bitfield(key, arguments)); + } + + @Override + public Response> bitfieldReadonly(String key, String... arguments) { + return appendCommand(commandObjects.bitfieldReadonly(key, arguments)); + } + + @Override + public Response bitop(BitOP op, String destKey, String... srcKeys) { + return appendCommand(commandObjects.bitop(op, destKey, srcKeys)); + } + + @Override + public Response lcs(String keyA, String keyB, LCSParams params) { + return appendCommand(commandObjects.lcs(keyA, keyB, params)); + } + + @Override + public Response set(String key, String value) { + return appendCommand(commandObjects.set(key, value)); + } + + @Override + public Response set(String key, String value, SetParams params) { + return appendCommand(commandObjects.set(key, value, params)); + } + + @Override + public Response rpush(String key, String... string) { + return appendCommand(commandObjects.rpush(key, string)); + + } + + @Override + public Response lpush(String key, String... string) { + return appendCommand(commandObjects.lpush(key, string)); + } + + @Override + public Response llen(String key) { + return appendCommand(commandObjects.llen(key)); + } + + @Override + public Response> lrange(String key, long start, long stop) { + return appendCommand(commandObjects.lrange(key, start, stop)); + } + + @Override + public Response ltrim(String key, long start, long stop) { + return appendCommand(commandObjects.ltrim(key, start, stop)); + } + + @Override + public Response lindex(String key, long index) { + return appendCommand(commandObjects.lindex(key, index)); + } + + @Override + public Response lset(String key, long index, String value) { + return appendCommand(commandObjects.lset(key, index, value)); + } + + @Override + public Response lrem(String key, long count, String value) { + return appendCommand(commandObjects.lrem(key, count, value)); + } + + @Override + public Response lpop(String key) { + return appendCommand(commandObjects.lpop(key)); + } + + @Override + public Response> lpop(String key, int count) { + return appendCommand(commandObjects.lpop(key, count)); + } + + @Override + public Response lpos(String key, String element) { + return appendCommand(commandObjects.lpos(key, element)); + } + + @Override + public Response lpos(String key, String element, LPosParams params) { + return appendCommand(commandObjects.lpos(key, element, params)); + } + + @Override + public Response> lpos(String key, String element, LPosParams params, long count) { + return appendCommand(commandObjects.lpos(key, element, params, count)); + } + + @Override + public Response rpop(String key) { + return appendCommand(commandObjects.rpop(key)); + } + + @Override + public Response> rpop(String key, int count) { + return appendCommand(commandObjects.rpop(key, count)); + } + + @Override + public Response linsert(String key, ListPosition where, String pivot, String value) { + return appendCommand(commandObjects.linsert(key, where, pivot, value)); + } + + @Override + public Response lpushx(String key, String... strings) { + return appendCommand(commandObjects.lpushx(key, strings)); + } + + @Override + public Response rpushx(String key, String... strings) { + return appendCommand(commandObjects.rpushx(key, strings)); + } + + @Override + public Response> blpop(int timeout, String key) { + return appendCommand(commandObjects.blpop(timeout, key)); + } + + @Override + public Response> blpop(double timeout, String key) { + return appendCommand(commandObjects.blpop(timeout, key)); + } + + @Override + public Response> brpop(int timeout, String key) { + return appendCommand(commandObjects.brpop(timeout, key)); + } + + @Override + public Response> brpop(double timeout, String key) { + return appendCommand(commandObjects.brpop(timeout, key)); + } + + @Override + public Response> blpop(int timeout, String... keys) { + return appendCommand(commandObjects.blpop(timeout, keys)); + } + + @Override + public Response> blpop(double timeout, String... keys) { + return appendCommand(commandObjects.blpop(timeout, keys)); + } + + @Override + public Response> brpop(int timeout, String... keys) { + return appendCommand(commandObjects.brpop(timeout, keys)); + } + + @Override + public Response> brpop(double timeout, String... keys) { + return appendCommand(commandObjects.brpop(timeout, keys)); + } + + @Override + public Response rpoplpush(String srcKey, String dstKey) { + return appendCommand(commandObjects.rpoplpush(srcKey, dstKey)); + } + + @Override + public Response brpoplpush(String source, String destination, int timeout) { + return appendCommand(commandObjects.brpoplpush(source, destination, timeout)); + } + + @Override + public Response lmove(String srcKey, String dstKey, ListDirection from, ListDirection to) { + return appendCommand(commandObjects.lmove(srcKey, dstKey, from, to)); + } + + @Override + public Response blmove(String srcKey, String dstKey, ListDirection from, ListDirection to, double timeout) { + return appendCommand(commandObjects.blmove(srcKey, dstKey, from, to, timeout)); + } + + @Override + public Response>> lmpop(ListDirection direction, String... keys) { + return appendCommand(commandObjects.lmpop(direction, keys)); + } + + @Override + public Response>> lmpop(ListDirection direction, int count, String... keys) { + return appendCommand(commandObjects.lmpop(direction, count, keys)); + } + + @Override + public Response>> blmpop(double timeout, ListDirection direction, String... keys) { + return appendCommand(commandObjects.blmpop(timeout, direction, keys)); + } + + @Override + public Response>> blmpop(double timeout, ListDirection direction, int count, String... keys) { + return appendCommand(commandObjects.blmpop(timeout, direction, count, keys)); + } + + @Override + public Response hset(String key, String field, String value) { + return appendCommand(commandObjects.hset(key, field, value)); + } + + @Override + public Response hset(String key, Map hash) { + return appendCommand(commandObjects.hset(key, hash)); + } + + @Override + public Response hget(String key, String field) { + return appendCommand(commandObjects.hget(key, field)); + } + + @Override + public Response hsetnx(String key, String field, String value) { + return appendCommand(commandObjects.hsetnx(key, field, value)); + } + + @Override + public Response hmset(String key, Map hash) { + return appendCommand(commandObjects.hmset(key, hash)); + } + + @Override + public Response> hmget(String key, String... fields) { + return appendCommand(commandObjects.hmget(key, fields)); + } + + @Override + public Response hincrBy(String key, String field, long value) { + return appendCommand(commandObjects.hincrBy(key, field, value)); + } + + @Override + public Response hincrByFloat(String key, String field, double value) { + return appendCommand(commandObjects.hincrByFloat(key, field, value)); + } + + @Override + public Response hexists(String key, String field) { + return appendCommand(commandObjects.hexists(key, field)); + } + + @Override + public Response hdel(String key, String... field) { + return appendCommand(commandObjects.hdel(key, field)); + } + + @Override + public Response hlen(String key) { + return appendCommand(commandObjects.hlen(key)); + } + + @Override + public Response> hkeys(String key) { + return appendCommand(commandObjects.hkeys(key)); + } + + @Override + public Response> hvals(String key) { + return appendCommand(commandObjects.hvals(key)); + } + + @Override + public Response> hgetAll(String key) { + return appendCommand(commandObjects.hgetAll(key)); + } + + @Override + public Response hrandfield(String key) { + return appendCommand(commandObjects.hrandfield(key)); + } + + @Override + public Response> hrandfield(String key, long count) { + return appendCommand(commandObjects.hrandfield(key, count)); + } + + @Override + public Response>> hrandfieldWithValues(String key, long count) { + return appendCommand(commandObjects.hrandfieldWithValues(key, count)); + } + + @Override + public Response>> hscan(String key, String cursor, ScanParams params) { + return appendCommand(commandObjects.hscan(key, cursor, params)); + } + + @Override + public Response hstrlen(String key, String field) { + return appendCommand(commandObjects.hstrlen(key, field)); + } + + @Override + public Response sadd(String key, String... members) { + return appendCommand(commandObjects.sadd(key, members)); + } + + @Override + public Response> smembers(String key) { + return appendCommand(commandObjects.smembers(key)); + } + + @Override + public Response srem(String key, String... members) { + return appendCommand(commandObjects.srem(key, members)); + } + + @Override + public Response spop(String key) { + return appendCommand(commandObjects.spop(key)); + } + + @Override + public Response> spop(String key, long count) { + return appendCommand(commandObjects.spop(key, count)); + } + + @Override + public Response scard(String key) { + return appendCommand(commandObjects.scard(key)); + } + + @Override + public Response sismember(String key, String member) { + return appendCommand(commandObjects.sismember(key, member)); + } + + @Override + public Response> smismember(String key, String... members) { + return appendCommand(commandObjects.smismember(key, members)); + } + + @Override + public Response srandmember(String key) { + return appendCommand(commandObjects.srandmember(key)); + } + + @Override + public Response> srandmember(String key, int count) { + return appendCommand(commandObjects.srandmember(key, count)); + } + + @Override + public Response> sscan(String key, String cursor, ScanParams params) { + return appendCommand(commandObjects.sscan(key, cursor, params)); + } + + @Override + public Response> sdiff(String... keys) { + return appendCommand(commandObjects.sdiff(keys)); + } + + @Override + public Response sdiffStore(String dstKey, String... keys) { + return appendCommand(commandObjects.sdiffstore(dstKey, keys)); + } + + @Override + public Response> sinter(String... keys) { + return appendCommand(commandObjects.sinter(keys)); + } + + @Override + public Response sinterstore(String dstKey, String... keys) { + return appendCommand(commandObjects.sinterstore(dstKey, keys)); + } + + @Override + public Response sintercard(String... keys) { + return appendCommand(commandObjects.sintercard(keys)); + } + + @Override + public Response sintercard(int limit, String... keys) { + return appendCommand(commandObjects.sintercard(limit, keys)); + } + + @Override + public Response> sunion(String... keys) { + return appendCommand(commandObjects.sunion(keys)); + } + + @Override + public Response sunionstore(String dstKey, String... keys) { + return appendCommand(commandObjects.sunionstore(dstKey, keys)); + } + + @Override + public Response smove(String srcKey, String dstKey, String member) { + return appendCommand(commandObjects.smove(srcKey, dstKey, member)); + } + + @Override + public Response zadd(String key, double score, String member) { + return appendCommand(commandObjects.zadd(key, score, member)); + } + + @Override + public Response zadd(String key, double score, String member, ZAddParams params) { + return appendCommand(commandObjects.zadd(key, score, member, params)); + } + + @Override + public Response zadd(String key, Map scoreMembers) { + return appendCommand(commandObjects.zadd(key, scoreMembers)); + } + + @Override + public Response zadd(String key, Map scoreMembers, ZAddParams params) { + return appendCommand(commandObjects.zadd(key, scoreMembers, params)); + } + + @Override + public Response zaddIncr(String key, double score, String member, ZAddParams params) { + return appendCommand(commandObjects.zaddIncr(key, score, member, params)); + } + + @Override + public Response zrem(String key, String... members) { + return appendCommand(commandObjects.zrem(key, members)); + } + + @Override + public Response zincrby(String key, double increment, String member) { + return appendCommand(commandObjects.zincrby(key, increment, member)); + } + + @Override + public Response zincrby(String key, double increment, String member, ZIncrByParams params) { + return appendCommand(commandObjects.zincrby(key, increment, member, params)); + } + + @Override + public Response zrank(String key, String member) { + return appendCommand(commandObjects.zrank(key, member)); + } + + @Override + public Response zrevrank(String key, String member) { + return appendCommand(commandObjects.zrevrank(key, member)); + } + + @Override + public Response> zrankWithScore(String key, String member) { + return appendCommand(commandObjects.zrankWithScore(key, member)); + } + + @Override + public Response> zrevrankWithScore(String key, String member) { + return appendCommand(commandObjects.zrevrankWithScore(key, member)); + } + + @Override + public Response> zrange(String key, long start, long stop) { + return appendCommand(commandObjects.zrange(key, start, stop)); + } + + @Override + public Response> zrevrange(String key, long start, long stop) { + return appendCommand(commandObjects.zrevrange(key, start, stop)); + } + + @Override + public Response> zrangeWithScores(String key, long start, long stop) { + return appendCommand(commandObjects.zrangeWithScores(key, start, stop)); + } + + @Override + public Response> zrevrangeWithScores(String key, long start, long stop) { + return appendCommand(commandObjects.zrevrangeWithScores(key, start, stop)); + } + + @Override + public Response zrandmember(String key) { + return appendCommand(commandObjects.zrandmember(key)); + } + + @Override + public Response> zrandmember(String key, long count) { + return appendCommand(commandObjects.zrandmember(key, count)); + } + + @Override + public Response> zrandmemberWithScores(String key, long count) { + return appendCommand(commandObjects.zrandmemberWithScores(key, count)); + } + + @Override + public Response zcard(String key) { + return appendCommand(commandObjects.zcard(key)); + } + + @Override + public Response zscore(String key, String member) { + return appendCommand(commandObjects.zscore(key, member)); + } + + @Override + public Response> zmscore(String key, String... members) { + return appendCommand(commandObjects.zmscore(key, members)); + } + + @Override + public Response zpopmax(String key) { + return appendCommand(commandObjects.zpopmax(key)); + } + + @Override + public Response> zpopmax(String key, int count) { + return appendCommand(commandObjects.zpopmax(key, count)); + } + + @Override + public Response zpopmin(String key) { + return appendCommand(commandObjects.zpopmin(key)); + } + + @Override + public Response> zpopmin(String key, int count) { + return appendCommand(commandObjects.zpopmin(key, count)); + } + + @Override + public Response zcount(String key, double min, double max) { + return appendCommand(commandObjects.zcount(key, min, max)); + } + + @Override + public Response zcount(String key, String min, String max) { + return appendCommand(commandObjects.zcount(key, min, max)); + } + + @Override + public Response> zrangeByScore(String key, double min, double max) { + return appendCommand(commandObjects.zrangeByScore(key, min, max)); + } + + @Override + public Response> zrangeByScore(String key, String min, String max) { + return appendCommand(commandObjects.zrangeByScore(key, min, max)); + } + + @Override + public Response> zrevrangeByScore(String key, double max, double min) { + return appendCommand(commandObjects.zrevrangeByScore(key, max, min)); + } + + @Override + public Response> zrangeByScore(String key, double min, double max, int offset, int count) { + return appendCommand(commandObjects.zrangeByScore(key, min, max, offset, count)); + } + + @Override + public Response> zrevrangeByScore(String key, String max, String min) { + return appendCommand(commandObjects.zrevrangeByScore(key, max, min)); + } + + @Override + public Response> zrangeByScore(String key, String min, String max, int offset, int count) { + return appendCommand(commandObjects.zrangeByScore(key, min, max, offset, count)); + } + + @Override + public Response> zrevrangeByScore(String key, double max, double min, int offset, int count) { + return appendCommand(commandObjects.zrevrangeByScore(key, max, min, offset, count)); + } + + @Override + public Response> zrangeByScoreWithScores(String key, double min, double max) { + return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max)); + } + + @Override + public Response> zrevrangeByScoreWithScores(String key, double max, double min) { + return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min)); + } + + @Override + public Response> zrangeByScoreWithScores(String key, double min, double max, int offset, int count) { + return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max, offset, count)); + } + + @Override + public Response> zrevrangeByScore(String key, String max, String min, int offset, int count) { + return appendCommand(commandObjects.zrevrangeByScore(key, max, min, offset, count)); + } + + @Override + public Response> zrangeByScoreWithScores(String key, String min, String max) { + return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max)); + } + + @Override + public Response> zrevrangeByScoreWithScores(String key, String max, String min) { + return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min)); + } + + @Override + public Response> zrangeByScoreWithScores(String key, String min, String max, int offset, int count) { + return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max, offset, count)); + } + + @Override + public Response> zrevrangeByScoreWithScores(String key, double max, double min, int offset, int count) { + return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min, offset, count)); + } + + @Override + public Response> zrevrangeByScoreWithScores(String key, String max, String min, int offset, int count) { + return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min, offset, count)); + } + + @Override + public Response> zrange(String key, ZRangeParams zRangeParams) { + return appendCommand(commandObjects.zrange(key, zRangeParams)); + } + + @Override + public Response> zrangeWithScores(String key, ZRangeParams zRangeParams) { + return appendCommand(commandObjects.zrangeWithScores(key, zRangeParams)); + } + + @Override + public Response zrangestore(String dest, String src, ZRangeParams zRangeParams) { + return appendCommand(commandObjects.zrangestore(dest, src, zRangeParams)); + } + + @Override + public Response zremrangeByRank(String key, long start, long stop) { + return appendCommand(commandObjects.zremrangeByRank(key, start, stop)); + } + + @Override + public Response zremrangeByScore(String key, double min, double max) { + return appendCommand(commandObjects.zremrangeByScore(key, min, max)); + } + + @Override + public Response zremrangeByScore(String key, String min, String max) { + return appendCommand(commandObjects.zremrangeByScore(key, min, max)); + } + + @Override + public Response zlexcount(String key, String min, String max) { + return appendCommand(commandObjects.zlexcount(key, min, max)); + } + + @Override + public Response> zrangeByLex(String key, String min, String max) { + return appendCommand(commandObjects.zrangeByLex(key, min, max)); + } + + @Override + public Response> zrangeByLex(String key, String min, String max, int offset, int count) { + return appendCommand(commandObjects.zrangeByLex(key, min, max, offset, count)); + } + + @Override + public Response> zrevrangeByLex(String key, String max, String min) { + return appendCommand(commandObjects.zrevrangeByLex(key, max, min)); + } + + @Override + public Response> zrevrangeByLex(String key, String max, String min, int offset, int count) { + return appendCommand(commandObjects.zrevrangeByLex(key, max, min, offset, count)); + } + + @Override + public Response zremrangeByLex(String key, String min, String max) { + return appendCommand(commandObjects.zremrangeByLex(key, min, max)); + } + + @Override + public Response> zscan(String key, String cursor, ScanParams params) { + return appendCommand(commandObjects.zscan(key, cursor, params)); + } + + @Override + public Response> bzpopmax(double timeout, String... keys) { + return appendCommand(commandObjects.bzpopmax(timeout, keys)); + } + + @Override + public Response> bzpopmin(double timeout, String... keys) { + return appendCommand(commandObjects.bzpopmin(timeout, keys)); + } + + @Override + public Response>> zmpop(SortedSetOption option, String... keys) { + return appendCommand(commandObjects.zmpop(option, keys)); + } + + @Override + public Response>> zmpop(SortedSetOption option, int count, String... keys) { + return appendCommand(commandObjects.zmpop(option, count, keys)); + } + + @Override + public Response>> bzmpop(double timeout, SortedSetOption option, String... keys) { + return appendCommand(commandObjects.bzmpop(timeout, option, keys)); + } + + @Override + public Response>> bzmpop(double timeout, SortedSetOption option, int count, String... keys) { + return appendCommand(commandObjects.bzmpop(timeout, option, count, keys)); + } + + @Override + public Response> zdiff(String... keys) { + return appendCommand(commandObjects.zdiff(keys)); + } + + @Override + public Response> zdiffWithScores(String... keys) { + return appendCommand(commandObjects.zdiffWithScores(keys)); + } + + @Override + @Deprecated + public Response zdiffStore(String dstKey, String... keys) { + return appendCommand(commandObjects.zdiffStore(dstKey, keys)); + } + + @Override + public Response zdiffstore(String dstKey, String... keys) { + return appendCommand(commandObjects.zdiffstore(dstKey, keys)); + } + + @Override + public Response zinterstore(String dstKey, String... sets) { + return appendCommand(commandObjects.zinterstore(dstKey, sets)); + } + + @Override + public Response zinterstore(String dstKey, ZParams params, String... sets) { + return appendCommand(commandObjects.zinterstore(dstKey, params, sets)); + } + + @Override + public Response> zinter(ZParams params, String... keys) { + return appendCommand(commandObjects.zinter(params, keys)); + } + + @Override + public Response> zinterWithScores(ZParams params, String... keys) { + return appendCommand(commandObjects.zinterWithScores(params, keys)); + } + + @Override + public Response zintercard(String... keys) { + return appendCommand(commandObjects.zintercard(keys)); + } + + @Override + public Response zintercard(long limit, String... keys) { + return appendCommand(commandObjects.zintercard(limit, keys)); + } + + @Override + public Response> zunion(ZParams params, String... keys) { + return appendCommand(commandObjects.zunion(params, keys)); + } + + @Override + public Response> zunionWithScores(ZParams params, String... keys) { + return appendCommand(commandObjects.zunionWithScores(params, keys)); + } + + @Override + public Response zunionstore(String dstKey, String... sets) { + return appendCommand(commandObjects.zunionstore(dstKey, sets)); + } + + @Override + public Response zunionstore(String dstKey, ZParams params, String... sets) { + return appendCommand(commandObjects.zunionstore(dstKey, params, sets)); + } + + @Override + public Response geoadd(String key, double longitude, double latitude, String member) { + return appendCommand(commandObjects.geoadd(key, longitude, latitude, member)); + } + + @Override + public Response geoadd(String key, Map memberCoordinateMap) { + return appendCommand(commandObjects.geoadd(key, memberCoordinateMap)); + } + + @Override + public Response geoadd(String key, GeoAddParams params, Map memberCoordinateMap) { + return appendCommand(commandObjects.geoadd(key, params, memberCoordinateMap)); + } + + @Override + public Response geodist(String key, String member1, String member2) { + return appendCommand(commandObjects.geodist(key, member1, member2)); + } + + @Override + public Response geodist(String key, String member1, String member2, GeoUnit unit) { + return appendCommand(commandObjects.geodist(key, member1, member2, unit)); + } + + @Override + public Response> geohash(String key, String... members) { + return appendCommand(commandObjects.geohash(key, members)); + } + + @Override + public Response> geopos(String key, String... members) { + return appendCommand(commandObjects.geopos(key, members)); + } + + @Override + public Response> georadius(String key, double longitude, double latitude, double radius, GeoUnit unit) { + return appendCommand(commandObjects.georadius(key, longitude, latitude, radius, unit)); + } + + @Override + public Response> georadiusReadonly(String key, double longitude, double latitude, double radius, GeoUnit unit) { + return appendCommand(commandObjects.georadiusReadonly(key, longitude, latitude, radius, unit)); + } + + @Override + public Response> georadius(String key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param) { + return appendCommand(commandObjects.georadius(key, longitude, latitude, radius, unit, param)); + } + + @Override + public Response> georadiusReadonly(String key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param) { + return appendCommand(commandObjects.georadiusReadonly(key, longitude, latitude, radius, unit, param)); + } + + @Override + public Response> georadiusByMember(String key, String member, double radius, GeoUnit unit) { + return appendCommand(commandObjects.georadiusByMember(key, member, radius, unit)); + } + + @Override + public Response> georadiusByMemberReadonly(String key, String member, double radius, GeoUnit unit) { + return appendCommand(commandObjects.georadiusByMemberReadonly(key, member, radius, unit)); + } + + @Override + public Response> georadiusByMember(String key, String member, double radius, GeoUnit unit, GeoRadiusParam param) { + return appendCommand(commandObjects.georadiusByMember(key, member, radius, unit, param)); + } + + @Override + public Response> georadiusByMemberReadonly(String key, String member, double radius, GeoUnit unit, GeoRadiusParam param) { + return appendCommand(commandObjects.georadiusByMemberReadonly(key, member, radius, unit, param)); + } + + @Override + public Response georadiusStore(String key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param, GeoRadiusStoreParam storeParam) { + return appendCommand(commandObjects.georadiusStore(key, longitude, latitude, radius, unit, param, storeParam)); + } + + @Override + public Response georadiusByMemberStore(String key, String member, double radius, GeoUnit unit, GeoRadiusParam param, GeoRadiusStoreParam storeParam) { + return appendCommand(commandObjects.georadiusByMemberStore(key, member, radius, unit, param, storeParam)); + } + + @Override + public Response> geosearch(String key, String member, double radius, GeoUnit unit) { + return appendCommand(commandObjects.geosearch(key, member, radius, unit)); + } + + @Override + public Response> geosearch(String key, GeoCoordinate coord, double radius, GeoUnit unit) { + return appendCommand(commandObjects.geosearch(key, coord, radius, unit)); + } + + @Override + public Response> geosearch(String key, String member, double width, double height, GeoUnit unit) { + return appendCommand(commandObjects.geosearch(key, member, width, height, unit)); + } + + @Override + public Response> geosearch(String key, GeoCoordinate coord, double width, double height, GeoUnit unit) { + return appendCommand(commandObjects.geosearch(key, coord, width, height, unit)); + } + + @Override + public Response> geosearch(String key, GeoSearchParam params) { + return appendCommand(commandObjects.geosearch(key, params)); + } + + @Override + public Response geosearchStore(String dest, String src, String member, double radius, GeoUnit unit) { + return appendCommand(commandObjects.geosearchStore(dest, src, member, radius, unit)); + } + + @Override + public Response geosearchStore(String dest, String src, GeoCoordinate coord, double radius, GeoUnit unit) { + return appendCommand(commandObjects.geosearchStore(dest, src, coord, radius, unit)); + } + + @Override + public Response geosearchStore(String dest, String src, String member, double width, double height, GeoUnit unit) { + return appendCommand(commandObjects.geosearchStore(dest, src, member, width, height, unit)); + } + + @Override + public Response geosearchStore(String dest, String src, GeoCoordinate coord, double width, double height, GeoUnit unit) { + return appendCommand(commandObjects.geosearchStore(dest, src, coord, width, height, unit)); + } + + @Override + public Response geosearchStore(String dest, String src, GeoSearchParam params) { + return appendCommand(commandObjects.geosearchStore(dest, src, params)); + } + + @Override + public Response geosearchStoreStoreDist(String dest, String src, GeoSearchParam params) { + return appendCommand(commandObjects.geosearchStoreStoreDist(dest, src, params)); + } + + @Override + public Response pfadd(String key, String... elements) { + return appendCommand(commandObjects.pfadd(key, elements)); + } + + @Override + public Response pfmerge(String destkey, String... sourcekeys) { + return appendCommand(commandObjects.pfmerge(destkey, sourcekeys)); + } + + @Override + public Response pfcount(String key) { + return appendCommand(commandObjects.pfcount(key)); + } + + @Override + public Response pfcount(String... keys) { + return appendCommand(commandObjects.pfcount(keys)); + } + + @Override + public Response xadd(String key, StreamEntryID id, Map hash) { + return appendCommand(commandObjects.xadd(key, id, hash)); + } + + @Override + public Response xadd(String key, XAddParams params, Map hash) { + return appendCommand(commandObjects.xadd(key, params, hash)); + } + + @Override + public Response xlen(String key) { + return appendCommand(commandObjects.xlen(key)); + } + + @Override + public Response> xrange(String key, StreamEntryID start, StreamEntryID end) { + return appendCommand(commandObjects.xrange(key, start, end)); + } + + @Override + public Response> xrange(String key, StreamEntryID start, StreamEntryID end, int count) { + return appendCommand(commandObjects.xrange(key, start, end, count)); + } + + @Override + public Response> xrevrange(String key, StreamEntryID end, StreamEntryID start) { + return appendCommand(commandObjects.xrevrange(key, end, start)); + } + + @Override + public Response> xrevrange(String key, StreamEntryID end, StreamEntryID start, int count) { + return appendCommand(commandObjects.xrevrange(key, end, start, count)); + } + + @Override + public Response> xrange(String key, String start, String end) { + return appendCommand(commandObjects.xrange(key, start, end)); + } + + @Override + public Response> xrange(String key, String start, String end, int count) { + return appendCommand(commandObjects.xrange(key, start, end, count)); + } + + @Override + public Response> xrevrange(String key, String end, String start) { + return appendCommand(commandObjects.xrevrange(key, end, start)); + } + + @Override + public Response> xrevrange(String key, String end, String start, int count) { + return appendCommand(commandObjects.xrevrange(key, end, start, count)); + } + + @Override + public Response xack(String key, String group, StreamEntryID... ids) { + return appendCommand(commandObjects.xack(key, group, ids)); + } + + @Override + public Response xgroupCreate(String key, String groupName, StreamEntryID id, boolean makeStream) { + return appendCommand(commandObjects.xgroupCreate(key, groupName, id, makeStream)); + } + + @Override + public Response xgroupSetID(String key, String groupName, StreamEntryID id) { + return appendCommand(commandObjects.xgroupSetID(key, groupName, id)); + } + + @Override + public Response xgroupDestroy(String key, String groupName) { + return appendCommand(commandObjects.xgroupDestroy(key, groupName)); + } + + @Override + public Response xgroupCreateConsumer(String key, String groupName, String consumerName) { + return appendCommand(commandObjects.xgroupCreateConsumer(key, groupName, consumerName)); + } + + @Override + public Response xgroupDelConsumer(String key, String groupName, String consumerName) { + return appendCommand(commandObjects.xgroupDelConsumer(key, groupName, consumerName)); + } + + @Override + public Response xpending(String key, String groupName) { + return appendCommand(commandObjects.xpending(key, groupName)); + } + + @Override + public Response> xpending(String key, String groupName, XPendingParams params) { + return appendCommand(commandObjects.xpending(key, groupName, params)); + } + + @Override + public Response xdel(String key, StreamEntryID... ids) { + return appendCommand(commandObjects.xdel(key, ids)); + } + + @Override + public Response xtrim(String key, long maxLen, boolean approximate) { + return appendCommand(commandObjects.xtrim(key, maxLen, approximate)); + } + + @Override + public Response xtrim(String key, XTrimParams params) { + return appendCommand(commandObjects.xtrim(key, params)); + } + + @Override + public Response> xclaim(String key, String group, String consumerName, long minIdleTime, XClaimParams params, StreamEntryID... ids) { + return appendCommand(commandObjects.xclaim(key, group, consumerName, minIdleTime, params, ids)); + } + + @Override + public Response> xclaimJustId(String key, String group, String consumerName, long minIdleTime, XClaimParams params, StreamEntryID... ids) { + return appendCommand(commandObjects.xclaimJustId(key, group, consumerName, minIdleTime, params, ids)); + } + + @Override + public Response>> xautoclaim(String key, String group, String consumerName, long minIdleTime, StreamEntryID start, XAutoClaimParams params) { + return appendCommand(commandObjects.xautoclaim(key, group, consumerName, minIdleTime, start, params)); + } + + @Override + public Response>> xautoclaimJustId(String key, String group, String consumerName, long minIdleTime, StreamEntryID start, XAutoClaimParams params) { + return appendCommand(commandObjects.xautoclaimJustId(key, group, consumerName, minIdleTime, start, params)); + } + + @Override + public Response xinfoStream(String key) { + return appendCommand(commandObjects.xinfoStream(key)); + } + + @Override + public Response xinfoStreamFull(String key) { + return appendCommand(commandObjects.xinfoStreamFull(key)); + } + + @Override + public Response xinfoStreamFull(String key, int count) { + return appendCommand(commandObjects.xinfoStreamFull(key, count)); + } + + @Override + public Response> xinfoGroups(String key) { + return appendCommand(commandObjects.xinfoGroups(key)); + } + + @Override + public Response> xinfoConsumers(String key, String group) { + return appendCommand(commandObjects.xinfoConsumers(key, group)); + } + + @Override + public Response> xinfoConsumers2(String key, String group) { + return appendCommand(commandObjects.xinfoConsumers2(key, group)); + } + + @Override + public Response>>> xread(XReadParams xReadParams, Map streams) { + return appendCommand(commandObjects.xread(xReadParams, streams)); + } + + @Override + public Response>>> xreadGroup(String groupName, String consumer, XReadGroupParams xReadGroupParams, Map streams) { + return appendCommand(commandObjects.xreadGroup(groupName, consumer, xReadGroupParams, streams)); + } + + @Override + public Response eval(String script) { + return appendCommand(commandObjects.eval(script)); + } + + @Override + public Response eval(String script, int keyCount, String... params) { + return appendCommand(commandObjects.eval(script, keyCount, params)); + } + + @Override + public Response eval(String script, List keys, List args) { + return appendCommand(commandObjects.eval(script, keys, args)); + } + + @Override + public Response evalReadonly(String script, List keys, List args) { + return appendCommand(commandObjects.evalReadonly(script, keys, args)); + } + + @Override + public Response evalsha(String sha1) { + return appendCommand(commandObjects.evalsha(sha1)); + } + + @Override + public Response evalsha(String sha1, int keyCount, String... params) { + return appendCommand(commandObjects.evalsha(sha1, keyCount, params)); + } + + @Override + public Response evalsha(String sha1, List keys, List args) { + return appendCommand(commandObjects.evalsha(sha1, keys, args)); + } + + @Override + public Response evalshaReadonly(String sha1, List keys, List args) { + return appendCommand(commandObjects.evalshaReadonly(sha1, keys, args)); + } + + @Override + public Response waitReplicas(String sampleKey, int replicas, long timeout) { + return appendCommand(commandObjects.waitReplicas(sampleKey, replicas, timeout)); + } + + @Override + public Response> waitAOF(String sampleKey, long numLocal, long numReplicas, long timeout) { + return appendCommand(commandObjects.waitAOF(sampleKey, numLocal, numReplicas, timeout)); + } + + @Override + public Response eval(String script, String sampleKey) { + return appendCommand(commandObjects.eval(script, sampleKey)); + } + + @Override + public Response evalsha(String sha1, String sampleKey) { + return appendCommand(commandObjects.evalsha(sha1, sampleKey)); + } + + @Override + public Response> scriptExists(String sampleKey, String... sha1) { + return appendCommand(commandObjects.scriptExists(sampleKey, sha1)); + } + + @Override + public Response scriptLoad(String script, String sampleKey) { + return appendCommand(commandObjects.scriptLoad(script, sampleKey)); + } + + @Override + public Response scriptFlush(String sampleKey) { + return appendCommand(commandObjects.scriptFlush(sampleKey)); + } + + @Override + public Response scriptFlush(String sampleKey, FlushMode flushMode) { + return appendCommand(commandObjects.scriptFlush(sampleKey, flushMode)); + } + + @Override + public Response scriptKill(String sampleKey) { + return appendCommand(commandObjects.scriptKill(sampleKey)); + } + + @Override + public Response fcall(byte[] name, List keys, List args) { + return appendCommand(commandObjects.fcall(name, keys, args)); + } + + @Override + public Response fcall(String name, List keys, List args) { + return appendCommand(commandObjects.fcall(name, keys, args)); + } + + @Override + public Response fcallReadonly(byte[] name, List keys, List args) { + return appendCommand(commandObjects.fcallReadonly(name, keys, args)); + } + + @Override + public Response fcallReadonly(String name, List keys, List args) { + return appendCommand(commandObjects.fcallReadonly(name, keys, args)); + } + + @Override + public Response functionDelete(byte[] libraryName) { + return appendCommand(commandObjects.functionDelete(libraryName)); + } + + @Override + public Response functionDelete(String libraryName) { + return appendCommand(commandObjects.functionDelete(libraryName)); + } + + @Override + public Response functionDump() { + return appendCommand(commandObjects.functionDump()); + } + + @Override + public Response> functionList(String libraryNamePattern) { + return appendCommand(commandObjects.functionList(libraryNamePattern)); + } + + @Override + public Response> functionList() { + return appendCommand(commandObjects.functionList()); + } + + @Override + public Response> functionListWithCode(String libraryNamePattern) { + return appendCommand(commandObjects.functionListWithCode(libraryNamePattern)); + } + + @Override + public Response> functionListWithCode() { + return appendCommand(commandObjects.functionListWithCode()); + } + + @Override + public Response> functionListBinary() { + return appendCommand(commandObjects.functionListBinary()); + } + + @Override + public Response> functionList(final byte[] libraryNamePattern) { + return appendCommand(commandObjects.functionList(libraryNamePattern)); + } + + @Override + public Response> functionListWithCodeBinary() { + return appendCommand(commandObjects.functionListWithCodeBinary()); + } + + @Override + public Response> functionListWithCode(final byte[] libraryNamePattern) { + return appendCommand(commandObjects.functionListWithCode(libraryNamePattern)); + } + + @Override + public Response functionLoad(byte[] functionCode) { + return appendCommand(commandObjects.functionLoad(functionCode)); + } + + @Override + public Response functionLoad(String functionCode) { + return appendCommand(commandObjects.functionLoad(functionCode)); + } + + @Override + public Response functionLoadReplace(byte[] functionCode) { + return appendCommand(commandObjects.functionLoadReplace(functionCode)); + } + + @Override + public Response functionLoadReplace(String functionCode) { + return appendCommand(commandObjects.functionLoadReplace(functionCode)); + } + + @Override + public Response functionRestore(byte[] serializedValue) { + return appendCommand(commandObjects.functionRestore(serializedValue)); + } + + @Override + public Response functionRestore(byte[] serializedValue, FunctionRestorePolicy policy) { + return appendCommand(commandObjects.functionRestore(serializedValue, policy)); + } + + @Override + public Response functionFlush() { + return appendCommand(commandObjects.functionFlush()); + } + + @Override + public Response functionFlush(FlushMode mode) { + return appendCommand(commandObjects.functionFlush(mode)); + } + + @Override + public Response functionKill() { + return appendCommand(commandObjects.functionKill()); + } + + @Override + public Response functionStats() { + return appendCommand(commandObjects.functionStats()); + } + + @Override + public Response functionStatsBinary() { + return appendCommand(commandObjects.functionStatsBinary()); + } + + @Override + public Response geoadd(byte[] key, double longitude, double latitude, byte[] member) { + return appendCommand(commandObjects.geoadd(key, longitude, latitude, member)); + } + + @Override + public Response geoadd(byte[] key, Map memberCoordinateMap) { + return appendCommand(commandObjects.geoadd(key, memberCoordinateMap)); + } + + @Override + public Response geoadd(byte[] key, GeoAddParams params, Map memberCoordinateMap) { + return appendCommand(commandObjects.geoadd(key, params, memberCoordinateMap)); + } + + @Override + public Response geodist(byte[] key, byte[] member1, byte[] member2) { + return appendCommand(commandObjects.geodist(key, member1, member2)); + } + + @Override + public Response geodist(byte[] key, byte[] member1, byte[] member2, GeoUnit unit) { + return appendCommand(commandObjects.geodist(key, member1, member2, unit)); + } + + @Override + public Response> geohash(byte[] key, byte[]... members) { + return appendCommand(commandObjects.geohash(key, members)); + } + + @Override + public Response> geopos(byte[] key, byte[]... members) { + return appendCommand(commandObjects.geopos(key, members)); + } + + @Override + public Response> georadius(byte[] key, double longitude, double latitude, double radius, GeoUnit unit) { + return appendCommand(commandObjects.georadius(key, longitude, latitude, radius, unit)); + } + + @Override + public Response> georadiusReadonly(byte[] key, double longitude, double latitude, double radius, GeoUnit unit) { + return appendCommand(commandObjects.georadiusReadonly(key, longitude, latitude, radius, unit)); + } + + @Override + public Response> georadius(byte[] key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param) { + return appendCommand(commandObjects.georadius(key, longitude, latitude, radius, unit, param)); + } + + @Override + public Response> georadiusReadonly(byte[] key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param) { + return appendCommand(commandObjects.georadiusReadonly(key, longitude, latitude, radius, unit, param)); + } + + @Override + public Response> georadiusByMember(byte[] key, byte[] member, double radius, GeoUnit unit) { + return appendCommand(commandObjects.georadiusByMember(key, member, radius, unit)); + } + + @Override + public Response> georadiusByMemberReadonly(byte[] key, byte[] member, double radius, GeoUnit unit) { + return appendCommand(commandObjects.georadiusByMemberReadonly(key, member, radius, unit)); + } + + @Override + public Response> georadiusByMember(byte[] key, byte[] member, double radius, GeoUnit unit, GeoRadiusParam param) { + return appendCommand(commandObjects.georadiusByMember(key, member, radius, unit, param)); + } + + @Override + public Response> georadiusByMemberReadonly(byte[] key, byte[] member, double radius, GeoUnit unit, GeoRadiusParam param) { + return appendCommand(commandObjects.georadiusByMemberReadonly(key, member, radius, unit, param)); + } + + @Override + public Response georadiusStore(byte[] key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param, GeoRadiusStoreParam storeParam) { + return appendCommand(commandObjects.georadiusStore(key, longitude, latitude, radius, unit, param, storeParam)); + } + + @Override + public Response georadiusByMemberStore(byte[] key, byte[] member, double radius, GeoUnit unit, GeoRadiusParam param, GeoRadiusStoreParam storeParam) { + return appendCommand(commandObjects.georadiusByMemberStore(key, member, radius, unit, param, storeParam)); + } + + @Override + public Response> geosearch(byte[] key, byte[] member, double radius, GeoUnit unit) { + return appendCommand(commandObjects.geosearch(key, member, radius, unit)); + } + + @Override + public Response> geosearch(byte[] key, GeoCoordinate coord, double radius, GeoUnit unit) { + return appendCommand(commandObjects.geosearch(key, coord, radius, unit)); + } + + @Override + public Response> geosearch(byte[] key, byte[] member, double width, double height, GeoUnit unit) { + return appendCommand(commandObjects.geosearch(key, member, width, height, unit)); + } + + @Override + public Response> geosearch(byte[] key, GeoCoordinate coord, double width, double height, GeoUnit unit) { + return appendCommand(commandObjects.geosearch(key, coord, width, height, unit)); + } + + @Override + public Response> geosearch(byte[] key, GeoSearchParam params) { + return appendCommand(commandObjects.geosearch(key, params)); + } + + @Override + public Response geosearchStore(byte[] dest, byte[] src, byte[] member, double radius, GeoUnit unit) { + return appendCommand(commandObjects.geosearchStore(dest, src, member, radius, unit)); + } + + @Override + public Response geosearchStore(byte[] dest, byte[] src, GeoCoordinate coord, double radius, GeoUnit unit) { + return appendCommand(commandObjects.geosearchStore(dest, src, coord, radius, unit)); + } + + @Override + public Response geosearchStore(byte[] dest, byte[] src, byte[] member, double width, double height, GeoUnit unit) { + return appendCommand(commandObjects.geosearchStore(dest, src, member, width, height, unit)); + } + + @Override + public Response geosearchStore(byte[] dest, byte[] src, GeoCoordinate coord, double width, double height, GeoUnit unit) { + return appendCommand(commandObjects.geosearchStore(dest, src, coord, width, height, unit)); + } + + @Override + public Response geosearchStore(byte[] dest, byte[] src, GeoSearchParam params) { + return appendCommand(commandObjects.geosearchStore(dest, src, params)); + } + + @Override + public Response geosearchStoreStoreDist(byte[] dest, byte[] src, GeoSearchParam params) { + return appendCommand(commandObjects.geosearchStoreStoreDist(dest, src, params)); + } + + @Override + public Response hset(byte[] key, byte[] field, byte[] value) { + return appendCommand(commandObjects.hset(key, field, value)); + } + + @Override + public Response hset(byte[] key, Map hash) { + return appendCommand(commandObjects.hset(key, hash)); + } + + @Override + public Response hget(byte[] key, byte[] field) { + return appendCommand(commandObjects.hget(key, field)); + } + + @Override + public Response hsetnx(byte[] key, byte[] field, byte[] value) { + return appendCommand(commandObjects.hsetnx(key, field, value)); + } + + @Override + public Response hmset(byte[] key, Map hash) { + return appendCommand(commandObjects.hmset(key, hash)); + } + + @Override + public Response> hmget(byte[] key, byte[]... fields) { + return appendCommand(commandObjects.hmget(key, fields)); + } + + @Override + public Response hincrBy(byte[] key, byte[] field, long value) { + return appendCommand(commandObjects.hincrBy(key, field, value)); + } + + @Override + public Response hincrByFloat(byte[] key, byte[] field, double value) { + return appendCommand(commandObjects.hincrByFloat(key, field, value)); + } + + @Override + public Response hexists(byte[] key, byte[] field) { + return appendCommand(commandObjects.hexists(key, field)); + } + + @Override + public Response hdel(byte[] key, byte[]... field) { + return appendCommand(commandObjects.hdel(key, field)); + } + + @Override + public Response hlen(byte[] key) { + return appendCommand(commandObjects.hlen(key)); + } + + @Override + public Response> hkeys(byte[] key) { + return appendCommand(commandObjects.hkeys(key)); + } + + @Override + public Response> hvals(byte[] key) { + return appendCommand(commandObjects.hvals(key)); + } + + @Override + public Response> hgetAll(byte[] key) { + return appendCommand(commandObjects.hgetAll(key)); + } + + @Override + public Response hrandfield(byte[] key) { + return appendCommand(commandObjects.hrandfield(key)); + } + + @Override + public Response> hrandfield(byte[] key, long count) { + return appendCommand(commandObjects.hrandfield(key, count)); + } + + @Override + public Response>> hrandfieldWithValues(byte[] key, long count) { + return appendCommand(commandObjects.hrandfieldWithValues(key, count)); + } + + @Override + public Response>> hscan(byte[] key, byte[] cursor, ScanParams params) { + return appendCommand(commandObjects.hscan(key, cursor, params)); + } + + @Override + public Response hstrlen(byte[] key, byte[] field) { + return appendCommand(commandObjects.hstrlen(key, field)); + } + + @Override + public Response pfadd(byte[] key, byte[]... elements) { + return appendCommand(commandObjects.pfadd(key, elements)); + } + + @Override + public Response pfmerge(byte[] destkey, byte[]... sourcekeys) { + return appendCommand(commandObjects.pfmerge(destkey, sourcekeys)); + } + + @Override + public Response pfcount(byte[] key) { + return appendCommand(commandObjects.pfcount(key)); + } + + @Override + public Response pfcount(byte[]... keys) { + return appendCommand(commandObjects.pfcount(keys)); + } + + @Override + public Response exists(byte[] key) { + return appendCommand(commandObjects.exists(key)); + } + + @Override + public Response exists(byte[]... keys) { + return appendCommand(commandObjects.exists(keys)); + } + + @Override + public Response persist(byte[] key) { + return appendCommand(commandObjects.persist(key)); + } + + @Override + public Response type(byte[] key) { + return appendCommand(commandObjects.type(key)); + } + + @Override + public Response dump(byte[] key) { + return appendCommand(commandObjects.dump(key)); + } + + @Override + public Response restore(byte[] key, long ttl, byte[] serializedValue) { + return appendCommand(commandObjects.restore(key, ttl, serializedValue)); + } + + @Override + public Response restore(byte[] key, long ttl, byte[] serializedValue, RestoreParams params) { + return appendCommand(commandObjects.restore(key, ttl, serializedValue, params)); + } + + @Override + public Response expire(byte[] key, long seconds) { + return appendCommand(commandObjects.expire(key, seconds)); + } + + @Override + public Response expire(byte[] key, long seconds, ExpiryOption expiryOption) { + return appendCommand(commandObjects.expire(key, seconds, expiryOption)); + } + + @Override + public Response pexpire(byte[] key, long milliseconds) { + return appendCommand(commandObjects.pexpire(key, milliseconds)); + } + + @Override + public Response pexpire(byte[] key, long milliseconds, ExpiryOption expiryOption) { + return appendCommand(commandObjects.pexpire(key, milliseconds, expiryOption)); + } + + @Override + public Response expireTime(byte[] key) { + return appendCommand(commandObjects.expireTime(key)); + } + + @Override + public Response pexpireTime(byte[] key) { + return appendCommand(commandObjects.pexpireTime(key)); + } + + @Override + public Response expireAt(byte[] key, long unixTime) { + return appendCommand(commandObjects.expireAt(key, unixTime)); + } + + @Override + public Response expireAt(byte[] key, long unixTime, ExpiryOption expiryOption) { + return appendCommand(commandObjects.expireAt(key, unixTime)); + } + + @Override + public Response pexpireAt(byte[] key, long millisecondsTimestamp) { + return appendCommand(commandObjects.pexpireAt(key, millisecondsTimestamp)); + } + + @Override + public Response pexpireAt(byte[] key, long millisecondsTimestamp, ExpiryOption expiryOption) { + return appendCommand(commandObjects.pexpireAt(key, millisecondsTimestamp, expiryOption)); + } + + @Override + public Response ttl(byte[] key) { + return appendCommand(commandObjects.ttl(key)); + } + + @Override + public Response pttl(byte[] key) { + return appendCommand(commandObjects.pttl(key)); + } + + @Override + public Response touch(byte[] key) { + return appendCommand(commandObjects.touch(key)); + } + + @Override + public Response touch(byte[]... keys) { + return appendCommand(commandObjects.touch(keys)); + } + + @Override + public Response> sort(byte[] key) { + return appendCommand(commandObjects.sort(key)); + } + + @Override + public Response> sort(byte[] key, SortingParams sortingParams) { + return appendCommand(commandObjects.sort(key, sortingParams)); + } + + @Override + public Response> sortReadonly(byte[] key, SortingParams sortingParams) { + return appendCommand(commandObjects.sortReadonly(key, sortingParams)); + } + + @Override + public Response del(byte[] key) { + return appendCommand(commandObjects.del(key)); + } + + @Override + public Response del(byte[]... keys) { + return appendCommand(commandObjects.del(keys)); + } + + @Override + public Response unlink(byte[] key) { + return appendCommand(commandObjects.unlink(key)); + } + + @Override + public Response unlink(byte[]... keys) { + return appendCommand(commandObjects.unlink(keys)); + } + + @Override + public Response copy(byte[] srcKey, byte[] dstKey, boolean replace) { + return appendCommand(commandObjects.copy(srcKey, dstKey, replace)); + } + + @Override + public Response rename(byte[] oldkey, byte[] newkey) { + return appendCommand(commandObjects.rename(oldkey, newkey)); + } + + @Override + public Response renamenx(byte[] oldkey, byte[] newkey) { + return appendCommand(commandObjects.renamenx(oldkey, newkey)); + } + + @Override + public Response sort(byte[] key, SortingParams sortingParams, byte[] dstkey) { + return appendCommand(commandObjects.sort(key, sortingParams, dstkey)); + } + + @Override + public Response sort(byte[] key, byte[] dstkey) { + return appendCommand(commandObjects.sort(key, dstkey)); + } + + @Override + public Response memoryUsage(byte[] key) { + return appendCommand(commandObjects.memoryUsage(key)); + } + + @Override + public Response memoryUsage(byte[] key, int samples) { + return appendCommand(commandObjects.memoryUsage(key, samples)); + } + + @Override + public Response objectRefcount(byte[] key) { + return appendCommand(commandObjects.objectRefcount(key)); + } + + @Override + public Response objectEncoding(byte[] key) { + return appendCommand(commandObjects.objectEncoding(key)); + } + + @Override + public Response objectIdletime(byte[] key) { + return appendCommand(commandObjects.objectIdletime(key)); + } + + @Override + public Response objectFreq(byte[] key) { + return appendCommand(commandObjects.objectFreq(key)); + } + + @Override + public Response migrate(String host, int port, byte[] key, int timeout) { + return appendCommand(commandObjects.migrate(host, port, key, timeout)); + } + + @Override + public Response migrate(String host, int port, int timeout, MigrateParams params, byte[]... keys) { + return appendCommand(commandObjects.migrate(host, port, timeout, params, keys)); + } + + @Override + public Response> keys(byte[] pattern) { + return appendCommand(commandObjects.keys(pattern)); + } + + @Override + public Response> scan(byte[] cursor) { + return appendCommand(commandObjects.scan(cursor)); + } + + @Override + public Response> scan(byte[] cursor, ScanParams params) { + return appendCommand(commandObjects.scan(cursor, params)); + } + + @Override + public Response> scan(byte[] cursor, ScanParams params, byte[] type) { + return appendCommand(commandObjects.scan(cursor, params, type)); + } + + @Override + public Response randomBinaryKey() { + return appendCommand(commandObjects.randomBinaryKey()); + } + + @Override + public Response rpush(byte[] key, byte[]... args) { + return appendCommand(commandObjects.rpush(key, args)); + } + + @Override + public Response lpush(byte[] key, byte[]... args) { + return appendCommand(commandObjects.lpush(key, args)); + } + + @Override + public Response llen(byte[] key) { + return appendCommand(commandObjects.llen(key)); + } + + @Override + public Response> lrange(byte[] key, long start, long stop) { + return appendCommand(commandObjects.lrange(key, start, stop)); + } + + @Override + public Response ltrim(byte[] key, long start, long stop) { + return appendCommand(commandObjects.ltrim(key, start, stop)); + } + + @Override + public Response lindex(byte[] key, long index) { + return appendCommand(commandObjects.lindex(key, index)); + } + + @Override + public Response lset(byte[] key, long index, byte[] value) { + return appendCommand(commandObjects.lset(key, index, value)); + } + + @Override + public Response lrem(byte[] key, long count, byte[] value) { + return appendCommand(commandObjects.lrem(key, count, value)); + } + + @Override + public Response lpop(byte[] key) { + return appendCommand(commandObjects.lpop(key)); + } + + @Override + public Response> lpop(byte[] key, int count) { + return appendCommand(commandObjects.lpop(key, count)); + } + + @Override + public Response lpos(byte[] key, byte[] element) { + return appendCommand(commandObjects.lpos(key, element)); + } + + @Override + public Response lpos(byte[] key, byte[] element, LPosParams params) { + return appendCommand(commandObjects.lpos(key, element, params)); + } + + @Override + public Response> lpos(byte[] key, byte[] element, LPosParams params, long count) { + return appendCommand(commandObjects.lpos(key, element, params, count)); + } + + @Override + public Response rpop(byte[] key) { + return appendCommand(commandObjects.rpop(key)); + } + + @Override + public Response> rpop(byte[] key, int count) { + return appendCommand(commandObjects.rpop(key, count)); + } + + @Override + public Response linsert(byte[] key, ListPosition where, byte[] pivot, byte[] value) { + return appendCommand(commandObjects.linsert(key, where, pivot, value)); + } + + @Override + public Response lpushx(byte[] key, byte[]... args) { + return appendCommand(commandObjects.lpushx(key, args)); + } + + @Override + public Response rpushx(byte[] key, byte[]... args) { + return appendCommand(commandObjects.rpushx(key, args)); + } + + @Override + public Response> blpop(int timeout, byte[]... keys) { + return appendCommand(commandObjects.blpop(timeout, keys)); + } + + @Override + public Response> blpop(double timeout, byte[]... keys) { + return appendCommand(commandObjects.blpop(timeout, keys)); + } + + @Override + public Response> brpop(int timeout, byte[]... keys) { + return appendCommand(commandObjects.brpop(timeout, keys)); + } + + @Override + public Response> brpop(double timeout, byte[]... keys) { + return appendCommand(commandObjects.brpop(timeout, keys)); + } + + @Override + public Response rpoplpush(byte[] srckey, byte[] dstkey) { + return appendCommand(commandObjects.rpoplpush(srckey, dstkey)); + } + + @Override + public Response brpoplpush(byte[] source, byte[] destination, int timeout) { + return appendCommand(commandObjects.brpoplpush(source, destination, timeout)); + } + + @Override + public Response lmove(byte[] srcKey, byte[] dstKey, ListDirection from, ListDirection to) { + return appendCommand(commandObjects.lmove(srcKey, dstKey, from, to)); + } + + @Override + public Response blmove(byte[] srcKey, byte[] dstKey, ListDirection from, ListDirection to, double timeout) { + return appendCommand(commandObjects.blmove(srcKey, dstKey, from, to, timeout)); + } + + @Override + public Response>> lmpop(ListDirection direction, byte[]... keys) { + return appendCommand(commandObjects.lmpop(direction, keys)); + } + + @Override + public Response>> lmpop(ListDirection direction, int count, byte[]... keys) { + return appendCommand(commandObjects.lmpop(direction, count, keys)); + } + + @Override + public Response>> blmpop(double timeout, ListDirection direction, byte[]... keys) { + return appendCommand(commandObjects.blmpop(timeout, direction, keys)); + } + + @Override + public Response>> blmpop(double timeout, ListDirection direction, int count, byte[]... keys) { + return appendCommand(commandObjects.blmpop(timeout, direction, count, keys)); + } + + @Override + public Response waitReplicas(byte[] sampleKey, int replicas, long timeout) { + return appendCommand(commandObjects.waitReplicas(sampleKey, replicas, timeout)); + } + + @Override + public Response> waitAOF(byte[] sampleKey, long numLocal, long numReplicas, long timeout) { + return appendCommand(commandObjects.waitAOF(sampleKey, numLocal, numReplicas, timeout)); + } + + @Override + public Response eval(byte[] script, byte[] sampleKey) { + return appendCommand(commandObjects.eval(script, sampleKey)); + } + + @Override + public Response evalsha(byte[] sha1, byte[] sampleKey) { + return appendCommand(commandObjects.evalsha(sha1, sampleKey)); + } + + @Override + public Response> scriptExists(byte[] sampleKey, byte[]... sha1s) { + return appendCommand(commandObjects.scriptExists(sampleKey, sha1s)); + } + + @Override + public Response scriptLoad(byte[] script, byte[] sampleKey) { + return appendCommand(commandObjects.scriptLoad(script, sampleKey)); + } + + @Override + public Response scriptFlush(byte[] sampleKey) { + return appendCommand(commandObjects.scriptFlush(sampleKey)); + } + + @Override + public Response scriptFlush(byte[] sampleKey, FlushMode flushMode) { + return appendCommand(commandObjects.scriptFlush(sampleKey, flushMode)); + } + + @Override + public Response scriptKill(byte[] sampleKey) { + return appendCommand(commandObjects.scriptKill(sampleKey)); + } + + @Override + public Response eval(byte[] script) { + return appendCommand(commandObjects.eval(script)); + } + + @Override + public Response eval(byte[] script, int keyCount, byte[]... params) { + return appendCommand(commandObjects.eval(script, keyCount, params)); + } + + @Override + public Response eval(byte[] script, List keys, List args) { + return appendCommand(commandObjects.eval(script, keys, args)); + } + + @Override + public Response evalReadonly(byte[] script, List keys, List args) { + return appendCommand(commandObjects.evalReadonly(script, keys, args)); + } + + @Override + public Response evalsha(byte[] sha1) { + return appendCommand(commandObjects.evalsha(sha1)); + } + + @Override + public Response evalsha(byte[] sha1, int keyCount, byte[]... params) { + return appendCommand(commandObjects.evalsha(sha1, keyCount, params)); + } + + @Override + public Response evalsha(byte[] sha1, List keys, List args) { + return appendCommand(commandObjects.evalsha(sha1, keys, args)); + } + + @Override + public Response evalshaReadonly(byte[] sha1, List keys, List args) { + return appendCommand(commandObjects.evalshaReadonly(sha1, keys, args)); + } + + @Override + public Response sadd(byte[] key, byte[]... members) { + return appendCommand(commandObjects.sadd(key, members)); + } + + @Override + public Response> smembers(byte[] key) { + return appendCommand(commandObjects.smembers(key)); + } + + @Override + public Response srem(byte[] key, byte[]... members) { + return appendCommand(commandObjects.srem(key, members)); + } + + @Override + public Response spop(byte[] key) { + return appendCommand(commandObjects.spop(key)); + } + + @Override + public Response> spop(byte[] key, long count) { + return appendCommand(commandObjects.spop(key, count)); + } + + @Override + public Response scard(byte[] key) { + return appendCommand(commandObjects.scard(key)); + } + + @Override + public Response sismember(byte[] key, byte[] member) { + return appendCommand(commandObjects.sismember(key, member)); + } + + @Override + public Response> smismember(byte[] key, byte[]... members) { + return appendCommand(commandObjects.smismember(key, members)); + } + + @Override + public Response srandmember(byte[] key) { + return appendCommand(commandObjects.srandmember(key)); + } + + @Override + public Response> srandmember(byte[] key, int count) { + return appendCommand(commandObjects.srandmember(key, count)); + } + + @Override + public Response> sscan(byte[] key, byte[] cursor, ScanParams params) { + return appendCommand(commandObjects.sscan(key, cursor, params)); + } + + @Override + public Response> sdiff(byte[]... keys) { + return appendCommand(commandObjects.sdiff(keys)); + } + + @Override + public Response sdiffstore(byte[] dstkey, byte[]... keys) { + return appendCommand(commandObjects.sdiffstore(dstkey, keys)); + } + + @Override + public Response> sinter(byte[]... keys) { + return appendCommand(commandObjects.sinter(keys)); + } + + @Override + public Response sinterstore(byte[] dstkey, byte[]... keys) { + return appendCommand(commandObjects.sinterstore(dstkey, keys)); + } + + @Override + public Response sintercard(byte[]... keys) { + return appendCommand(commandObjects.sintercard(keys)); + } + + @Override + public Response sintercard(int limit, byte[]... keys) { + return appendCommand(commandObjects.sintercard(limit, keys)); + } + + @Override + public Response> sunion(byte[]... keys) { + return appendCommand(commandObjects.sunion(keys)); + } + + @Override + public Response sunionstore(byte[] dstkey, byte[]... keys) { + return appendCommand(commandObjects.sunionstore(dstkey, keys)); + } + + @Override + public Response smove(byte[] srckey, byte[] dstkey, byte[] member) { + return appendCommand(commandObjects.smove(srckey, dstkey, member)); + } + + @Override + public Response zadd(byte[] key, double score, byte[] member) { + return appendCommand(commandObjects.zadd(key, score, member)); + } + + @Override + public Response zadd(byte[] key, double score, byte[] member, ZAddParams params) { + return appendCommand(commandObjects.zadd(key, score, member, params)); + } + + @Override + public Response zadd(byte[] key, Map scoreMembers) { + return appendCommand(commandObjects.zadd(key, scoreMembers)); + } + + @Override + public Response zadd(byte[] key, Map scoreMembers, ZAddParams params) { + return appendCommand(commandObjects.zadd(key, scoreMembers, params)); + } + + @Override + public Response zaddIncr(byte[] key, double score, byte[] member, ZAddParams params) { + return appendCommand(commandObjects.zaddIncr(key, score, member, params)); + } + + @Override + public Response zrem(byte[] key, byte[]... members) { + return appendCommand(commandObjects.zrem(key, members)); + } + + @Override + public Response zincrby(byte[] key, double increment, byte[] member) { + return appendCommand(commandObjects.zincrby(key, increment, member)); + } + + @Override + public Response zincrby(byte[] key, double increment, byte[] member, ZIncrByParams params) { + return appendCommand(commandObjects.zincrby(key, increment, member, params)); + } + + @Override + public Response zrank(byte[] key, byte[] member) { + return appendCommand(commandObjects.zrank(key, member)); + } + + @Override + public Response zrevrank(byte[] key, byte[] member) { + return appendCommand(commandObjects.zrevrank(key, member)); + } + + @Override + public Response> zrankWithScore(byte[] key, byte[] member) { + return appendCommand(commandObjects.zrankWithScore(key, member)); + } + + @Override + public Response> zrevrankWithScore(byte[] key, byte[] member) { + return appendCommand(commandObjects.zrevrankWithScore(key, member)); + } + + @Override + public Response> zrange(byte[] key, long start, long stop) { + return appendCommand(commandObjects.zrange(key, start, stop)); + } + + @Override + public Response> zrevrange(byte[] key, long start, long stop) { + return appendCommand(commandObjects.zrevrange(key, start, stop)); + } + + @Override + public Response> zrangeWithScores(byte[] key, long start, long stop) { + return appendCommand(commandObjects.zrangeWithScores(key, start, stop)); + } + + @Override + public Response> zrevrangeWithScores(byte[] key, long start, long stop) { + return appendCommand(commandObjects.zrevrangeWithScores(key, start, stop)); + } + + @Override + public Response zrandmember(byte[] key) { + return appendCommand(commandObjects.zrandmember(key)); + } + + @Override + public Response> zrandmember(byte[] key, long count) { + return appendCommand(commandObjects.zrandmember(key, count)); + } + + @Override + public Response> zrandmemberWithScores(byte[] key, long count) { + return appendCommand(commandObjects.zrandmemberWithScores(key, count)); + } + + @Override + public Response zcard(byte[] key) { + return appendCommand(commandObjects.zcard(key)); + } + + @Override + public Response zscore(byte[] key, byte[] member) { + return appendCommand(commandObjects.zscore(key, member)); + } + + @Override + public Response> zmscore(byte[] key, byte[]... members) { + return appendCommand(commandObjects.zmscore(key, members)); + } + + @Override + public Response zpopmax(byte[] key) { + return appendCommand(commandObjects.zpopmax(key)); + } + + @Override + public Response> zpopmax(byte[] key, int count) { + return appendCommand(commandObjects.zpopmax(key, count)); + } + + @Override + public Response zpopmin(byte[] key) { + return appendCommand(commandObjects.zpopmin(key)); + } + + @Override + public Response> zpopmin(byte[] key, int count) { + return appendCommand(commandObjects.zpopmin(key, count)); + } + + @Override + public Response zcount(byte[] key, double min, double max) { + return appendCommand(commandObjects.zcount(key, min, max)); + } + + @Override + public Response zcount(byte[] key, byte[] min, byte[] max) { + return appendCommand(commandObjects.zcount(key, min, max)); + } + + @Override + public Response> zrangeByScore(byte[] key, double min, double max) { + return appendCommand(commandObjects.zrangeByScore(key, min, max)); + } + + @Override + public Response> zrangeByScore(byte[] key, byte[] min, byte[] max) { + return appendCommand(commandObjects.zrangeByScore(key, min, max)); + } + + @Override + public Response> zrevrangeByScore(byte[] key, double max, double min) { + return appendCommand(commandObjects.zrevrangeByScore(key, max, min)); + } + + @Override + public Response> zrangeByScore(byte[] key, double min, double max, int offset, int count) { + return appendCommand(commandObjects.zrangeByScore(key, min, max, offset, count)); + } + + @Override + public Response> zrevrangeByScore(byte[] key, byte[] max, byte[] min) { + return appendCommand(commandObjects.zrevrangeByScore(key, max, min)); + } + + @Override + public Response> zrangeByScore(byte[] key, byte[] min, byte[] max, int offset, int count) { + return appendCommand(commandObjects.zrangeByScore(key, min, max, offset, count)); + } + + @Override + public Response> zrevrangeByScore(byte[] key, double max, double min, int offset, int count) { + return appendCommand(commandObjects.zrevrangeByScore(key, max, min, offset, count)); + } + + @Override + public Response> zrangeByScoreWithScores(byte[] key, double min, double max) { + return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max)); + } + + @Override + public Response> zrevrangeByScoreWithScores(byte[] key, double max, double min) { + return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min)); + } + + @Override + public Response> zrangeByScoreWithScores(byte[] key, double min, double max, int offset, int count) { + return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max, offset, count)); + } + + @Override + public Response> zrevrangeByScore(byte[] key, byte[] max, byte[] min, int offset, int count) { + return appendCommand(commandObjects.zrevrangeByScore(key, max, min, offset, count)); + } + + @Override + public Response> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max) { + return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max)); + } + + @Override + public Response> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min) { + return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min)); + } + + @Override + public Response> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max, int offset, int count) { + return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max, offset, count)); + } + + @Override + public Response> zrevrangeByScoreWithScores(byte[] key, double max, double min, int offset, int count) { + return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min, offset, count)); + } + + @Override + public Response> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min, int offset, int count) { + return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min, offset, count)); + } + + @Override + public Response zremrangeByRank(byte[] key, long start, long stop) { + return appendCommand(commandObjects.zremrangeByRank(key, start, stop)); + } + + @Override + public Response zremrangeByScore(byte[] key, double min, double max) { + return appendCommand(commandObjects.zremrangeByScore(key, min, max)); + } + + @Override + public Response zremrangeByScore(byte[] key, byte[] min, byte[] max) { + return appendCommand(commandObjects.zremrangeByScore(key, min, max)); + } + + @Override + public Response zlexcount(byte[] key, byte[] min, byte[] max) { + return appendCommand(commandObjects.zlexcount(key, min, max)); + } + + @Override + public Response> zrangeByLex(byte[] key, byte[] min, byte[] max) { + return appendCommand(commandObjects.zrangeByLex(key, min, max)); + } + + @Override + public Response> zrangeByLex(byte[] key, byte[] min, byte[] max, int offset, int count) { + return appendCommand(commandObjects.zrangeByLex(key, min, max, offset, count)); + } + + @Override + public Response> zrevrangeByLex(byte[] key, byte[] max, byte[] min) { + return appendCommand(commandObjects.zrevrangeByLex(key, max, min)); + } + + @Override + public Response> zrevrangeByLex(byte[] key, byte[] max, byte[] min, int offset, int count) { + return appendCommand(commandObjects.zrevrangeByLex(key, max, min, offset, count)); + } + + @Override + public Response> zrange(byte[] key, ZRangeParams zRangeParams) { + return appendCommand(commandObjects.zrange(key, zRangeParams)); + } + + @Override + public Response> zrangeWithScores(byte[] key, ZRangeParams zRangeParams) { + return appendCommand(commandObjects.zrangeWithScores(key, zRangeParams)); + } + + @Override + public Response zrangestore(byte[] dest, byte[] src, ZRangeParams zRangeParams) { + return appendCommand(commandObjects.zrangestore(dest, src, zRangeParams)); + } + + @Override + public Response zremrangeByLex(byte[] key, byte[] min, byte[] max) { + return appendCommand(commandObjects.zremrangeByLex(key, min, max)); + } + + @Override + public Response> zscan(byte[] key, byte[] cursor, ScanParams params) { + return appendCommand(commandObjects.zscan(key, cursor, params)); + } + + @Override + public Response> bzpopmax(double timeout, byte[]... keys) { + return appendCommand(commandObjects.bzpopmax(timeout, keys)); + } + + @Override + public Response> bzpopmin(double timeout, byte[]... keys) { + return appendCommand(commandObjects.bzpopmin(timeout, keys)); + } + + @Override + public Response>> zmpop(SortedSetOption option, byte[]... keys) { + return appendCommand(commandObjects.zmpop(option, keys)); + } + + @Override + public Response>> zmpop(SortedSetOption option, int count, byte[]... keys) { + return appendCommand(commandObjects.zmpop(option, count, keys)); + } + + @Override + public Response>> bzmpop(double timeout, SortedSetOption option, byte[]... keys) { + return appendCommand(commandObjects.bzmpop(timeout, option, keys)); + } + + @Override + public Response>> bzmpop(double timeout, SortedSetOption option, int count, byte[]... keys) { + return appendCommand(commandObjects.bzmpop(timeout, option, count, keys)); + } + + @Override + public Response> zdiff(byte[]... keys) { + return appendCommand(commandObjects.zdiff(keys)); + } + + @Override + public Response> zdiffWithScores(byte[]... keys) { + return appendCommand(commandObjects.zdiffWithScores(keys)); + } + + @Override + @Deprecated + public Response zdiffStore(byte[] dstkey, byte[]... keys) { + return appendCommand(commandObjects.zdiffStore(dstkey, keys)); + } + + @Override + public Response zdiffstore(byte[] dstkey, byte[]... keys) { + return appendCommand(commandObjects.zdiffstore(dstkey, keys)); + } + + @Override + public Response> zinter(ZParams params, byte[]... keys) { + return appendCommand(commandObjects.zinter(params, keys)); + } + + @Override + public Response> zinterWithScores(ZParams params, byte[]... keys) { + return appendCommand(commandObjects.zinterWithScores(params, keys)); + } + + @Override + public Response zinterstore(byte[] dstkey, byte[]... sets) { + return appendCommand(commandObjects.zinterstore(dstkey, sets)); + } + + @Override + public Response zinterstore(byte[] dstkey, ZParams params, byte[]... sets) { + return appendCommand(commandObjects.zinterstore(dstkey, params, sets)); + } + + @Override + public Response zintercard(byte[]... keys) { + return appendCommand(commandObjects.zintercard(keys)); + } + + @Override + public Response zintercard(long limit, byte[]... keys) { + return appendCommand(commandObjects.zintercard(limit, keys)); + } + + @Override + public Response> zunion(ZParams params, byte[]... keys) { + return appendCommand(commandObjects.zunion(params, keys)); + } + + @Override + public Response> zunionWithScores(ZParams params, byte[]... keys) { + return appendCommand(commandObjects.zunionWithScores(params, keys)); + } + + @Override + public Response zunionstore(byte[] dstkey, byte[]... sets) { + return appendCommand(commandObjects.zunionstore(dstkey, sets)); + } + + @Override + public Response zunionstore(byte[] dstkey, ZParams params, byte[]... sets) { + return appendCommand(commandObjects.zunionstore(dstkey, params, sets)); + } + + @Override + public Response xadd(byte[] key, XAddParams params, Map hash) { + return appendCommand(commandObjects.xadd(key, params, hash)); + } + + @Override + public Response xlen(byte[] key) { + return appendCommand(commandObjects.xlen(key)); + } + + @Override + public Response> xrange(byte[] key, byte[] start, byte[] end) { + return appendCommand(commandObjects.xrange(key, start, end)); + } + + @Override + public Response> xrange(byte[] key, byte[] start, byte[] end, int count) { + return appendCommand(commandObjects.xrange(key, start, end, count)); + } + + @Override + public Response> xrevrange(byte[] key, byte[] end, byte[] start) { + return appendCommand(commandObjects.xrevrange(key, end, start)); + } + + @Override + public Response> xrevrange(byte[] key, byte[] end, byte[] start, int count) { + return appendCommand(commandObjects.xrevrange(key, end, start, count)); + } + + @Override + public Response xack(byte[] key, byte[] group, byte[]... ids) { + return appendCommand(commandObjects.xack(key, group, ids)); + } + + @Override + public Response xgroupCreate(byte[] key, byte[] groupName, byte[] id, boolean makeStream) { + return appendCommand(commandObjects.xgroupCreate(key, groupName, id, makeStream)); + } + + @Override + public Response xgroupSetID(byte[] key, byte[] groupName, byte[] id) { + return appendCommand(commandObjects.xgroupSetID(key, groupName, id)); + } + + @Override + public Response xgroupDestroy(byte[] key, byte[] groupName) { + return appendCommand(commandObjects.xgroupDestroy(key, groupName)); + } + + @Override + public Response xgroupCreateConsumer(byte[] key, byte[] groupName, byte[] consumerName) { + return appendCommand(commandObjects.xgroupCreateConsumer(key, groupName, consumerName)); + } + + @Override + public Response xgroupDelConsumer(byte[] key, byte[] groupName, byte[] consumerName) { + return appendCommand(commandObjects.xgroupDelConsumer(key, groupName, consumerName)); + } + + @Override + public Response xdel(byte[] key, byte[]... ids) { + return appendCommand(commandObjects.xdel(key, ids)); + } + + @Override + public Response xtrim(byte[] key, long maxLen, boolean approximateLength) { + return appendCommand(commandObjects.xtrim(key, maxLen, approximateLength)); + } + + @Override + public Response xtrim(byte[] key, XTrimParams params) { + return appendCommand(commandObjects.xtrim(key, params)); + } + + @Override + public Response xpending(byte[] key, byte[] groupName) { + return appendCommand(commandObjects.xpending(key, groupName)); + } + + @Override + public Response> xpending(byte[] key, byte[] groupName, XPendingParams params) { + return appendCommand(commandObjects.xpending(key, groupName, params)); + } + + @Override + public Response> xclaim(byte[] key, byte[] group, byte[] consumerName, long minIdleTime, XClaimParams params, byte[]... ids) { + return appendCommand(commandObjects.xclaim(key, group, consumerName, minIdleTime, params, ids)); + } + + @Override + public Response> xclaimJustId(byte[] key, byte[] group, byte[] consumerName, long minIdleTime, XClaimParams params, byte[]... ids) { + return appendCommand(commandObjects.xclaimJustId(key, group, consumerName, minIdleTime, params, ids)); + } + + @Override + public Response> xautoclaim(byte[] key, byte[] groupName, byte[] consumerName, long minIdleTime, byte[] start, XAutoClaimParams params) { + return appendCommand(commandObjects.xautoclaim(key, groupName, consumerName, minIdleTime, start, params)); + } + + @Override + public Response> xautoclaimJustId(byte[] key, byte[] groupName, byte[] consumerName, long minIdleTime, byte[] start, XAutoClaimParams params) { + return appendCommand(commandObjects.xautoclaimJustId(key, groupName, consumerName, minIdleTime, start, params)); + } + + @Override + public Response xinfoStream(byte[] key) { + return appendCommand(commandObjects.xinfoStream(key)); + } + + @Override + public Response xinfoStreamFull(byte[] key) { + return appendCommand(commandObjects.xinfoStreamFull(key)); + } + + @Override + public Response xinfoStreamFull(byte[] key, int count) { + return appendCommand(commandObjects.xinfoStreamFull(key, count)); + } + + @Override + public Response> xinfoGroups(byte[] key) { + return appendCommand(commandObjects.xinfoGroups(key)); + } + + @Override + public Response> xinfoConsumers(byte[] key, byte[] group) { + return appendCommand(commandObjects.xinfoConsumers(key, group)); + } + + @Override + public Response> xread(XReadParams xReadParams, Map.Entry... streams) { + return appendCommand(commandObjects.xread(xReadParams, streams)); + } + + @Override + public Response> xreadGroup(byte[] groupName, byte[] consumer, + XReadGroupParams xReadGroupParams, Map.Entry... streams) { + return appendCommand(commandObjects.xreadGroup(groupName, consumer, xReadGroupParams, streams)); + } + + @Override + public Response set(byte[] key, byte[] value) { + return appendCommand(commandObjects.set(key, value)); + } + + @Override + public Response set(byte[] key, byte[] value, SetParams params) { + return appendCommand(commandObjects.set(key, value, params)); + } + + @Override + public Response get(byte[] key) { + return appendCommand(commandObjects.get(key)); + } + + @Override + public Response setGet(byte[] key, byte[] value, SetParams params) { + return appendCommand(commandObjects.setGet(key, value, params)); + } + + @Override + public Response getDel(byte[] key) { + return appendCommand(commandObjects.getDel(key)); + } + + @Override + public Response getEx(byte[] key, GetExParams params) { + return appendCommand(commandObjects.getEx(key, params)); + } + + @Override + public Response setbit(byte[] key, long offset, boolean value) { + return appendCommand(commandObjects.setbit(key, offset, value)); + } + + @Override + public Response getbit(byte[] key, long offset) { + return appendCommand(commandObjects.getbit(key, offset)); + } + + @Override + public Response setrange(byte[] key, long offset, byte[] value) { + return appendCommand(commandObjects.setrange(key, offset, value)); + } + + @Override + public Response getrange(byte[] key, long startOffset, long endOffset) { + return appendCommand(commandObjects.getrange(key, startOffset, endOffset)); + } + + @Override + public Response getSet(byte[] key, byte[] value) { + return appendCommand(commandObjects.getSet(key, value)); + } + + @Override + public Response setnx(byte[] key, byte[] value) { + return appendCommand(commandObjects.setnx(key, value)); + } + + @Override + public Response setex(byte[] key, long seconds, byte[] value) { + return appendCommand(commandObjects.setex(key, seconds, value)); + } + + @Override + public Response psetex(byte[] key, long milliseconds, byte[] value) { + return appendCommand(commandObjects.psetex(key, milliseconds, value)); + } + + @Override + public Response> mget(byte[]... keys) { + return appendCommand(commandObjects.mget(keys)); + } + + @Override + public Response mset(byte[]... keysvalues) { + return appendCommand(commandObjects.mset(keysvalues)); + } + + @Override + public Response msetnx(byte[]... keysvalues) { + return appendCommand(commandObjects.msetnx(keysvalues)); + } + + @Override + public Response incr(byte[] key) { + return appendCommand(commandObjects.incr(key)); + } + + @Override + public Response incrBy(byte[] key, long increment) { + return appendCommand(commandObjects.incrBy(key, increment)); + } + + @Override + public Response incrByFloat(byte[] key, double increment) { + return appendCommand(commandObjects.incrByFloat(key, increment)); + } + + @Override + public Response decr(byte[] key) { + return appendCommand(commandObjects.decr(key)); + } + + @Override + public Response decrBy(byte[] key, long decrement) { + return appendCommand(commandObjects.decrBy(key, decrement)); + } + + @Override + public Response append(byte[] key, byte[] value) { + return appendCommand(commandObjects.append(key, value)); + } + + @Override + public Response substr(byte[] key, int start, int end) { + return appendCommand(commandObjects.substr(key, start, end)); + } + + @Override + public Response strlen(byte[] key) { + return appendCommand(commandObjects.strlen(key)); + } + + @Override + public Response bitcount(byte[] key) { + return appendCommand(commandObjects.bitcount(key)); + } + + @Override + public Response bitcount(byte[] key, long start, long end) { + return appendCommand(commandObjects.bitcount(key, start, end)); + } + + @Override + public Response bitcount(byte[] key, long start, long end, BitCountOption option) { + return appendCommand(commandObjects.bitcount(key, start, end, option)); + } + + @Override + public Response bitpos(byte[] key, boolean value) { + return appendCommand(commandObjects.bitpos(key, value)); + } + + @Override + public Response bitpos(byte[] key, boolean value, BitPosParams params) { + return appendCommand(commandObjects.bitpos(key, value, params)); + } + + @Override + public Response> bitfield(byte[] key, byte[]... arguments) { + return appendCommand(commandObjects.bitfield(key, arguments)); + } + + @Override + public Response> bitfieldReadonly(byte[] key, byte[]... arguments) { + return appendCommand(commandObjects.bitfieldReadonly(key, arguments)); + } + + @Override + public Response bitop(BitOP op, byte[] destKey, byte[]... srcKeys) { + return appendCommand(commandObjects.bitop(op, destKey, srcKeys)); + } + + // RediSearch commands + @Override + public Response ftCreate(String indexName, IndexOptions indexOptions, Schema schema) { + return appendCommand(commandObjects.ftCreate(indexName, indexOptions, schema)); + } + + @Override + public Response ftCreate(String indexName, FTCreateParams createParams, Iterable schemaFields) { + return appendCommand(commandObjects.ftCreate(indexName, createParams, schemaFields)); + } + + @Override + public Response ftAlter(String indexName, Schema schema) { + return appendCommand(commandObjects.ftAlter(indexName, schema)); + } + + @Override + public Response ftAlter(String indexName, Iterable schemaFields) { + return appendCommand(commandObjects.ftAlter(indexName, schemaFields)); + } + + @Override + public Response ftAliasAdd(String aliasName, String indexName) { + return appendCommand(commandObjects.ftAliasAdd(aliasName, indexName)); + } + + @Override + public Response ftAliasUpdate(String aliasName, String indexName) { + return appendCommand(commandObjects.ftAliasUpdate(aliasName, indexName)); + } + + @Override + public Response ftAliasDel(String aliasName) { + return appendCommand(commandObjects.ftAliasDel(aliasName)); + } + + @Override + public Response ftDropIndex(String indexName) { + return appendCommand(commandObjects.ftDropIndex(indexName)); + } + + @Override + public Response ftDropIndexDD(String indexName) { + return appendCommand(commandObjects.ftDropIndexDD(indexName)); + } + + @Override + public Response ftSearch(String indexName, String query) { + return appendCommand(commandObjects.ftSearch(indexName, query)); + } + + @Override + public Response ftSearch(String indexName, String query, FTSearchParams searchParams) { + return appendCommand(commandObjects.ftSearch(indexName, query, searchParams)); + } + + @Override + public Response ftSearch(String indexName, Query query) { + return appendCommand(commandObjects.ftSearch(indexName, query)); + } + + @Override + @Deprecated + public Response ftSearch(byte[] indexName, Query query) { + return appendCommand(commandObjects.ftSearch(indexName, query)); + } + + @Override + public Response ftExplain(String indexName, Query query) { + return appendCommand(commandObjects.ftExplain(indexName, query)); + } + + @Override + public Response> ftExplainCLI(String indexName, Query query) { + return appendCommand(commandObjects.ftExplainCLI(indexName, query)); + } + + @Override + public Response ftAggregate(String indexName, AggregationBuilder aggr) { + return appendCommand(commandObjects.ftAggregate(indexName, aggr)); + } + + @Override + public Response ftSynUpdate(String indexName, String synonymGroupId, String... terms) { + return appendCommand(commandObjects.ftSynUpdate(indexName, synonymGroupId, terms)); + } + + @Override + public Response>> ftSynDump(String indexName) { + return appendCommand(commandObjects.ftSynDump(indexName)); + } + + @Override + public Response ftDictAdd(String dictionary, String... terms) { + return appendCommand(commandObjects.ftDictAdd(dictionary, terms)); + } + + @Override + public Response ftDictDel(String dictionary, String... terms) { + return appendCommand(commandObjects.ftDictDel(dictionary, terms)); + } + + @Override + public Response> ftDictDump(String dictionary) { + return appendCommand(commandObjects.ftDictDump(dictionary)); + } + + @Override + public Response ftDictAddBySampleKey(String indexName, String dictionary, String... terms) { + return appendCommand(commandObjects.ftDictAddBySampleKey(indexName, dictionary, terms)); + } + + @Override + public Response ftDictDelBySampleKey(String indexName, String dictionary, String... terms) { + return appendCommand(commandObjects.ftDictDelBySampleKey(indexName, dictionary, terms)); + } + + @Override + public Response> ftDictDumpBySampleKey(String indexName, String dictionary) { + return appendCommand(commandObjects.ftDictDumpBySampleKey(indexName, dictionary)); + } + + @Override + public Response>> ftSpellCheck(String index, String query) { + return appendCommand(commandObjects.ftSpellCheck(index, query)); + } + + @Override + public Response>> ftSpellCheck(String index, String query, FTSpellCheckParams spellCheckParams) { + return appendCommand(commandObjects.ftSpellCheck(index, query, spellCheckParams)); + } + + @Override + public Response> ftInfo(String indexName) { + return appendCommand(commandObjects.ftInfo(indexName)); + } + + @Override + public Response> ftTagVals(String indexName, String fieldName) { + return appendCommand(commandObjects.ftTagVals(indexName, fieldName)); + } + + @Override + public Response> ftConfigGet(String option) { + return appendCommand(commandObjects.ftConfigGet(option)); + } + + @Override + public Response> ftConfigGet(String indexName, String option) { + return appendCommand(commandObjects.ftConfigGet(indexName, option)); + } + + @Override + public Response ftConfigSet(String option, String value) { + return appendCommand(commandObjects.ftConfigSet(option, value)); + } + + @Override + public Response ftConfigSet(String indexName, String option, String value) { + return appendCommand(commandObjects.ftConfigSet(indexName, option, value)); + } + + @Override + public Response ftSugAdd(String key, String string, double score) { + return appendCommand(commandObjects.ftSugAdd(key, string, score)); + } + + @Override + public Response ftSugAddIncr(String key, String string, double score) { + return appendCommand(commandObjects.ftSugAddIncr(key, string, score)); + } + + @Override + public Response> ftSugGet(String key, String prefix) { + return appendCommand(commandObjects.ftSugGet(key, prefix)); + } + + @Override + public Response> ftSugGet(String key, String prefix, boolean fuzzy, int max) { + return appendCommand(commandObjects.ftSugGet(key, prefix, fuzzy, max)); + } + + @Override + public Response> ftSugGetWithScores(String key, String prefix) { + return appendCommand(commandObjects.ftSugGetWithScores(key, prefix)); + } + + @Override + public Response> ftSugGetWithScores(String key, String prefix, boolean fuzzy, int max) { + return appendCommand(commandObjects.ftSugGetWithScores(key, prefix, fuzzy, max)); + } + + @Override + public Response ftSugDel(String key, String string) { + return appendCommand(commandObjects.ftSugDel(key, string)); + } + + @Override + public Response ftSugLen(String key) { + return appendCommand(commandObjects.ftSugLen(key)); + } + // RediSearch commands + + // RedisJSON commands + @Override + public Response lcs(byte[] keyA, byte[] keyB, LCSParams params) { + return appendCommand(commandObjects.lcs(keyA, keyB, params)); + } + + @Override + public Response jsonSet(String key, Path2 path, Object object) { + return appendCommand(commandObjects.jsonSet(key, path, object)); + } + + @Override + public Response jsonSetWithEscape(String key, Path2 path, Object object) { + return appendCommand(commandObjects.jsonSetWithEscape(key, path, object)); + } + + @Override + public Response jsonSet(String key, Path path, Object object) { + return appendCommand(commandObjects.jsonSet(key, path, object)); + } + + @Override + public Response jsonSet(String key, Path2 path, Object object, JsonSetParams params) { + return appendCommand(commandObjects.jsonSet(key, path, object, params)); + } + + @Override + public Response jsonSetWithEscape(String key, Path2 path, Object object, JsonSetParams params) { + return appendCommand(commandObjects.jsonSetWithEscape(key, path, object, params)); + } + + @Override + public Response jsonSet(String key, Path path, Object object, JsonSetParams params) { + return appendCommand(commandObjects.jsonSet(key, path, object, params)); + } + + @Override + public Response jsonMerge(String key, Path2 path, Object object) { + return appendCommand(commandObjects.jsonMerge(key, path, object)); + } + + @Override + public Response jsonMerge(String key, Path path, Object object) { + return appendCommand(commandObjects.jsonMerge(key, path, object)); + } + + @Override + public Response jsonGet(String key) { + return appendCommand(commandObjects.jsonGet(key)); + } + + @Override + public Response jsonGet(String key, Class clazz) { + return appendCommand(commandObjects.jsonGet(key, clazz)); + } + + @Override + public Response jsonGet(String key, Path2... paths) { + return appendCommand(commandObjects.jsonGet(key, paths)); + } + + @Override + public Response jsonGet(String key, Path... paths) { + return appendCommand(commandObjects.jsonGet(key, paths)); + } + + @Override + public Response jsonGet(String key, Class clazz, Path... paths) { + return appendCommand(commandObjects.jsonGet(key, clazz, paths)); + } + + @Override + public Response> jsonMGet(Path2 path, String... keys) { + return appendCommand(commandObjects.jsonMGet(path, keys)); + } + + @Override + public Response> jsonMGet(Path path, Class clazz, String... keys) { + return appendCommand(commandObjects.jsonMGet(path, clazz, keys)); + } + + @Override + public Response jsonDel(String key) { + return appendCommand(commandObjects.jsonDel(key)); + } + + @Override + public Response jsonDel(String key, Path2 path) { + return appendCommand(commandObjects.jsonDel(key, path)); + } + + @Override + public Response jsonDel(String key, Path path) { + return appendCommand(commandObjects.jsonDel(key, path)); + } + + @Override + public Response jsonClear(String key) { + return appendCommand(commandObjects.jsonClear(key)); + } + + @Override + public Response jsonClear(String key, Path2 path) { + return appendCommand(commandObjects.jsonClear(key, path)); + } + + @Override + public Response jsonClear(String key, Path path) { + return appendCommand(commandObjects.jsonClear(key, path)); + } + + @Override + public Response> jsonToggle(String key, Path2 path) { + return appendCommand(commandObjects.jsonToggle(key, path)); + } + + @Override + public Response jsonToggle(String key, Path path) { + return appendCommand(commandObjects.jsonToggle(key, path)); + } + + @Override + public Response> jsonType(String key) { + return appendCommand(commandObjects.jsonType(key)); + } + + @Override + public Response>> jsonType(String key, Path2 path) { + return appendCommand(commandObjects.jsonType(key, path)); + } + + @Override + public Response> jsonType(String key, Path path) { + return appendCommand(commandObjects.jsonType(key, path)); + } + + @Override + public Response jsonStrAppend(String key, Object string) { + return appendCommand(commandObjects.jsonStrAppend(key, string)); + } + + @Override + public Response> jsonStrAppend(String key, Path2 path, Object string) { + return appendCommand(commandObjects.jsonStrAppend(key, path, string)); + } + + @Override + public Response jsonStrAppend(String key, Path path, Object string) { + return appendCommand(commandObjects.jsonStrAppend(key, path, string)); + } + + @Override + public Response jsonStrLen(String key) { + return appendCommand(commandObjects.jsonStrLen(key)); + } + + @Override + public Response> jsonStrLen(String key, Path2 path) { + return appendCommand(commandObjects.jsonStrLen(key, path)); + } + + @Override + public Response jsonStrLen(String key, Path path) { + return appendCommand(commandObjects.jsonStrLen(key, path)); + } + + @Override + public Response jsonNumIncrBy(String key, Path2 path, double value) { + return appendCommand(commandObjects.jsonNumIncrBy(key, path, value)); + } + + @Override + public Response jsonNumIncrBy(String key, Path path, double value) { + return appendCommand(commandObjects.jsonNumIncrBy(key, path, value)); + } + + @Override + public Response> jsonArrAppend(String key, Path2 path, Object... objects) { + return appendCommand(commandObjects.jsonArrAppend(key, path, objects)); + } + + @Override + public Response> jsonArrAppendWithEscape(String key, Path2 path, Object... objects) { + return appendCommand(commandObjects.jsonArrAppendWithEscape(key, path, objects)); + } + + @Override + public Response jsonArrAppend(String key, Path path, Object... objects) { + return appendCommand(commandObjects.jsonArrAppend(key, path, objects)); + } + + @Override + public Response> jsonArrIndex(String key, Path2 path, Object scalar) { + return appendCommand(commandObjects.jsonArrIndex(key, path, scalar)); + } + + @Override + public Response> jsonArrIndexWithEscape(String key, Path2 path, Object scalar) { + return appendCommand(commandObjects.jsonArrIndexWithEscape(key, path, scalar)); + } + + @Override + public Response jsonArrIndex(String key, Path path, Object scalar) { + return appendCommand(commandObjects.jsonArrIndex(key, path, scalar)); + } + + @Override + public Response> jsonArrInsert(String key, Path2 path, int index, Object... objects) { + return appendCommand(commandObjects.jsonArrInsert(key, path, index, objects)); + } + + @Override + public Response> jsonArrInsertWithEscape(String key, Path2 path, int index, Object... objects) { + return appendCommand(commandObjects.jsonArrInsertWithEscape(key, path, index, objects)); + } + + @Override + public Response jsonArrInsert(String key, Path path, int index, Object... pojos) { + return appendCommand(commandObjects.jsonArrInsert(key, path, index, pojos)); + } + + @Override + public Response jsonArrPop(String key) { + return appendCommand(commandObjects.jsonArrPop(key)); + } + + @Override + public Response jsonArrLen(String key, Path path) { + return appendCommand(commandObjects.jsonArrLen(key, path)); + } + + @Override + public Response> jsonArrTrim(String key, Path2 path, int start, int stop) { + return appendCommand(commandObjects.jsonArrTrim(key, path, start, stop)); + } + + @Override + public Response jsonArrTrim(String key, Path path, int start, int stop) { + return appendCommand(commandObjects.jsonArrTrim(key, path, start, stop)); + } + + @Override + public Response jsonArrPop(String key, Class clazz, Path path) { + return appendCommand(commandObjects.jsonArrPop(key, clazz, path)); + } + + @Override + public Response> jsonArrPop(String key, Path2 path, int index) { + return appendCommand(commandObjects.jsonArrPop(key, path, index)); + } + + @Override + public Response jsonArrPop(String key, Path path, int index) { + return appendCommand(commandObjects.jsonArrPop(key, path, index)); + } + + @Override + public Response jsonArrPop(String key, Class clazz, Path path, int index) { + return appendCommand(commandObjects.jsonArrPop(key, clazz, path, index)); + } + + @Override + public Response jsonArrLen(String key) { + return appendCommand(commandObjects.jsonArrLen(key)); + } + + @Override + public Response> jsonArrLen(String key, Path2 path) { + return appendCommand(commandObjects.jsonArrLen(key, path)); + } + + @Override + public Response jsonArrPop(String key, Class clazz) { + return appendCommand(commandObjects.jsonArrPop(key, clazz)); + } + + @Override + public Response> jsonArrPop(String key, Path2 path) { + return appendCommand(commandObjects.jsonArrPop(key, path)); + } + + @Override + public Response jsonArrPop(String key, Path path) { + return appendCommand(commandObjects.jsonArrPop(key, path)); + } + // RedisJSON commands + + // RedisTimeSeries commands + @Override + public Response tsCreate(String key) { + return appendCommand(commandObjects.tsCreate(key)); + } + + @Override + public Response tsCreate(String key, TSCreateParams createParams) { + return appendCommand(commandObjects.tsCreate(key, createParams)); + } + + @Override + public Response tsDel(String key, long fromTimestamp, long toTimestamp) { + return appendCommand(commandObjects.tsDel(key, fromTimestamp, toTimestamp)); + } + + @Override + public Response tsAlter(String key, TSAlterParams alterParams) { + return appendCommand(commandObjects.tsAlter(key, alterParams)); + } + + @Override + public Response tsAdd(String key, double value) { + return appendCommand(commandObjects.tsAdd(key, value)); + } + + @Override + public Response tsAdd(String key, long timestamp, double value) { + return appendCommand(commandObjects.tsAdd(key, timestamp, value)); + } + + @Override + public Response tsAdd(String key, long timestamp, double value, TSCreateParams createParams) { + return appendCommand(commandObjects.tsAdd(key, timestamp, value, createParams)); + } + + @Override + public Response> tsMAdd(Map.Entry... entries) { + return appendCommand(commandObjects.tsMAdd(entries)); + } + + @Override + public Response tsIncrBy(String key, double value) { + return appendCommand(commandObjects.tsIncrBy(key, value)); + } + + @Override + public Response tsIncrBy(String key, double value, long timestamp) { + return appendCommand(commandObjects.tsIncrBy(key, value, timestamp)); + } + + @Override + public Response tsDecrBy(String key, double value) { + return appendCommand(commandObjects.tsDecrBy(key, value)); + } + + @Override + public Response tsDecrBy(String key, double value, long timestamp) { + return appendCommand(commandObjects.tsDecrBy(key, value, timestamp)); + } + + @Override + public Response> tsRange(String key, long fromTimestamp, long toTimestamp) { + return appendCommand(commandObjects.tsRange(key, fromTimestamp, toTimestamp)); + } + + @Override + public Response> tsRange(String key, TSRangeParams rangeParams) { + return appendCommand(commandObjects.tsRange(key, rangeParams)); + } + + @Override + public Response> tsRevRange(String key, long fromTimestamp, long toTimestamp) { + return appendCommand(commandObjects.tsRevRange(key, fromTimestamp, toTimestamp)); + } + + @Override + public Response> tsRevRange(String key, TSRangeParams rangeParams) { + return appendCommand(commandObjects.tsRevRange(key, rangeParams)); + } + + @Override + public Response> tsMRange(long fromTimestamp, long toTimestamp, String... filters) { + return appendCommand(commandObjects.tsMRange(fromTimestamp, toTimestamp, filters)); + } + + @Override + public Response> tsMRange(TSMRangeParams multiRangeParams) { + return appendCommand(commandObjects.tsMRange(multiRangeParams)); + } + + @Override + public Response> tsMRevRange(long fromTimestamp, long toTimestamp, String... filters) { + return appendCommand(commandObjects.tsMRevRange(fromTimestamp, toTimestamp, filters)); + } + + @Override + public Response> tsMRevRange(TSMRangeParams multiRangeParams) { + return appendCommand(commandObjects.tsMRevRange(multiRangeParams)); + } + + @Override + public Response tsGet(String key) { + return appendCommand(commandObjects.tsGet(key)); + } + + @Override + public Response tsGet(String key, TSGetParams getParams) { + return appendCommand(commandObjects.tsGet(key, getParams)); + } + + @Override + public Response> tsMGet(TSMGetParams multiGetParams, String... filters) { + return appendCommand(commandObjects.tsMGet(multiGetParams, filters)); + } + + @Override + public Response tsCreateRule(String sourceKey, String destKey, AggregationType aggregationType, long timeBucket) { + return appendCommand(commandObjects.tsCreateRule(sourceKey, destKey, aggregationType, timeBucket)); + } + + @Override + public Response tsCreateRule(String sourceKey, String destKey, AggregationType aggregationType, long bucketDuration, long alignTimestamp) { + return appendCommand(commandObjects.tsCreateRule(sourceKey, destKey, aggregationType, bucketDuration, alignTimestamp)); + } + + @Override + public Response tsDeleteRule(String sourceKey, String destKey) { + return appendCommand(commandObjects.tsDeleteRule(sourceKey, destKey)); + } + + @Override + public Response> tsQueryIndex(String... filters) { + return appendCommand(commandObjects.tsQueryIndex(filters)); + } + // RedisTimeSeries commands + + // RedisBloom commands + @Override + public Response bfReserve(String key, double errorRate, long capacity) { + return appendCommand(commandObjects.bfReserve(key, errorRate, capacity)); + } + + @Override + public Response bfReserve(String key, double errorRate, long capacity, BFReserveParams reserveParams) { + return appendCommand(commandObjects.bfReserve(key, errorRate, capacity, reserveParams)); + } + + @Override + public Response bfAdd(String key, String item) { + return appendCommand(commandObjects.bfAdd(key, item)); + } + + @Override + public Response> bfMAdd(String key, String... items) { + return appendCommand(commandObjects.bfMAdd(key, items)); + } + + @Override + public Response> bfInsert(String key, String... items) { + return appendCommand(commandObjects.bfInsert(key, items)); + } + + @Override + public Response> bfInsert(String key, BFInsertParams insertParams, String... items) { + return appendCommand(commandObjects.bfInsert(key, insertParams, items)); + } + + @Override + public Response bfExists(String key, String item) { + return appendCommand(commandObjects.bfExists(key, item)); + } + + @Override + public Response> bfMExists(String key, String... items) { + return appendCommand(commandObjects.bfMExists(key, items)); + } + + @Override + public Response> bfScanDump(String key, long iterator) { + return appendCommand(commandObjects.bfScanDump(key, iterator)); + } + + @Override + public Response bfLoadChunk(String key, long iterator, byte[] data) { + return appendCommand(commandObjects.bfLoadChunk(key, iterator, data)); + } + + @Override + public Response bfCard(String key) { + return appendCommand(commandObjects.bfCard(key)); + } + + @Override + public Response> bfInfo(String key) { + return appendCommand(commandObjects.bfInfo(key)); + } + + @Override + public Response cfReserve(String key, long capacity) { + return appendCommand(commandObjects.cfReserve(key, capacity)); + } + + @Override + public Response cfReserve(String key, long capacity, CFReserveParams reserveParams) { + return appendCommand(commandObjects.cfReserve(key, capacity, reserveParams)); + } + + @Override + public Response cfAdd(String key, String item) { + return appendCommand(commandObjects.cfAdd(key, item)); + } + + @Override + public Response cfAddNx(String key, String item) { + return appendCommand(commandObjects.cfAddNx(key, item)); + } + + @Override + public Response> cfInsert(String key, String... items) { + return appendCommand(commandObjects.cfInsert(key, items)); + } + + @Override + public Response> cfInsert(String key, CFInsertParams insertParams, String... items) { + return appendCommand(commandObjects.cfInsert(key, insertParams, items)); + } + + @Override + public Response> cfInsertNx(String key, String... items) { + return appendCommand(commandObjects.cfInsertNx(key, items)); + } + + @Override + public Response> cfInsertNx(String key, CFInsertParams insertParams, String... items) { + return appendCommand(commandObjects.cfInsertNx(key, insertParams, items)); + } + + @Override + public Response cfExists(String key, String item) { + return appendCommand(commandObjects.cfExists(key, item)); + } + + @Override + public Response cfDel(String key, String item) { + return appendCommand(commandObjects.cfDel(key, item)); + } + + @Override + public Response cfCount(String key, String item) { + return appendCommand(commandObjects.cfCount(key, item)); + } + + @Override + public Response> cfScanDump(String key, long iterator) { + return appendCommand(commandObjects.cfScanDump(key, iterator)); + } + + @Override + public Response cfLoadChunk(String key, long iterator, byte[] data) { + return appendCommand(commandObjects.cfLoadChunk(key, iterator, data)); + } + + @Override + public Response> cfInfo(String key) { + return appendCommand(commandObjects.cfInfo(key)); + } + + @Override + public Response cmsInitByDim(String key, long width, long depth) { + return appendCommand(commandObjects.cmsInitByDim(key, width, depth)); + } + + @Override + public Response cmsInitByProb(String key, double error, double probability) { + return appendCommand(commandObjects.cmsInitByProb(key, error, probability)); + } + + @Override + public Response> cmsIncrBy(String key, Map itemIncrements) { + return appendCommand(commandObjects.cmsIncrBy(key, itemIncrements)); + } + + @Override + public Response> cmsQuery(String key, String... items) { + return appendCommand(commandObjects.cmsQuery(key, items)); + } + + @Override + public Response cmsMerge(String destKey, String... keys) { + return appendCommand(commandObjects.cmsMerge(destKey, keys)); + } + + @Override + public Response cmsMerge(String destKey, Map keysAndWeights) { + return appendCommand(commandObjects.cmsMerge(destKey, keysAndWeights)); + } + + @Override + public Response> cmsInfo(String key) { + return appendCommand(commandObjects.cmsInfo(key)); + } + + @Override + public Response topkReserve(String key, long topk) { + return appendCommand(commandObjects.topkReserve(key, topk)); + } + + @Override + public Response topkReserve(String key, long topk, long width, long depth, double decay) { + return appendCommand(commandObjects.topkReserve(key, topk, width, depth, decay)); + } + + @Override + public Response> topkAdd(String key, String... items) { + return appendCommand(commandObjects.topkAdd(key, items)); + } + + @Override + public Response> topkIncrBy(String key, Map itemIncrements) { + return appendCommand(commandObjects.topkIncrBy(key, itemIncrements)); + } + + @Override + public Response> topkQuery(String key, String... items) { + return appendCommand(commandObjects.topkQuery(key, items)); + } + + @Override + public Response> topkList(String key) { + return appendCommand(commandObjects.topkList(key)); + } + + @Override + public Response> topkListWithCount(String key) { + return appendCommand(commandObjects.topkListWithCount(key)); + } + + @Override + public Response> topkInfo(String key) { + return appendCommand(commandObjects.topkInfo(key)); + } + + @Override + public Response tdigestCreate(String key) { + return appendCommand(commandObjects.tdigestCreate(key)); + } + + @Override + public Response tdigestCreate(String key, int compression) { + return appendCommand(commandObjects.tdigestCreate(key, compression)); + } + + @Override + public Response tdigestReset(String key) { + return appendCommand(commandObjects.tdigestReset(key)); + } + + @Override + public Response tdigestMerge(String destinationKey, String... sourceKeys) { + return appendCommand(commandObjects.tdigestMerge(destinationKey, sourceKeys)); + } + + @Override + public Response tdigestMerge(TDigestMergeParams mergeParams, String destinationKey, String... sourceKeys) { + return appendCommand(commandObjects.tdigestMerge(mergeParams, destinationKey, sourceKeys)); + } + + @Override + public Response> tdigestInfo(String key) { + return appendCommand(commandObjects.tdigestInfo(key)); + } + + @Override + public Response tdigestAdd(String key, double... values) { + return appendCommand(commandObjects.tdigestAdd(key, values)); + } + + @Override + public Response> tdigestCDF(String key, double... values) { + return appendCommand(commandObjects.tdigestCDF(key, values)); + } + + @Override + public Response> tdigestQuantile(String key, double... quantiles) { + return appendCommand(commandObjects.tdigestQuantile(key, quantiles)); + } + + @Override + public Response tdigestMin(String key) { + return appendCommand(commandObjects.tdigestMin(key)); + } + + @Override + public Response tdigestMax(String key) { + return appendCommand(commandObjects.tdigestMax(key)); + } + + @Override + public Response tdigestTrimmedMean(String key, double lowCutQuantile, double highCutQuantile) { + return appendCommand(commandObjects.tdigestTrimmedMean(key, lowCutQuantile, highCutQuantile)); + } + + @Override + public Response> tdigestRank(String key, double... values) { + return appendCommand(commandObjects.tdigestRank(key, values)); + } + + @Override + public Response> tdigestRevRank(String key, double... values) { + return appendCommand(commandObjects.tdigestRevRank(key, values)); + } + + @Override + public Response> tdigestByRank(String key, long... ranks) { + return appendCommand(commandObjects.tdigestByRank(key, ranks)); + } + + @Override + public Response> tdigestByRevRank(String key, long... ranks) { + return appendCommand(commandObjects.tdigestByRevRank(key, ranks)); + } + // RedisBloom commands + + // RedisGraph commands + @Override + public Response graphQuery(String name, String query) { + return appendCommand(graphCommandObjects.graphQuery(name, query)); + } + + @Override + public Response graphReadonlyQuery(String name, String query) { + return appendCommand(graphCommandObjects.graphReadonlyQuery(name, query)); + } + + @Override + public Response graphQuery(String name, String query, long timeout) { + return appendCommand(graphCommandObjects.graphQuery(name, query, timeout)); + } + + @Override + public Response graphReadonlyQuery(String name, String query, long timeout) { + return appendCommand(graphCommandObjects.graphReadonlyQuery(name, query, timeout)); + } + + @Override + public Response graphQuery(String name, String query, Map params) { + return appendCommand(graphCommandObjects.graphQuery(name, query, params)); + } + + @Override + public Response graphReadonlyQuery(String name, String query, Map params) { + return appendCommand(graphCommandObjects.graphReadonlyQuery(name, query, params)); + } + + @Override + public Response graphQuery(String name, String query, Map params, long timeout) { + return appendCommand(graphCommandObjects.graphQuery(name, query, params, timeout)); + } + + @Override + public Response graphReadonlyQuery(String name, String query, Map params, long timeout) { + return appendCommand(graphCommandObjects.graphReadonlyQuery(name, query, params, timeout)); + } + + @Override + public Response graphDelete(String name) { + return appendCommand(graphCommandObjects.graphDelete(name)); + } + + @Override + public Response> graphProfile(String graphName, String query) { + return appendCommand(commandObjects.graphProfile(graphName, query)); + } + // RedisGraph commands + + public Response sendCommand(ProtocolCommand cmd, String... args) { + return sendCommand(new CommandArguments(cmd).addObjects((Object[]) args)); + } + + public Response sendCommand(ProtocolCommand cmd, byte[]... args) { + return sendCommand(new CommandArguments(cmd).addObjects((Object[]) args)); + } + + public Response sendCommand(CommandArguments args) { + return executeCommand(new CommandObject<>(args, BuilderFactory.RAW_OBJECT)); + } + + public Response executeCommand(CommandObject command) { + return appendCommand(command); + } + + public void setJsonObjectMapper(JsonObjectMapper jsonObjectMapper) { + this.commandObjects.setJsonObjectMapper(jsonObjectMapper); + } +} diff --git a/src/main/java/redis/clients/jedis/Protocol.java b/src/main/java/redis/clients/jedis/Protocol.java index d84c66375b..234b73bda9 100644 --- a/src/main/java/redis/clients/jedis/Protocol.java +++ b/src/main/java/redis/clients/jedis/Protocol.java @@ -10,6 +10,7 @@ import redis.clients.jedis.exceptions.*; import redis.clients.jedis.args.Rawable; import redis.clients.jedis.commands.ProtocolCommand; +import redis.clients.jedis.util.KeyValue; import redis.clients.jedis.util.RedisInputStream; import redis.clients.jedis.util.RedisOutputStream; import redis.clients.jedis.util.SafeEncoder; @@ -25,11 +26,19 @@ public final class Protocol { public static final Charset CHARSET = StandardCharsets.UTF_8; - public static final byte DOLLAR_BYTE = '$'; public static final byte ASTERISK_BYTE = '*'; - public static final byte PLUS_BYTE = '+'; - public static final byte MINUS_BYTE = '-'; public static final byte COLON_BYTE = ':'; + public static final byte COMMA_BYTE = ','; + public static final byte DOLLAR_BYTE = '$'; + public static final byte EQUAL_BYTE = '='; + public static final byte GREATER_THAN_BYTE = '>'; + public static final byte HASH_BYTE = '#'; + public static final byte LEFT_BRACE_BYTE = '('; + public static final byte MINUS_BYTE = '-'; + public static final byte PERCENT_BYTE = '%'; + public static final byte PLUS_BYTE = '+'; + public static final byte TILDE_BYTE = '~'; + public static final byte UNDERSCORE_BYTE = '_'; public static final byte[] BYTES_TRUE = toByteArray(1); public static final byte[] BYTES_FALSE = toByteArray(0); @@ -49,7 +58,7 @@ public final class Protocol { private static final String NOPERM_PREFIX = "NOPERM"; private Protocol() { - // this prevent the class from instantiation + throw new InstantiationError("Must not instantiate this class"); } public static void sendCommand(final RedisOutputStream os, CommandArguments args) { @@ -124,27 +133,40 @@ private static String[] parseTargetHostAndSlot(String clusterRedirectResponse) { private static Object process(final RedisInputStream is) { final byte b = is.readByte(); + //System.out.println((char) b); switch (b) { case PLUS_BYTE: - return processStatusCodeReply(is); + return is.readLineBytes(); case DOLLAR_BYTE: + case EQUAL_BYTE: return processBulkReply(is); case ASTERISK_BYTE: return processMultiBulkReply(is); + case UNDERSCORE_BYTE: + return is.readNullCrLf(); + case HASH_BYTE: + return is.readBooleanCrLf(); case COLON_BYTE: - return processInteger(is); + return is.readLongCrLf(); + case COMMA_BYTE: + return is.readDoubleCrLf(); + case LEFT_BRACE_BYTE: + return is.readBigIntegerCrLf(); + case PERCENT_BYTE: // TODO: currently just to start working with HELLO + return processMapKeyValueReply(is); + case TILDE_BYTE: // TODO: + return processMultiBulkReply(is); + case GREATER_THAN_BYTE: + return processMultiBulkReply(is); case MINUS_BYTE: processError(is); return null; + // TODO: Blob error '!' default: throw new JedisConnectionException("Unknown reply: " + (char) b); } } - private static byte[] processStatusCodeReply(final RedisInputStream is) { - return is.readLineBytes(); - } - private static byte[] processBulkReply(final RedisInputStream is) { final int len = is.readIntCrLf(); if (len == -1) { @@ -168,15 +190,10 @@ private static byte[] processBulkReply(final RedisInputStream is) { return read; } - private static Long processInteger(final RedisInputStream is) { - return is.readLongCrLf(); - } - private static List processMultiBulkReply(final RedisInputStream is) { + // private static List processMultiBulkReply(final int num, final RedisInputStream is) { final int num = is.readIntCrLf(); - if (num == -1) { - return null; - } + if (num == -1) return null; final List ret = new ArrayList<>(num); for (int i = 0; i < num; i++) { try { @@ -188,6 +205,18 @@ private static List processMultiBulkReply(final RedisInputStream is) { return ret; } + // private static List processMultiBulkReply(final RedisInputStream is) { + // private static List processMultiBulkReply(final int num, final RedisInputStream is) { + private static List processMapKeyValueReply(final RedisInputStream is) { + final int num = is.readIntCrLf(); + if (num == -1) return null; + final List ret = new ArrayList<>(num); + for (int i = 0; i < num; i++) { + ret.add(new KeyValue(process(is), process(is))); + } + return ret; + } + public static Object read(final RedisInputStream is) { return process(is); } @@ -216,28 +245,34 @@ public static final byte[] toByteArray(final double value) { public static enum Command implements ProtocolCommand { - PING, SET, GET, GETDEL, GETEX, QUIT, EXISTS, DEL, UNLINK, TYPE, FLUSHDB, KEYS, RANDOMKEY, MOVE, - RENAME, RENAMENX, DBSIZE, EXPIRE, EXPIREAT, TTL, SELECT, FLUSHALL, GETSET, MGET, SETNX, SETEX, - MSET, MSETNX, DECRBY, DECR, INCRBY, INCR, APPEND, SUBSTR, HSET, HGET, HSETNX, HMSET, HMGET, - HINCRBY, HEXISTS, HDEL, HLEN, HKEYS, HVALS, HGETALL, HRANDFIELD, HINCRBYFLOAT, HSTRLEN, MIGRATE, + PING, AUTH, HELLO, SET, GET, GETDEL, GETEX, EXISTS, DEL, UNLINK, TYPE, FLUSHDB, FLUSHALL, MOVE, + KEYS, RANDOMKEY, RENAME, RENAMENX, DUMP, RESTORE, DBSIZE, SELECT, SWAPDB, MIGRATE, ECHO, // + EXPIRE, EXPIREAT, EXPIRETIME, PEXPIRE, PEXPIREAT, PEXPIRETIME, TTL, PTTL, // <-- key expiration + MULTI, DISCARD, EXEC, WATCH, UNWATCH, SORT, SORT_RO, INFO, SHUTDOWN, MONITOR, CONFIG, LCS, // + GETSET, MGET, SETNX, SETEX, PSETEX, MSET, MSETNX, DECR, DECRBY, INCR, INCRBY, INCRBYFLOAT, + STRLEN, APPEND, SUBSTR, // <-- string + SETBIT, GETBIT, BITPOS, SETRANGE, GETRANGE, BITCOUNT, BITOP, BITFIELD, BITFIELD_RO, // <-- bit (string) + HSET, HGET, HSETNX, HMSET, HMGET, HINCRBY, HEXISTS, HDEL, HLEN, HKEYS, HVALS, HGETALL, HSTRLEN, + HRANDFIELD, HINCRBYFLOAT, // <-- hash RPUSH, LPUSH, LLEN, LRANGE, LTRIM, LINDEX, LSET, LREM, LPOP, RPOP, BLPOP, BRPOP, LINSERT, LPOS, - RPOPLPUSH, BRPOPLPUSH, BLMOVE, LMOVE, SADD, SMEMBERS, SREM, SPOP, SMOVE, SCARD, SRANDMEMBER, - SINTER, SINTERSTORE, SUNION, SUNIONSTORE, SDIFF, SDIFFSTORE, SISMEMBER, SMISMEMBER, SINTERCARD, - MULTI, DISCARD, EXEC, WATCH, UNWATCH, SORT, SORT_RO, AUTH, INFO, SHUTDOWN, MONITOR, CONFIG, LCS, - SUBSCRIBE, PUBLISH, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBSUB, STRLEN, LPUSHX, RPUSHX, ECHO, + RPOPLPUSH, BRPOPLPUSH, BLMOVE, LMOVE, LMPOP, BLMPOP, LPUSHX, RPUSHX, // <-- list + SADD, SMEMBERS, SREM, SPOP, SMOVE, SCARD, SRANDMEMBER, SINTER, SINTERSTORE, SUNION, SUNIONSTORE, + SDIFF, SDIFFSTORE, SISMEMBER, SMISMEMBER, SINTERCARD, // <-- set ZADD, ZDIFF, ZDIFFSTORE, ZRANGE, ZREM, ZINCRBY, ZRANK, ZREVRANK, ZREVRANGE, ZRANDMEMBER, ZCARD, ZSCORE, ZPOPMAX, ZPOPMIN, ZCOUNT, ZUNION, ZUNIONSTORE, ZINTER, ZINTERSTORE, ZRANGEBYSCORE, ZREVRANGEBYSCORE, ZREMRANGEBYRANK, ZREMRANGEBYSCORE, ZLEXCOUNT, ZRANGEBYLEX, ZREVRANGEBYLEX, - ZREMRANGEBYLEX, ZMSCORE, ZRANGESTORE, ZINTERCARD, SAVE, BGSAVE, BGREWRITEAOF, LASTSAVE, PERSIST, - SETBIT, GETBIT, BITPOS, SETRANGE, GETRANGE, EVAL, EVALSHA, SCRIPT, SLOWLOG, OBJECT, BITCOUNT, - BITOP, SENTINEL, DUMP, RESTORE, PEXPIRE, PEXPIREAT, PTTL, INCRBYFLOAT, PSETEX, CLIENT, TIME, - SCAN, HSCAN, SSCAN, ZSCAN, WAIT, CLUSTER, ASKING, READONLY, READWRITE, SLAVEOF, REPLICAOF, COPY, - PFADD, PFCOUNT, PFMERGE, MODULE, ACL, GEOADD, GEODIST, GEOHASH, GEOPOS, GEORADIUS, GEORADIUS_RO, - GEORADIUSBYMEMBER, GEORADIUSBYMEMBER_RO, BITFIELD, TOUCH, SWAPDB, MEMORY, BZPOPMIN, BZPOPMAX, + ZREMRANGEBYLEX, ZMSCORE, ZRANGESTORE, ZINTERCARD, ZMPOP, BZMPOP, BZPOPMIN, BZPOPMAX, // <-- zset + GEOADD, GEODIST, GEOHASH, GEOPOS, GEORADIUS, GEORADIUS_RO, GEOSEARCH, GEOSEARCHSTORE, + GEORADIUSBYMEMBER, GEORADIUSBYMEMBER_RO, // <-- geo + PFADD, PFCOUNT, PFMERGE, // <-- hyper log log XADD, XLEN, XDEL, XTRIM, XRANGE, XREVRANGE, XREAD, XACK, XGROUP, XREADGROUP, XPENDING, XCLAIM, - XAUTOCLAIM, XINFO, BITFIELD_RO, ROLE, FAILOVER, GEOSEARCH, GEOSEARCHSTORE, EVAL_RO, EVALSHA_RO, - LOLWUT, EXPIRETIME, PEXPIRETIME, FUNCTION, FCALL, FCALL_RO, LMPOP, BLMPOP, ZMPOP, BZMPOP, - COMMAND, LATENCY, @Deprecated STRALGO; + XAUTOCLAIM, XINFO, // <-- stream + EVAL, EVALSHA, SCRIPT, EVAL_RO, EVALSHA_RO, FUNCTION, FCALL, FCALL_RO, // <-- program + SUBSCRIBE, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBLISH, PUBSUB, + SSUBSCRIBE, SUNSUBSCRIBE, SPUBLISH, // <-- pub sub + SAVE, BGSAVE, BGREWRITEAOF, LASTSAVE, PERSIST, ROLE, FAILOVER, SLOWLOG, OBJECT, CLIENT, TIME, + SCAN, HSCAN, SSCAN, ZSCAN, WAIT, CLUSTER, ASKING, READONLY, READWRITE, SLAVEOF, REPLICAOF, COPY, + SENTINEL, MODULE, ACL, TOUCH, MEMORY, LOLWUT, COMMAND, RESET, LATENCY, WAITAOF; private final byte[] raw; @@ -253,18 +288,19 @@ public byte[] getRaw() { public static enum Keyword implements Rawable { - AGGREGATE, ALPHA, BY, GET, LIMIT, NO, NOSORT, ONE, SET, STORE, WEIGHTS, WITHSCORES, RESETSTAT, - REWRITE, RESET, FLUSH, EXISTS, LOAD, LEN, HELP, SCHEDULE, MATCH, COUNT, TYPE, KEYS, REFCOUNT, - ENCODING, IDLETIME, FREQ, REPLACE, GETNAME, SETNAME, LIST, ID, KILL, PAUSE, UNPAUSE, UNBLOCK, + AGGREGATE, ALPHA, BY, GET, LIMIT, NO, NOSORT, ONE, SET, STORE, WEIGHTS, WITHSCORE, WITHSCORES, + RESETSTAT, REWRITE, RESET, FLUSH, EXISTS, LOAD, LEN, HELP, SCHEDULE, MATCH, COUNT, TYPE, KEYS, + REFCOUNT, ENCODING, IDLETIME, FREQ, REPLACE, GETNAME, SETNAME, SETINFO, LIST, ID, KILL, PERSIST, STREAMS, CREATE, MKSTREAM, SETID, DESTROY, DELCONSUMER, MAXLEN, GROUP, IDLE, TIME, BLOCK, NOACK, RETRYCOUNT, STREAM, GROUPS, CONSUMERS, JUSTID, WITHVALUES, NOMKSTREAM, MINID, CREATECONSUMER, SETUSER, GETUSER, DELUSER, WHOAMI, USERS, CAT, GENPASS, LOG, SAVE, DRYRUN, COPY, AUTH, AUTH2, - NX, XX, EX, PX, EXAT, PXAT, CH, ABSTTL, KEEPTTL, INCR, INFO, CHANNELS, NUMPAT, NUMSUB, NOW, REV, - WITHCOORD, WITHDIST, WITHHASH, ANY, FROMMEMBER, FROMLONLAT, BYRADIUS, BYBOX, BYLEX, BYSCORE, + NX, XX, EX, PX, EXAT, PXAT, ABSTTL, KEEPTTL, INCR, LT, GT, CH, INFO, PAUSE, UNPAUSE, UNBLOCK, + REV, WITHCOORD, WITHDIST, WITHHASH, ANY, FROMMEMBER, FROMLONLAT, BYRADIUS, BYBOX, BYLEX, BYSCORE, STOREDIST, TO, FORCE, TIMEOUT, DB, UNLOAD, ABORT, IDX, MINMATCHLEN, WITHMATCHLEN, FULL, DELETE, LIBRARYNAME, WITHCODE, DESCRIPTION, GETKEYS, GETKEYSANDFLAGS, DOCS, FILTERBY, DUMP, - MODULE, ACLCAT, PATTERN, DOCTOR, USAGE, SAMPLES, PURGE, STATS, LOADEX, CONFIG, ARGS, - @Deprecated ASC, @Deprecated DESC, @Deprecated LCS, @Deprecated STRINGS; + MODULE, ACLCAT, PATTERN, DOCTOR, USAGE, SAMPLES, PURGE, STATS, LOADEX, CONFIG, ARGS, RANK, + NOW, VERSION, ADDR, SKIPME, USER, LADDR, + CHANNELS, NUMPAT, NUMSUB, SHARDCHANNELS, SHARDNUMSUB; private final byte[] raw; @@ -301,7 +337,8 @@ public byte[] getRaw() { public static enum ResponseKeyword implements Rawable { - SUBSCRIBE, PSUBSCRIBE, UNSUBSCRIBE, PUNSUBSCRIBE, MESSAGE, PMESSAGE, PONG; + SUBSCRIBE, PSUBSCRIBE, UNSUBSCRIBE, PUNSUBSCRIBE, MESSAGE, PMESSAGE, PONG, + SSUBSCRIBE, SUNSUBSCRIBE, SMESSAGE; private final byte[] raw; @@ -319,7 +356,8 @@ public static enum ClusterKeyword implements Rawable { MEET, RESET, INFO, FAILOVER, SLOTS, NODES, REPLICAS, SLAVES, MYID, ADDSLOTS, DELSLOTS, GETKEYSINSLOT, SETSLOT, NODE, MIGRATING, IMPORTING, STABLE, FORGET, FLUSHSLOTS, KEYSLOT, - COUNTKEYSINSLOT, SAVECONFIG, REPLICATE, LINKS, ADDSLOTSRANGE, DELSLOTSRANGE, BUMPEPOCH; + COUNTKEYSINSLOT, SAVECONFIG, REPLICATE, LINKS, ADDSLOTSRANGE, DELSLOTSRANGE, BUMPEPOCH, + MYSHARDID, SHARDS; private final byte[] raw; diff --git a/src/main/java/redis/clients/jedis/Queable.java b/src/main/java/redis/clients/jedis/Queable.java deleted file mode 100644 index 2fe7c5e3ba..0000000000 --- a/src/main/java/redis/clients/jedis/Queable.java +++ /dev/null @@ -1,31 +0,0 @@ -package redis.clients.jedis; - -import java.util.LinkedList; -import java.util.Queue; - -public class Queable { - - private final Queue> pipelinedResponses = new LinkedList<>(); - - protected final void clean() { - pipelinedResponses.clear(); - } - -// protected final void generateResponse(Object data) { -// pipelinedResponses.poll().set(data); - protected final Response generateResponse(Object data) { - Response response = pipelinedResponses.poll(); - response.set(data); - return response; - } - - protected final Response enqueResponse(Builder builder) { - Response lr = new Response<>(builder); - pipelinedResponses.add(lr); - return lr; - } - - protected final int getPipelinedResponseLength() { - return pipelinedResponses.size(); - } -} diff --git a/src/main/java/redis/clients/jedis/RedisCredentials.java b/src/main/java/redis/clients/jedis/RedisCredentials.java new file mode 100644 index 0000000000..b0b1e4b04f --- /dev/null +++ b/src/main/java/redis/clients/jedis/RedisCredentials.java @@ -0,0 +1,15 @@ +package redis.clients.jedis; + +public interface RedisCredentials { + + /** + * @return Redis ACL user + */ + default String getUser() { + return null; + } + + default char[] getPassword() { + return null; + } +} diff --git a/src/main/java/redis/clients/jedis/RedisCredentialsProvider.java b/src/main/java/redis/clients/jedis/RedisCredentialsProvider.java new file mode 100644 index 0000000000..59345cc709 --- /dev/null +++ b/src/main/java/redis/clients/jedis/RedisCredentialsProvider.java @@ -0,0 +1,27 @@ +package redis.clients.jedis; + +import java.util.function.Supplier; + +public interface RedisCredentialsProvider extends Supplier { + + /** + * Prepare {@link RedisCredentials} before {@link RedisCredentialsProvider#get()} is called. + *

+ * An application may: + *

    + *
  • Load credentials from the credentials management system
  • + *
  • Reload credentials when credentials are rotated.
  • + *
  • Reload credentials after an authentication error (e.g. NOAUTH, WRONGPASS, etc).
  • + *
  • Minimize the time that the password lives in the memory (in combination with + * {@link RedisCredentialsProvider#cleanUp()}).
  • + *
+ */ + default void prepare() { } + + /** + * Clean up credentials (e.g. from memory). + * + * @see RedisCredentialsProvider#prepare() + */ + default void cleanUp() { } +} diff --git a/src/main/java/redis/clients/jedis/RedisProtocol.java b/src/main/java/redis/clients/jedis/RedisProtocol.java new file mode 100644 index 0000000000..2a3ea72470 --- /dev/null +++ b/src/main/java/redis/clients/jedis/RedisProtocol.java @@ -0,0 +1,17 @@ +package redis.clients.jedis; + +public enum RedisProtocol { + + RESP2("2"), + RESP3("3"); + + private final String version; + + private RedisProtocol(String ver) { + this.version = ver; + } + + public String version() { + return version; + } +} diff --git a/src/main/java/redis/clients/jedis/ReliableTransaction.java b/src/main/java/redis/clients/jedis/ReliableTransaction.java index f060d4f1fa..c750bdb9d9 100644 --- a/src/main/java/redis/clients/jedis/ReliableTransaction.java +++ b/src/main/java/redis/clients/jedis/ReliableTransaction.java @@ -1,7 +1,20 @@ package redis.clients.jedis; +import static redis.clients.jedis.Protocol.Command.DISCARD; +import static redis.clients.jedis.Protocol.Command.EXEC; +import static redis.clients.jedis.Protocol.Command.MULTI; +import static redis.clients.jedis.Protocol.Command.UNWATCH; +import static redis.clients.jedis.Protocol.Command.WATCH; + +import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; +import java.util.Queue; + +import redis.clients.jedis.exceptions.JedisConnectionException; +import redis.clients.jedis.exceptions.JedisDataException; import redis.clients.jedis.exceptions.JedisException; +import redis.clients.jedis.graph.GraphCommandObjects; /** * ReliableTransaction is a transaction where commands are immediately sent to Redis server and the @@ -11,13 +24,22 @@ public class ReliableTransaction extends TransactionBase { private static final String QUEUED_STR = "QUEUED"; + private final Queue> pipelinedResponses = new LinkedList<>(); + protected final Connection connection; + private final boolean closeConnection; + + private boolean broken = false; + private boolean inWatch = false; + private boolean inMulti = false; + /** * Creates a new transaction. * * A MULTI command will be executed. WATCH/UNWATCH/MULTI commands must not be called with this object. + * @param connection connection */ public ReliableTransaction(Connection connection) { - super(connection); + this(connection, true); } /** @@ -30,41 +52,155 @@ public ReliableTransaction(Connection connection) { * @param doMulti {@code false} should be set to enable manual WATCH, UNWATCH and MULTI */ public ReliableTransaction(Connection connection, boolean doMulti) { - super(connection, doMulti); + this(connection, doMulti, false); + } + + /** + * Creates a new transaction. + * + * A user wanting to WATCH/UNWATCH keys followed by a call to MULTI ({@link #multi()}) it should + * be {@code doMulti=false}. + * + * @param connection connection + * @param doMulti {@code false} should be set to enable manual WATCH, UNWATCH and MULTI + * @param closeConnection should the 'connection' be closed when 'close()' is called? + */ + public ReliableTransaction(Connection connection, boolean doMulti, boolean closeConnection) { + this.connection = connection; + this.closeConnection = closeConnection; + setGraphCommands(new GraphCommandObjects(this.connection)); + if (doMulti) multi(); } @Override - protected final void processMultiResponse() { + public final void multi() { + connection.sendCommand(MULTI); String status = connection.getStatusCodeReply(); if (!"OK".equals(status)) { throw new JedisException("MULTI command failed. Received response: " + status); } + inMulti = true; } @Override - protected final void processAppendStatus() { + public String watch(final String... keys) { + connection.sendCommand(WATCH, keys); + String status = connection.getStatusCodeReply(); + inWatch = true; + return status; + } + + @Override + public String watch(final byte[]... keys) { + connection.sendCommand(WATCH, keys); + String status = connection.getStatusCodeReply(); + inWatch = true; + return status; + } + + @Override + public String unwatch() { + connection.sendCommand(UNWATCH); + String status = connection.getStatusCodeReply(); + inWatch = false; + return status; + } + + @Override + protected final Response appendCommand(CommandObject commandObject) { + connection.sendCommand(commandObject.getArguments()); String status = connection.getStatusCodeReply(); if (!QUEUED_STR.equals(status)) { throw new JedisException(status); } + Response response = new Response<>(commandObject.getBuilder()); + pipelinedResponses.add(response); + return response; } @Override - protected final void processPipelinedResponses() { - // do nothing + public final void close() { + try { + clear(); + } finally { + if (closeConnection) { + connection.close(); + } + } + } + + @Deprecated // TODO: private + public final void clear() { + if (broken) { + return; + } + if (inMulti) { + discard(); + } else if (inWatch) { + unwatch(); + } } @Override - public final List exec() { - return super.exec(); + public List exec() { + if (!inMulti) { + throw new IllegalStateException("EXEC without MULTI"); + } + + try { + // processPipelinedResponses(pipelinedResponses.size()); + // do nothing + connection.sendCommand(EXEC); + + List unformatted = connection.getObjectMultiBulkReply(); + if (unformatted == null) { + pipelinedResponses.clear(); + return null; + } + + List formatted = new ArrayList<>(unformatted.size()); + for (Object o : unformatted) { + try { + Response response = pipelinedResponses.poll(); + response.set(o); + formatted.add(response.get()); + } catch (JedisDataException e) { + formatted.add(e); + } + } + return formatted; + } catch (JedisConnectionException jce) { + broken = true; + throw jce; + } finally { + inMulti = false; + inWatch = false; + pipelinedResponses.clear(); + } } @Override - public final String discard() { - String status = super.discard(); - if (!"OK".equals(status)) { - throw new JedisException("DISCARD command failed. Received response: " + status); + public String discard() { + if (!inMulti) { + throw new IllegalStateException("DISCARD without MULTI"); + } + + try { + // processPipelinedResponses(pipelinedResponses.size()); + // do nothing + connection.sendCommand(DISCARD); + String status = connection.getStatusCodeReply(); + if (!"OK".equals(status)) { + throw new JedisException("DISCARD command failed. Received response: " + status); + } + return status; + } catch (JedisConnectionException jce) { + broken = true; + throw jce; + } finally { + inMulti = false; + inWatch = false; + pipelinedResponses.clear(); } - return status; } } diff --git a/src/main/java/redis/clients/jedis/ScanIteration.java b/src/main/java/redis/clients/jedis/ScanIteration.java new file mode 100644 index 0000000000..8744df991e --- /dev/null +++ b/src/main/java/redis/clients/jedis/ScanIteration.java @@ -0,0 +1,50 @@ +package redis.clients.jedis; + +import java.util.Collection; +import java.util.function.Function; + +import redis.clients.jedis.params.ScanParams; +import redis.clients.jedis.Protocol.Keyword; +import redis.clients.jedis.providers.ConnectionProvider; +import redis.clients.jedis.resps.ScanResult; +import redis.clients.jedis.util.JedisCommandIterationBase; + +public class ScanIteration extends JedisCommandIterationBase, String> { + + private final int count; + private final Function args; + + public ScanIteration(ConnectionProvider connectionProvider, int batchCount, String match) { + super(connectionProvider, BuilderFactory.SCAN_RESPONSE); + this.count = batchCount; + this.args = (cursor) -> new CommandArguments(Protocol.Command.SCAN).add(cursor) + .add(Keyword.MATCH).add(match).add(Keyword.COUNT).add(count); + } + + public ScanIteration(ConnectionProvider connectionProvider, int batchCount, String match, String type) { + super(connectionProvider, BuilderFactory.SCAN_RESPONSE); + this.count = batchCount; + this.args = (cursor) -> new CommandArguments(Protocol.Command.SCAN).add(cursor) + .add(Keyword.MATCH).add(match).add(Keyword.COUNT).add(count).add(Keyword.TYPE).add(type); + } + + @Override + protected boolean isNodeCompleted(ScanResult reply) { + return reply.isCompleteIteration(); + } + + @Override + protected CommandArguments initCommandArguments() { + return args.apply(ScanParams.SCAN_POINTER_START); + } + + @Override + protected CommandArguments nextCommandArguments(ScanResult lastReply) { + return args.apply(lastReply.getCursor()); + } + + @Override + protected Collection convertBatchToData(ScanResult batch) { + return batch.getResult(); + } +} diff --git a/src/main/java/redis/clients/jedis/ShardedCommandArguments.java b/src/main/java/redis/clients/jedis/ShardedCommandArguments.java index 30552eb7e8..7eec0561a2 100644 --- a/src/main/java/redis/clients/jedis/ShardedCommandArguments.java +++ b/src/main/java/redis/clients/jedis/ShardedCommandArguments.java @@ -6,6 +6,10 @@ import redis.clients.jedis.exceptions.JedisException; import redis.clients.jedis.util.Hashing; +/** + * @deprecated Sharding/Sharded feature will be removed in next major release. + */ +@Deprecated public class ShardedCommandArguments extends CommandArguments { private final Hashing algo; diff --git a/src/main/java/redis/clients/jedis/ShardedCommandObjects.java b/src/main/java/redis/clients/jedis/ShardedCommandObjects.java index da46d2048d..44604c00eb 100644 --- a/src/main/java/redis/clients/jedis/ShardedCommandObjects.java +++ b/src/main/java/redis/clients/jedis/ShardedCommandObjects.java @@ -12,7 +12,12 @@ import redis.clients.jedis.resps.ScanResult; import redis.clients.jedis.util.Hashing; import redis.clients.jedis.util.JedisClusterHashTag; +import redis.clients.jedis.util.KeyValue; +/** + * @deprecated Sharding/Sharded feature will be removed in next major release. + */ +@Deprecated public class ShardedCommandObjects extends CommandObjects { private final Hashing algo; @@ -109,4 +114,9 @@ public final CommandObject> scan(byte[] cursor, ScanParams pa public final CommandObject waitReplicas(int replicas, long timeout) { throw new UnsupportedOperationException(); } + + @Override + public CommandObject> waitAOF(long numLocal, long numReplicas, long timeout) { + throw new UnsupportedOperationException(); + } } diff --git a/src/main/java/redis/clients/jedis/ShardedPipeline.java b/src/main/java/redis/clients/jedis/ShardedPipeline.java index 7548353497..8ad89cc59e 100644 --- a/src/main/java/redis/clients/jedis/ShardedPipeline.java +++ b/src/main/java/redis/clients/jedis/ShardedPipeline.java @@ -7,6 +7,12 @@ import redis.clients.jedis.util.Hashing; import redis.clients.jedis.util.IOUtils; +/** + * WARNING: RESP3 is not properly implemented for ShardedPipeline. + * + * @deprecated Sharding/Sharded feature will be removed in next major release. + */ +@Deprecated public class ShardedPipeline extends MultiNodePipelineBase { private final ShardedConnectionProvider provider; diff --git a/src/main/java/redis/clients/jedis/StreamEntryID.java b/src/main/java/redis/clients/jedis/StreamEntryID.java index 66683d9038..9644010d7c 100644 --- a/src/main/java/redis/clients/jedis/StreamEntryID.java +++ b/src/main/java/redis/clients/jedis/StreamEntryID.java @@ -55,8 +55,8 @@ public int hashCode() { @Override public int compareTo(StreamEntryID other) { - int timeComapre = Long.compare(this.time, other.time); - return timeComapre != 0 ? timeComapre : Long.compare(this.sequence, other.sequence); + int timeCompare = Long.compare(this.time, other.time); + return timeCompare != 0 ? timeCompare : Long.compare(this.sequence, other.sequence); } public long getTime() { diff --git a/src/main/java/redis/clients/jedis/Transaction.java b/src/main/java/redis/clients/jedis/Transaction.java index feb6f0af11..0dccd655a0 100644 --- a/src/main/java/redis/clients/jedis/Transaction.java +++ b/src/main/java/redis/clients/jedis/Transaction.java @@ -1,18 +1,40 @@ package redis.clients.jedis; +import static redis.clients.jedis.Protocol.Command.DISCARD; +import static redis.clients.jedis.Protocol.Command.EXEC; +import static redis.clients.jedis.Protocol.Command.MULTI; +import static redis.clients.jedis.Protocol.Command.UNWATCH; +import static redis.clients.jedis.Protocol.Command.WATCH; + +import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; +import java.util.Queue; + +import redis.clients.jedis.exceptions.JedisConnectionException; +import redis.clients.jedis.exceptions.JedisDataException; +import redis.clients.jedis.graph.GraphCommandObjects; /** * A pipeline based transaction. */ public class Transaction extends TransactionBase { - private final Jedis jedis; + private final Queue> pipelinedResponses = new LinkedList<>(); + + private Jedis jedis = null; + + protected final Connection connection; + private final boolean closeConnection; + + private boolean broken = false; + private boolean inWatch = false; + private boolean inMulti = false; // Legacy - to support Jedis.multi() // TODO: Should be package private ?? public Transaction(Jedis jedis) { - super(jedis.getConnection()); + this(jedis.getConnection()); this.jedis = jedis; } @@ -21,10 +43,10 @@ public Transaction(Jedis jedis) { * * A MULTI command will be added to be sent to server. WATCH/UNWATCH/MULTI commands must not be * called with this object. + * @param connection connection */ public Transaction(Connection connection) { - super(connection); - this.jedis = null; + this(connection, true); } /** @@ -37,49 +59,156 @@ public Transaction(Connection connection) { * @param doMulti {@code false} should be set to enable manual WATCH, UNWATCH and MULTI */ public Transaction(Connection connection, boolean doMulti) { - super(connection, doMulti); - this.jedis = null; + this(connection, doMulti, false); + } + + /** + * Creates a new transaction. + * + * A user wanting to WATCH/UNWATCH keys followed by a call to MULTI ({@link #multi()}) it should + * be {@code doMulti=false}. + * + * @param connection connection + * @param doMulti {@code false} should be set to enable manual WATCH, UNWATCH and MULTI + * @param closeConnection should the 'connection' be closed when 'close()' is called? + */ + public Transaction(Connection connection, boolean doMulti, boolean closeConnection) { + this.connection = connection; + this.closeConnection = closeConnection; + setGraphCommands(new GraphCommandObjects(this.connection)); + if (doMulti) multi(); + } + + @Override + public final void multi() { + connection.sendCommand(MULTI); + // processMultiResponse(); // do nothing + inMulti = true; + } + + @Override + public String watch(final String... keys) { + connection.sendCommand(WATCH, keys); + String status = connection.getStatusCodeReply(); + inWatch = true; + return status; } @Override - protected final void processMultiResponse() { - // do nothing + public String watch(final byte[]... keys) { + connection.sendCommand(WATCH, keys); + String status = connection.getStatusCodeReply(); + inWatch = true; + return status; } @Override - protected final void processAppendStatus() { - // do nothing + public String unwatch() { + connection.sendCommand(UNWATCH); + String status = connection.getStatusCodeReply(); + inWatch = false; + return status; } @Override - protected final void processPipelinedResponses() { - // ignore QUEUED or ERROR - connection.getMany(1 + getPipelinedResponseLength()); + protected final Response appendCommand(CommandObject commandObject) { + connection.sendCommand(commandObject.getArguments()); + // processAppendStatus(); // do nothing + Response response = new Response<>(commandObject.getBuilder()); + pipelinedResponses.add(response); + return response; } @Override - public final List exec() { - List ret; + public final void close() { try { - ret = super.exec(); + clear(); } finally { + if (closeConnection) { + connection.close(); + } + } + } + + @Deprecated // TODO: private + public final void clear() { + if (broken) { + return; + } + if (inMulti) { + discard(); + } else if (inWatch) { + unwatch(); + } + } + + @Override + public List exec() { + if (!inMulti) { + throw new IllegalStateException("EXEC without MULTI"); + } + + try { + // ignore QUEUED (or ERROR) + // processPipelinedResponses(pipelinedResponses.size()); + connection.getMany(1 + pipelinedResponses.size()); + + connection.sendCommand(EXEC); + + List unformatted = connection.getObjectMultiBulkReply(); + if (unformatted == null) { + pipelinedResponses.clear(); + return null; + } + + List formatted = new ArrayList<>(unformatted.size()); + for (Object o : unformatted) { + try { + Response response = pipelinedResponses.poll(); + response.set(o); + formatted.add(response.get()); + } catch (JedisDataException e) { + formatted.add(e); + } + } + return formatted; + } catch (JedisConnectionException jce) { + broken = true; + throw jce; + } finally { + inMulti = false; + inWatch = false; + pipelinedResponses.clear(); if (jedis != null) { jedis.resetState(); } } - return ret; } @Override - public final String discard() { - String ret; + public String discard() { + if (!inMulti) { + throw new IllegalStateException("DISCARD without MULTI"); + } + try { - ret = super.discard(); + // ignore QUEUED (or ERROR) + // processPipelinedResponses(pipelinedResponses.size()); + connection.getMany(1 + pipelinedResponses.size()); + + connection.sendCommand(DISCARD); + + return connection.getStatusCodeReply(); + } catch (JedisConnectionException jce) { + broken = true; + throw jce; } finally { + inMulti = false; + inWatch = false; + pipelinedResponses.clear(); if (jedis != null) { jedis.resetState(); } } - return ret; } } diff --git a/src/main/java/redis/clients/jedis/TransactionBase.java b/src/main/java/redis/clients/jedis/TransactionBase.java index cc4f92b354..805a1120c4 100644 --- a/src/main/java/redis/clients/jedis/TransactionBase.java +++ b/src/main/java/redis/clients/jedis/TransactionBase.java @@ -1,4379 +1,12 @@ package redis.clients.jedis; -import static redis.clients.jedis.Protocol.Command.DISCARD; -import static redis.clients.jedis.Protocol.Command.EXEC; -import static redis.clients.jedis.Protocol.Command.MULTI; -import static redis.clients.jedis.Protocol.Command.UNWATCH; -import static redis.clients.jedis.Protocol.Command.WATCH; - -import java.io.Closeable; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import org.json.JSONArray; - -import redis.clients.jedis.args.*; -import redis.clients.jedis.bloom.*; -import redis.clients.jedis.commands.PipelineBinaryCommands; -import redis.clients.jedis.commands.PipelineCommands; -import redis.clients.jedis.commands.ProtocolCommand; -import redis.clients.jedis.commands.RedisModulePipelineCommands; -import redis.clients.jedis.exceptions.JedisConnectionException; -import redis.clients.jedis.exceptions.JedisDataException; -import redis.clients.jedis.graph.GraphCommandObjects; -import redis.clients.jedis.graph.ResultSet; -import redis.clients.jedis.json.JsonSetParams; -import redis.clients.jedis.json.Path; -import redis.clients.jedis.json.Path2; -import redis.clients.jedis.params.*; -import redis.clients.jedis.resps.*; -import redis.clients.jedis.search.*; -import redis.clients.jedis.search.aggr.AggregationBuilder; -import redis.clients.jedis.search.aggr.AggregationResult; -import redis.clients.jedis.search.schemafields.SchemaField; -import redis.clients.jedis.timeseries.*; -import redis.clients.jedis.util.KeyValue; - -public abstract class TransactionBase extends Queable implements PipelineCommands, - PipelineBinaryCommands, RedisModulePipelineCommands, Closeable { - - protected final Connection connection; - private final CommandObjects commandObjects; - private final GraphCommandObjects graphCommandObjects; - - private boolean broken = false; - private boolean inWatch = false; - private boolean inMulti = false; - - /** - * Creates a new transaction. - * - * A MULTI command will be added to be sent to server. WATCH/UNWATCH/MULTI commands must not be - * called with this object. - */ - public TransactionBase(Connection connection) { - this(connection, true); - } - - /** - * Creates a new transaction. - * - * A user wanting to WATCH/UNWATCH keys followed by a call to MULTI ({@link #multi()}) it should - * be {@code doMulti=false}. - * - * @param connection connection - * @param doMulti {@code false} should be set to enable manual WATCH, UNWATCH and MULTI - */ - public TransactionBase(Connection connection, boolean doMulti) { - this.connection = connection; - this.commandObjects = new CommandObjects(); - this.graphCommandObjects = new GraphCommandObjects(this.connection); - if (doMulti) multi(); - } - - public final void multi() { - connection.sendCommand(MULTI); - processMultiResponse(); - inMulti = true; - } - - public String watch(final String... keys) { - connection.sendCommand(WATCH, keys); - String status = connection.getStatusCodeReply(); - inWatch = true; - return status; - } - - public String watch(final byte[]... keys) { - connection.sendCommand(WATCH, keys); - String status = connection.getStatusCodeReply(); - inWatch = true; - return status; - } - - public String unwatch() { - connection.sendCommand(UNWATCH); - String status = connection.getStatusCodeReply(); - inWatch = false; - return status; - } - - protected abstract void processMultiResponse(); - - protected abstract void processAppendStatus(); - - protected final Response appendCommand(CommandObject commandObject) { - connection.sendCommand(commandObject.getArguments()); - processAppendStatus(); - return enqueResponse(commandObject.getBuilder()); - } - - @Override - public final void close() { - clear(); - } - - public final void clear() { - if (broken) { - return; - } - if (inMulti) { - discard(); - } else if (inWatch) { - unwatch(); - } - } - - protected abstract void processPipelinedResponses(); - - public List exec() { - if (!inMulti) { - throw new IllegalStateException("EXEC without MULTI"); - } - - try { - processPipelinedResponses(); - connection.sendCommand(EXEC); - - List unformatted = connection.getObjectMultiBulkReply(); - if (unformatted == null) { - clean(); - return null; - } - - List formatted = new ArrayList<>(unformatted.size()); - for (Object o : unformatted) { - try { - formatted.add(generateResponse(o).get()); - } catch (JedisDataException e) { - formatted.add(e); - } - } - return formatted; - } catch (JedisConnectionException jce) { - broken = true; - throw jce; - } finally { - inMulti = false; - inWatch = false; - clean(); - } - } - - public String discard() { - if (!inMulti) { - throw new IllegalStateException("DISCARD without MULTI"); - } - - try { - processPipelinedResponses(); - connection.sendCommand(DISCARD); - return connection.getStatusCodeReply(); - } catch (JedisConnectionException jce) { - broken = true; - throw jce; - } finally { - inMulti = false; - inWatch = false; - clean(); - } - } - - @Override - public Response exists(String key) { - return appendCommand(commandObjects.exists(key)); - } - - @Override - public Response exists(String... keys) { - return appendCommand(commandObjects.exists(keys)); - } - - @Override - public Response persist(String key) { - return appendCommand(commandObjects.persist(key)); - } - - @Override - public Response type(String key) { - return appendCommand(commandObjects.type(key)); - } - - @Override - public Response dump(String key) { - return appendCommand(commandObjects.dump(key)); - } - - @Override - public Response restore(String key, long ttl, byte[] serializedValue) { - return appendCommand(commandObjects.restore(key, ttl, serializedValue)); - } - - @Override - public Response restore(String key, long ttl, byte[] serializedValue, RestoreParams params) { - return appendCommand(commandObjects.restore(key, ttl, serializedValue, params)); - } - - @Override - public Response expire(String key, long seconds) { - return appendCommand(commandObjects.expire(key, seconds)); - } - - @Override - public Response expire(String key, long seconds, ExpiryOption expiryOption) { - return appendCommand(commandObjects.expire(key, seconds, expiryOption)); - } - - @Override - public Response pexpire(String key, long milliseconds) { - return appendCommand(commandObjects.pexpire(key, milliseconds)); - } - - @Override - public Response pexpire(String key, long milliseconds, ExpiryOption expiryOption) { - return appendCommand(commandObjects.pexpire(key, milliseconds, expiryOption)); - } - - @Override - public Response expireTime(String key) { - return appendCommand(commandObjects.expireTime(key)); - } - - @Override - public Response pexpireTime(String key) { - return appendCommand(commandObjects.pexpireTime(key)); - } - - @Override - public Response expireAt(String key, long unixTime) { - return appendCommand(commandObjects.expireAt(key, unixTime)); - } - - @Override - public Response expireAt(String key, long unixTime, ExpiryOption expiryOption) { - return appendCommand(commandObjects.expireAt(key, unixTime, expiryOption)); - } - - @Override - public Response pexpireAt(String key, long millisecondsTimestamp) { - return appendCommand(commandObjects.pexpireAt(key, millisecondsTimestamp)); - } - - @Override - public Response pexpireAt(String key, long millisecondsTimestamp, ExpiryOption expiryOption) { - return appendCommand(commandObjects.pexpireAt(key, millisecondsTimestamp, expiryOption)); - } - - @Override - public Response ttl(String key) { - return appendCommand(commandObjects.ttl(key)); - } - - @Override - public Response pttl(String key) { - return appendCommand(commandObjects.pttl(key)); - } - - @Override - public Response touch(String key) { - return appendCommand(commandObjects.touch(key)); - } - - @Override - public Response touch(String... keys) { - return appendCommand(commandObjects.touch(keys)); - } - - @Override - public Response> sort(String key) { - return appendCommand(commandObjects.sort(key)); - } - - @Override - public Response sort(String key, String dstKey) { - return appendCommand(commandObjects.sort(key, dstKey)); - } - - @Override - public Response> sort(String key, SortingParams sortingParams) { - return appendCommand(commandObjects.sort(key, sortingParams)); - } - - @Override - public Response sort(String key, SortingParams sortingParams, String dstKey) { - return appendCommand(commandObjects.sort(key, sortingParams, dstKey)); - } - - @Override - public Response> sortReadonly(String key, SortingParams sortingParams) { - return appendCommand(commandObjects.sortReadonly(key, sortingParams)); - } - - @Override - public Response del(String key) { - return appendCommand(commandObjects.del(key)); - } - - @Override - public Response del(String... keys) { - return appendCommand(commandObjects.del(keys)); - } - - @Override - public Response unlink(String key) { - return appendCommand(commandObjects.unlink(key)); - } - - @Override - public Response unlink(String... keys) { - return appendCommand(commandObjects.unlink(keys)); - } - - @Override - public Response copy(String srcKey, String dstKey, boolean replace) { - return appendCommand(commandObjects.copy(srcKey, dstKey, replace)); - } - - @Override - public Response rename(String oldkey, String newkey) { - return appendCommand(commandObjects.rename(oldkey, newkey)); - } - - @Override - public Response renamenx(String oldkey, String newkey) { - return appendCommand(commandObjects.renamenx(oldkey, newkey)); - } - - @Override - public Response memoryUsage(String key) { - return appendCommand(commandObjects.memoryUsage(key)); - } - - @Override - public Response memoryUsage(String key, int samples) { - return appendCommand(commandObjects.memoryUsage(key, samples)); - } - - @Override - public Response objectRefcount(String key) { - return appendCommand(commandObjects.objectRefcount(key)); - } - - @Override - public Response objectEncoding(String key) { - return appendCommand(commandObjects.objectEncoding(key)); - } - - @Override - public Response objectIdletime(String key) { - return appendCommand(commandObjects.objectIdletime(key)); - } - - @Override - public Response objectFreq(String key) { - return appendCommand(commandObjects.objectFreq(key)); - } - - @Override - public Response migrate(String host, int port, String key, int timeout) { - return appendCommand(commandObjects.migrate(host, port, key, timeout)); - } - - @Override - public Response migrate(String host, int port, int timeout, MigrateParams params, String... keys) { - return appendCommand(commandObjects.migrate(host, port, timeout, params, keys)); - } - - @Override - public Response> keys(String pattern) { - return appendCommand(commandObjects.keys(pattern)); - } - - @Override - public Response> scan(String cursor) { - return appendCommand(commandObjects.scan(cursor)); - } - - @Override - public Response> scan(String cursor, ScanParams params) { - return appendCommand(commandObjects.scan(cursor, params)); - } - - @Override - public Response> scan(String cursor, ScanParams params, String type) { - return appendCommand(commandObjects.scan(cursor, params, type)); - } - - @Override - public Response randomKey() { - return appendCommand(commandObjects.randomKey()); - } - - @Override - public Response get(String key) { - return appendCommand(commandObjects.get(key)); - } - - @Override - public Response setGet(String key, String value, SetParams params) { - return appendCommand(commandObjects.setGet(key, value, params)); - } - - @Override - public Response getDel(String key) { - return appendCommand(commandObjects.getDel(key)); - } - - @Override - public Response getEx(String key, GetExParams params) { - return appendCommand(commandObjects.getEx(key, params)); - } - - @Override - public Response setbit(String key, long offset, boolean value) { - return appendCommand(commandObjects.setbit(key, offset, value)); - } - - @Override - public Response getbit(String key, long offset) { - return appendCommand(commandObjects.getbit(key, offset)); - } - - @Override - public Response setrange(String key, long offset, String value) { - return appendCommand(commandObjects.setrange(key, offset, value)); - } - - @Override - public Response getrange(String key, long startOffset, long endOffset) { - return appendCommand(commandObjects.getrange(key, startOffset, endOffset)); - } - - @Override - public Response getSet(String key, String value) { - return appendCommand(commandObjects.getSet(key, value)); - } - - @Override - public Response setnx(String key, String value) { - return appendCommand(commandObjects.setnx(key, value)); - } - - @Override - public Response setex(String key, long seconds, String value) { - return appendCommand(commandObjects.setex(key, seconds, value)); - } - - @Override - public Response psetex(String key, long milliseconds, String value) { - return appendCommand(commandObjects.psetex(key, milliseconds, value)); - } - - @Override - public Response> mget(String... keys) { - return appendCommand(commandObjects.mget(keys)); - } - - @Override - public Response mset(String... keysvalues) { - return appendCommand(commandObjects.mset(keysvalues)); - } - - @Override - public Response msetnx(String... keysvalues) { - return appendCommand(commandObjects.msetnx(keysvalues)); - } - - @Override - public Response incr(String key) { - return appendCommand(commandObjects.incr(key)); - } - - @Override - public Response incrBy(String key, long increment) { - return appendCommand(commandObjects.incrBy(key, increment)); - } - - @Override - public Response incrByFloat(String key, double increment) { - return appendCommand(commandObjects.incrByFloat(key, increment)); - } - - @Override - public Response decr(String key) { - return appendCommand(commandObjects.decr(key)); - } - - @Override - public Response decrBy(String key, long decrement) { - return appendCommand(commandObjects.decrBy(key, decrement)); - } - - @Override - public Response append(String key, String value) { - return appendCommand(commandObjects.append(key, value)); - } - - @Override - public Response substr(String key, int start, int end) { - return appendCommand(commandObjects.substr(key, start, end)); - } - - @Override - public Response strlen(String key) { - return appendCommand(commandObjects.strlen(key)); - } - - @Override - public Response bitcount(String key) { - return appendCommand(commandObjects.bitcount(key)); - } - - @Override - public Response bitcount(String key, long start, long end) { - return appendCommand(commandObjects.bitcount(key, start, end)); - } - - @Override - public Response bitcount(String key, long start, long end, BitCountOption option) { - return appendCommand(commandObjects.bitcount(key, start, end, option)); - } - - @Override - public Response bitpos(String key, boolean value) { - return appendCommand(commandObjects.bitpos(key, value)); - } - - @Override - public Response bitpos(String key, boolean value, BitPosParams params) { - return appendCommand(commandObjects.bitpos(key, value, params)); - } - - @Override - public Response> bitfield(String key, String... arguments) { - return appendCommand(commandObjects.bitfield(key, arguments)); - } - - @Override - public Response> bitfieldReadonly(String key, String... arguments) { - return appendCommand(commandObjects.bitfieldReadonly(key, arguments)); - } - - @Override - public Response bitop(BitOP op, String destKey, String... srcKeys) { - return appendCommand(commandObjects.bitop(op, destKey, srcKeys)); - } - - @Override - public Response strAlgoLCSKeys(String keyA, String keyB, StrAlgoLCSParams params) { - return appendCommand(commandObjects.strAlgoLCSKeys(keyA, keyB, params)); - } - - @Override - public Response lcs(String keyA, String keyB, LCSParams params) { - return appendCommand(commandObjects.lcs(keyA, keyB, params)); - } - - @Override - public Response set(String key, String value) { - return appendCommand(commandObjects.set(key, value)); - } - - @Override - public Response set(String key, String value, SetParams params) { - return appendCommand(commandObjects.set(key, value, params)); - } - - @Override - public Response rpush(String key, String... string) { - return appendCommand(commandObjects.rpush(key, string)); - - } - - @Override - public Response lpush(String key, String... string) { - return appendCommand(commandObjects.lpush(key, string)); - } - - @Override - public Response llen(String key) { - return appendCommand(commandObjects.llen(key)); - } - - @Override - public Response> lrange(String key, long start, long stop) { - return appendCommand(commandObjects.lrange(key, start, stop)); - } - - @Override - public Response ltrim(String key, long start, long stop) { - return appendCommand(commandObjects.ltrim(key, start, stop)); - } - - @Override - public Response lindex(String key, long index) { - return appendCommand(commandObjects.lindex(key, index)); - } - - @Override - public Response lset(String key, long index, String value) { - return appendCommand(commandObjects.lset(key, index, value)); - } - - @Override - public Response lrem(String key, long count, String value) { - return appendCommand(commandObjects.lrem(key, count, value)); - } - - @Override - public Response lpop(String key) { - return appendCommand(commandObjects.lpop(key)); - } - - @Override - public Response> lpop(String key, int count) { - return appendCommand(commandObjects.lpop(key, count)); - } - - @Override - public Response lpos(String key, String element) { - return appendCommand(commandObjects.lpos(key, element)); - } - - @Override - public Response lpos(String key, String element, LPosParams params) { - return appendCommand(commandObjects.lpos(key, element, params)); - } - - @Override - public Response> lpos(String key, String element, LPosParams params, long count) { - return appendCommand(commandObjects.lpos(key, element, params, count)); - } - - @Override - public Response rpop(String key) { - return appendCommand(commandObjects.rpop(key)); - } - - @Override - public Response> rpop(String key, int count) { - return appendCommand(commandObjects.rpop(key, count)); - } - - @Override - public Response linsert(String key, ListPosition where, String pivot, String value) { - return appendCommand(commandObjects.linsert(key, where, pivot, value)); - } - - @Override - public Response lpushx(String key, String... strings) { - return appendCommand(commandObjects.lpushx(key, strings)); - } - - @Override - public Response rpushx(String key, String... strings) { - return appendCommand(commandObjects.rpushx(key, strings)); - } - - @Override - public Response> blpop(int timeout, String key) { - return appendCommand(commandObjects.blpop(timeout, key)); - } - - @Override - public Response blpop(double timeout, String key) { - return appendCommand(commandObjects.blpop(timeout, key)); - } - - @Override - public Response> brpop(int timeout, String key) { - return appendCommand(commandObjects.brpop(timeout, key)); - } - - @Override - public Response brpop(double timeout, String key) { - return appendCommand(commandObjects.brpop(timeout, key)); - } - - @Override - public Response> blpop(int timeout, String... keys) { - return appendCommand(commandObjects.blpop(timeout, keys)); - } - - @Override - public Response blpop(double timeout, String... keys) { - return appendCommand(commandObjects.blpop(timeout, keys)); - } - - @Override - public Response> brpop(int timeout, String... keys) { - return appendCommand(commandObjects.brpop(timeout, keys)); - } - - @Override - public Response brpop(double timeout, String... keys) { - return appendCommand(commandObjects.brpop(timeout, keys)); - } - - @Override - public Response rpoplpush(String srcKey, String dstKey) { - return appendCommand(commandObjects.rpoplpush(srcKey, dstKey)); - } - - @Override - public Response brpoplpush(String source, String destination, int timeout) { - return appendCommand(commandObjects.brpoplpush(source, destination, timeout)); - } - - @Override - public Response lmove(String srcKey, String dstKey, ListDirection from, ListDirection to) { - return appendCommand(commandObjects.lmove(srcKey, dstKey, from, to)); - } - - @Override - public Response blmove(String srcKey, String dstKey, ListDirection from, ListDirection to, double timeout) { - return appendCommand(commandObjects.blmove(srcKey, dstKey, from, to, timeout)); - } - - @Override - public Response>> lmpop(ListDirection direction, String... keys) { - return appendCommand(commandObjects.lmpop(direction, keys)); - } - - @Override - public Response>> lmpop(ListDirection direction, int count, String... keys) { - return appendCommand(commandObjects.lmpop(direction, count, keys)); - } - - @Override - public Response>> blmpop(long timeout, ListDirection direction, String... keys) { - return appendCommand(commandObjects.blmpop(timeout, direction, keys)); - } - - @Override - public Response>> blmpop(long timeout, ListDirection direction, int count, String... keys) { - return appendCommand(commandObjects.blmpop(timeout, direction, count, keys)); - } - - @Override - public Response hset(String key, String field, String value) { - return appendCommand(commandObjects.hset(key, field, value)); - } - - @Override - public Response hset(String key, Map hash) { - return appendCommand(commandObjects.hset(key, hash)); - } - - @Override - public Response hget(String key, String field) { - return appendCommand(commandObjects.hget(key, field)); - } - - @Override - public Response hsetnx(String key, String field, String value) { - return appendCommand(commandObjects.hsetnx(key, field, value)); - } - - @Override - public Response hmset(String key, Map hash) { - return appendCommand(commandObjects.hmset(key, hash)); - } - - @Override - public Response> hmget(String key, String... fields) { - return appendCommand(commandObjects.hmget(key, fields)); - } - - @Override - public Response hincrBy(String key, String field, long value) { - return appendCommand(commandObjects.hincrBy(key, field, value)); - } - - @Override - public Response hincrByFloat(String key, String field, double value) { - return appendCommand(commandObjects.hincrByFloat(key, field, value)); - } - - @Override - public Response hexists(String key, String field) { - return appendCommand(commandObjects.hexists(key, field)); - } - - @Override - public Response hdel(String key, String... field) { - return appendCommand(commandObjects.hdel(key, field)); - } - - @Override - public Response hlen(String key) { - return appendCommand(commandObjects.hlen(key)); - } - - @Override - public Response> hkeys(String key) { - return appendCommand(commandObjects.hkeys(key)); - } - - @Override - public Response> hvals(String key) { - return appendCommand(commandObjects.hvals(key)); - } - - @Override - public Response> hgetAll(String key) { - return appendCommand(commandObjects.hgetAll(key)); - } - - @Override - public Response hrandfield(String key) { - return appendCommand(commandObjects.hrandfield(key)); - } - - @Override - public Response> hrandfield(String key, long count) { - return appendCommand(commandObjects.hrandfield(key, count)); - } - - @Override - public Response> hrandfieldWithValues(String key, long count) { - return appendCommand(commandObjects.hrandfieldWithValues(key, count)); - } - - @Override - public Response>> hscan(String key, String cursor, ScanParams params) { - return appendCommand(commandObjects.hscan(key, cursor, params)); - } - - @Override - public Response hstrlen(String key, String field) { - return appendCommand(commandObjects.hstrlen(key, field)); - } - - @Override - public Response sadd(String key, String... members) { - return appendCommand(commandObjects.sadd(key, members)); - } - - @Override - public Response> smembers(String key) { - return appendCommand(commandObjects.smembers(key)); - } - - @Override - public Response srem(String key, String... members) { - return appendCommand(commandObjects.srem(key, members)); - } - - @Override - public Response spop(String key) { - return appendCommand(commandObjects.spop(key)); - } - - @Override - public Response> spop(String key, long count) { - return appendCommand(commandObjects.spop(key, count)); - } - - @Override - public Response scard(String key) { - return appendCommand(commandObjects.scard(key)); - } - - @Override - public Response sismember(String key, String member) { - return appendCommand(commandObjects.sismember(key, member)); - } - - @Override - public Response> smismember(String key, String... members) { - return appendCommand(commandObjects.smismember(key, members)); - } - - @Override - public Response srandmember(String key) { - return appendCommand(commandObjects.srandmember(key)); - } - - @Override - public Response> srandmember(String key, int count) { - return appendCommand(commandObjects.srandmember(key, count)); - } - - @Override - public Response> sscan(String key, String cursor, ScanParams params) { - return appendCommand(commandObjects.sscan(key, cursor, params)); - } - - @Override - public Response> sdiff(String... keys) { - return appendCommand(commandObjects.sdiff(keys)); - } - - @Override - public Response sdiffstore(String dstKey, String... keys) { - return appendCommand(commandObjects.sdiffstore(dstKey, keys)); - } - - @Override - public Response> sinter(String... keys) { - return appendCommand(commandObjects.sinter(keys)); - } - - @Override - public Response sinterstore(String dstKey, String... keys) { - return appendCommand(commandObjects.sinterstore(dstKey, keys)); - } - - @Override - public Response sintercard(String... keys) { - return appendCommand(commandObjects.sintercard(keys)); - } - - @Override - public Response sintercard(int limit, String... keys) { - return appendCommand(commandObjects.sintercard(limit, keys)); - } - - @Override - public Response> sunion(String... keys) { - return appendCommand(commandObjects.sunion(keys)); - } - - @Override - public Response sunionstore(String dstKey, String... keys) { - return appendCommand(commandObjects.sunionstore(dstKey, keys)); - } - - @Override - public Response smove(String srcKey, String dstKey, String member) { - return appendCommand(commandObjects.smove(srcKey, dstKey, member)); - } - - @Override - public Response zadd(String key, double score, String member) { - return appendCommand(commandObjects.zadd(key, score, member)); - } - - @Override - public Response zadd(String key, double score, String member, ZAddParams params) { - return appendCommand(commandObjects.zadd(key, score, member, params)); - } - - @Override - public Response zadd(String key, Map scoreMembers) { - return appendCommand(commandObjects.zadd(key, scoreMembers)); - } - - @Override - public Response zadd(String key, Map scoreMembers, ZAddParams params) { - return appendCommand(commandObjects.zadd(key, scoreMembers, params)); - } - - @Override - public Response zaddIncr(String key, double score, String member, ZAddParams params) { - return appendCommand(commandObjects.zaddIncr(key, score, member, params)); - } - - @Override - public Response zrem(String key, String... members) { - return appendCommand(commandObjects.zrem(key, members)); - } - - @Override - public Response zincrby(String key, double increment, String member) { - return appendCommand(commandObjects.zincrby(key, increment, member)); - } - - @Override - public Response zincrby(String key, double increment, String member, ZIncrByParams params) { - return appendCommand(commandObjects.zincrby(key, increment, member, params)); - } - - @Override - public Response zrank(String key, String member) { - return appendCommand(commandObjects.zrank(key, member)); - } - - @Override - public Response zrevrank(String key, String member) { - return appendCommand(commandObjects.zrevrank(key, member)); - } - - @Override - public Response> zrange(String key, long start, long stop) { - return appendCommand(commandObjects.zrange(key, start, stop)); - } - - @Override - public Response> zrevrange(String key, long start, long stop) { - return appendCommand(commandObjects.zrevrange(key, start, stop)); - } - - @Override - public Response> zrangeWithScores(String key, long start, long stop) { - return appendCommand(commandObjects.zrangeWithScores(key, start, stop)); - } - - @Override - public Response> zrevrangeWithScores(String key, long start, long stop) { - return appendCommand(commandObjects.zrevrangeWithScores(key, start, stop)); - } - - @Override - public Response> zrange(String key, ZRangeParams zRangeParams) { - return appendCommand(commandObjects.zrange(key, zRangeParams)); - } - - @Override - public Response> zrangeWithScores(String key, ZRangeParams zRangeParams) { - return appendCommand(commandObjects.zrangeWithScores(key, zRangeParams)); - } - - @Override - public Response zrangestore(String dest, String src, ZRangeParams zRangeParams) { - return appendCommand(commandObjects.zrangestore(dest, src, zRangeParams)); - } - - @Override - public Response zrandmember(String key) { - return appendCommand(commandObjects.zrandmember(key)); - } - - @Override - public Response> zrandmember(String key, long count) { - return appendCommand(commandObjects.zrandmember(key, count)); - } - - @Override - public Response> zrandmemberWithScores(String key, long count) { - return appendCommand(commandObjects.zrandmemberWithScores(key, count)); - } - - @Override - public Response zcard(String key) { - return appendCommand(commandObjects.zcard(key)); - } - - @Override - public Response zscore(String key, String member) { - return appendCommand(commandObjects.zscore(key, member)); - } - - @Override - public Response> zmscore(String key, String... members) { - return appendCommand(commandObjects.zmscore(key, members)); - } - - @Override - public Response zpopmax(String key) { - return appendCommand(commandObjects.zpopmax(key)); - } - - @Override - public Response> zpopmax(String key, int count) { - return appendCommand(commandObjects.zpopmax(key, count)); - } - - @Override - public Response zpopmin(String key) { - return appendCommand(commandObjects.zpopmin(key)); - } - - @Override - public Response> zpopmin(String key, int count) { - return appendCommand(commandObjects.zpopmin(key, count)); - } - - @Override - public Response zcount(String key, double min, double max) { - return appendCommand(commandObjects.zcount(key, min, max)); - } - - @Override - public Response zcount(String key, String min, String max) { - return appendCommand(commandObjects.zcount(key, min, max)); - } - - @Override - public Response> zrangeByScore(String key, double min, double max) { - return appendCommand(commandObjects.zrangeByScore(key, min, max)); - } - - @Override - public Response> zrangeByScore(String key, String min, String max) { - return appendCommand(commandObjects.zrangeByScore(key, min, max)); - } - - @Override - public Response> zrevrangeByScore(String key, double max, double min) { - return appendCommand(commandObjects.zrevrangeByScore(key, max, min)); - - } - - @Override - public Response> zrangeByScore(String key, double min, double max, int offset, int count) { - return appendCommand(commandObjects.zrangeByScore(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByScore(String key, String max, String min) { - return appendCommand(commandObjects.zrevrangeByScore(key, max, min)); - } - - @Override - public Response> zrangeByScore(String key, String min, String max, int offset, int count) { - return appendCommand(commandObjects.zrangeByScore(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByScore(String key, double max, double min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByScore(key, max, min, offset, count)); - } - - @Override - public Response> zrangeByScoreWithScores(String key, double min, double max) { - return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max)); - } - - @Override - public Response> zrevrangeByScoreWithScores(String key, double max, double min) { - return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min)); - } - - @Override - public Response> zrangeByScoreWithScores(String key, double min, double max, int offset, int count) { - return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByScore(String key, String max, String min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByScore(key, max, min, offset, count)); - } - - @Override - public Response> zrangeByScoreWithScores(String key, String min, String max) { - return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max)); - } - - @Override - public Response> zrevrangeByScoreWithScores(String key, String max, String min) { - return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min)); - } - - @Override - public Response> zrangeByScoreWithScores(String key, String min, String max, int offset, int count) { - return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByScoreWithScores(String key, double max, double min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min, offset, count)); - } - - @Override - public Response> zrevrangeByScoreWithScores(String key, String max, String min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min, offset, count)); - } - - @Override - public Response zremrangeByRank(String key, long start, long stop) { - return appendCommand(commandObjects.zremrangeByRank(key, start, stop)); - } - - @Override - public Response zremrangeByScore(String key, double min, double max) { - return appendCommand(commandObjects.zremrangeByScore(key, min, max)); - } - - @Override - public Response zremrangeByScore(String key, String min, String max) { - return appendCommand(commandObjects.zremrangeByScore(key, min, max)); - } - - @Override - public Response zlexcount(String key, String min, String max) { - return appendCommand(commandObjects.zlexcount(key, min, max)); - } - - @Override - public Response> zrangeByLex(String key, String min, String max) { - return appendCommand(commandObjects.zrangeByLex(key, min, max)); - } - - @Override - public Response> zrangeByLex(String key, String min, String max, int offset, int count) { - return appendCommand(commandObjects.zrangeByLex(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByLex(String key, String max, String min) { - return appendCommand(commandObjects.zrevrangeByLex(key, max, min)); - } - - @Override - public Response> zrevrangeByLex(String key, String max, String min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByLex(key, max, min, offset, count)); - } - - @Override - public Response zremrangeByLex(String key, String min, String max) { - return appendCommand(commandObjects.zremrangeByLex(key, min, max)); - } - - @Override - public Response> zscan(String key, String cursor, ScanParams params) { - return appendCommand(commandObjects.zscan(key, cursor, params)); - } - - @Override - public Response bzpopmax(double timeout, String... keys) { - return appendCommand(commandObjects.bzpopmax(timeout, keys)); - } - - @Override - public Response bzpopmin(double timeout, String... keys) { - return appendCommand(commandObjects.bzpopmin(timeout, keys)); - } - - @Override - public Response>> zmpop(SortedSetOption option, String... keys) { - return appendCommand(commandObjects.zmpop(option, keys)); - } - - @Override - public Response>> zmpop(SortedSetOption option, int count, String... keys) { - return appendCommand(commandObjects.zmpop(option, count, keys)); - } - - @Override - public Response>> bzmpop(long timeout, SortedSetOption option, String... keys) { - return appendCommand(commandObjects.bzmpop(timeout, option, keys)); - } - - @Override - public Response>> bzmpop(long timeout, SortedSetOption option, int count, String... keys) { - return appendCommand(commandObjects.bzmpop(timeout, option, count, keys)); - } - - @Override - public Response> zdiff(String... keys) { - return appendCommand(commandObjects.zdiff(keys)); - } - - @Override - public Response> zdiffWithScores(String... keys) { - return appendCommand(commandObjects.zdiffWithScores(keys)); - } - - @Override - public Response zdiffStore(String dstKey, String... keys) { - return appendCommand(commandObjects.zdiffStore(dstKey, keys)); - } - - @Override - public Response zinterstore(String dstKey, String... sets) { - return appendCommand(commandObjects.zinterstore(dstKey, sets)); - } - - @Override - public Response zinterstore(String dstKey, ZParams params, String... sets) { - return appendCommand(commandObjects.zinterstore(dstKey, params, sets)); - } - - @Override - public Response> zinter(ZParams params, String... keys) { - return appendCommand(commandObjects.zinter(params, keys)); - } - - @Override - public Response> zinterWithScores(ZParams params, String... keys) { - return appendCommand(commandObjects.zinterWithScores(params, keys)); - } - - @Override - public Response zintercard(String... keys) { - return appendCommand(commandObjects.zintercard(keys)); - } - - @Override - public Response zintercard(long limit, String... keys) { - return appendCommand(commandObjects.zintercard(limit, keys)); - } - - @Override - public Response> zunion(ZParams params, String... keys) { - return appendCommand(commandObjects.zunion(params, keys)); - } - - @Override - public Response> zunionWithScores(ZParams params, String... keys) { - return appendCommand(commandObjects.zunionWithScores(params, keys)); - } - - @Override - public Response zunionstore(String dstKey, String... sets) { - return appendCommand(commandObjects.zunionstore(dstKey, sets)); - } - - @Override - public Response zunionstore(String dstKey, ZParams params, String... sets) { - return appendCommand(commandObjects.zunionstore(dstKey, params, sets)); - } - - @Override - public Response geoadd(String key, double longitude, double latitude, String member) { - return appendCommand(commandObjects.geoadd(key, longitude, latitude, member)); - } - - @Override - public Response geoadd(String key, Map memberCoordinateMap) { - return appendCommand(commandObjects.geoadd(key, memberCoordinateMap)); - } - - @Override - public Response geoadd(String key, GeoAddParams params, Map memberCoordinateMap) { - return appendCommand(commandObjects.geoadd(key, params, memberCoordinateMap)); - } - - @Override - public Response geodist(String key, String member1, String member2) { - return appendCommand(commandObjects.geodist(key, member1, member2)); - } - - @Override - public Response geodist(String key, String member1, String member2, GeoUnit unit) { - return appendCommand(commandObjects.geodist(key, member1, member2, unit)); - } - - @Override - public Response> geohash(String key, String... members) { - return appendCommand(commandObjects.geohash(key, members)); - } - - @Override - public Response> geopos(String key, String... members) { - return appendCommand(commandObjects.geopos(key, members)); - } - - @Override - public Response> georadius(String key, double longitude, double latitude, double radius, GeoUnit unit) { - return appendCommand(commandObjects.georadius(key, longitude, latitude, radius, unit)); - } - - @Override - public Response> georadiusReadonly(String key, double longitude, double latitude, double radius, GeoUnit unit) { - return appendCommand(commandObjects.georadiusReadonly(key, longitude, latitude, radius, unit)); - } - - @Override - public Response> georadius(String key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param) { - return appendCommand(commandObjects.georadius(key, longitude, latitude, radius, unit, param)); - } - - @Override - public Response> georadiusReadonly(String key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param) { - return appendCommand(commandObjects.georadiusReadonly(key, longitude, latitude, radius, unit, param)); - } - - @Override - public Response> georadiusByMember(String key, String member, double radius, GeoUnit unit) { - return appendCommand(commandObjects.georadiusByMember(key, member, radius, unit)); - } - - @Override - public Response> georadiusByMemberReadonly(String key, String member, double radius, GeoUnit unit) { - return appendCommand(commandObjects.georadiusByMemberReadonly(key, member, radius, unit)); - } - - @Override - public Response> georadiusByMember(String key, String member, double radius, GeoUnit unit, GeoRadiusParam param) { - return appendCommand(commandObjects.georadiusByMember(key, member, radius, unit, param)); - } - - @Override - public Response> georadiusByMemberReadonly(String key, String member, double radius, GeoUnit unit, GeoRadiusParam param) { - return appendCommand(commandObjects.georadiusByMemberReadonly(key, member, radius, unit, param)); - } - - @Override - public Response georadiusStore(String key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param, GeoRadiusStoreParam storeParam) { - return appendCommand(commandObjects.georadiusStore(key, longitude, latitude, radius, unit, param, storeParam)); - } - - @Override - public Response georadiusByMemberStore(String key, String member, double radius, GeoUnit unit, GeoRadiusParam param, GeoRadiusStoreParam storeParam) { - return appendCommand(commandObjects.georadiusByMemberStore(key, member, radius, unit, param, storeParam)); - } - - @Override - public Response> geosearch(String key, String member, double radius, GeoUnit unit) { - return appendCommand(commandObjects.geosearch(key, member, radius, unit)); - } - - @Override - public Response> geosearch(String key, GeoCoordinate coord, double radius, GeoUnit unit) { - return appendCommand(commandObjects.geosearch(key, coord, radius, unit)); - } - - @Override - public Response> geosearch(String key, String member, double width, double height, GeoUnit unit) { - return appendCommand(commandObjects.geosearch(key, member, width, height, unit)); - } - - @Override - public Response> geosearch(String key, GeoCoordinate coord, double width, double height, GeoUnit unit) { - return appendCommand(commandObjects.geosearch(key, coord, width, height, unit)); - } - - @Override - public Response> geosearch(String key, GeoSearchParam params) { - return appendCommand(commandObjects.geosearch(key, params)); - } - - @Override - public Response geosearchStore(String dest, String src, String member, double radius, GeoUnit unit) { - return appendCommand(commandObjects.geosearchStore(dest, src, member, radius, unit)); - } - - @Override - public Response geosearchStore(String dest, String src, GeoCoordinate coord, double radius, GeoUnit unit) { - return appendCommand(commandObjects.geosearchStore(dest, src, coord, radius, unit)); - } - - @Override - public Response geosearchStore(String dest, String src, String member, double width, double height, GeoUnit unit) { - return appendCommand(commandObjects.geosearchStore(dest, src, member, width, height, unit)); - } - - @Override - public Response geosearchStore(String dest, String src, GeoCoordinate coord, double width, double height, GeoUnit unit) { - return appendCommand(commandObjects.geosearchStore(dest, src, coord, width, height, unit)); - } - - @Override - public Response geosearchStore(String dest, String src, GeoSearchParam params) { - return appendCommand(commandObjects.geosearchStore(dest, src, params)); - } - - @Override - public Response geosearchStoreStoreDist(String dest, String src, GeoSearchParam params) { - return appendCommand(commandObjects.geosearchStoreStoreDist(dest, src, params)); - } - - @Override - public Response pfadd(String key, String... elements) { - return appendCommand(commandObjects.pfadd(key, elements)); - } - - @Override - public Response pfmerge(String destkey, String... sourcekeys) { - return appendCommand(commandObjects.pfmerge(destkey, sourcekeys)); - } - - @Override - public Response pfcount(String key) { - return appendCommand(commandObjects.pfcount(key)); - } - - @Override - public Response pfcount(String... keys) { - return appendCommand(commandObjects.pfcount(keys)); - } - - @Override - public Response xadd(String key, StreamEntryID id, Map hash) { - return appendCommand(commandObjects.xadd(key, id, hash)); - } - - @Override - public Response xadd(String key, XAddParams params, Map hash) { - return appendCommand(commandObjects.xadd(key, params, hash)); - } - - @Override - public Response xlen(String key) { - return appendCommand(commandObjects.xlen(key)); - } - - @Override - public Response> xrange(String key, StreamEntryID start, StreamEntryID end) { - return appendCommand(commandObjects.xrange(key, start, end)); - } - - @Override - public Response> xrange(String key, StreamEntryID start, StreamEntryID end, int count) { - return appendCommand(commandObjects.xrange(key, start, end, count)); - } - - @Override - public Response> xrevrange(String key, StreamEntryID end, StreamEntryID start) { - return appendCommand(commandObjects.xrevrange(key, start, end)); - } - - @Override - public Response> xrevrange(String key, StreamEntryID end, StreamEntryID start, int count) { - return appendCommand(commandObjects.xrevrange(key, start, end, count)); - } - - @Override - public Response> xrange(String key, String start, String end) { - return appendCommand(commandObjects.xrange(key, start, end)); - } - - @Override - public Response> xrange(String key, String start, String end, int count) { - return appendCommand(commandObjects.xrange(key, start, end, count)); - } - - @Override - public Response> xrevrange(String key, String end, String start) { - return appendCommand(commandObjects.xrevrange(key, start, end)); - } - - @Override - public Response> xrevrange(String key, String end, String start, int count) { - return appendCommand(commandObjects.xrevrange(key, start, end, count)); - } - - @Override - public Response xack(String key, String group, StreamEntryID... ids) { - return appendCommand(commandObjects.xack(key, group, ids)); - } - - @Override - public Response xgroupCreate(String key, String groupName, StreamEntryID id, boolean makeStream) { - return appendCommand(commandObjects.xgroupCreate(key, groupName, id, makeStream)); - } - - @Override - public Response xgroupSetID(String key, String groupName, StreamEntryID id) { - return appendCommand(commandObjects.xgroupSetID(key, groupName, id)); - } - - @Override - public Response xgroupDestroy(String key, String groupName) { - return appendCommand(commandObjects.xgroupDestroy(key, groupName)); - } - - @Override - public Response xgroupCreateConsumer(String key, String groupName, String consumerName) { - return appendCommand(commandObjects.xgroupCreateConsumer(key, groupName, consumerName)); - } - - @Override - public Response xgroupDelConsumer(String key, String groupName, String consumerName) { - return appendCommand(commandObjects.xgroupDelConsumer(key, groupName, consumerName)); - } - - @Override - public Response xpending(String key, String groupName) { - return appendCommand(commandObjects.xpending(key, groupName)); - } - - @Override - public Response> xpending(String key, String groupName, StreamEntryID start, StreamEntryID end, int count, String consumerName) { - return appendCommand(commandObjects.xpending(key, groupName, start, end, count, consumerName)); - } - - @Override - public Response> xpending(String key, String groupName, XPendingParams params) { - return appendCommand(commandObjects.xpending(key, groupName, params)); - } - - @Override - public Response xdel(String key, StreamEntryID... ids) { - return appendCommand(commandObjects.xdel(key, ids)); - } - - @Override - public Response xtrim(String key, long maxLen, boolean approximate) { - return appendCommand(commandObjects.xtrim(key, maxLen, approximate)); - } - - @Override - public Response xtrim(String key, XTrimParams params) { - return appendCommand(commandObjects.xtrim(key, params)); - } - - @Override - public Response> xclaim(String key, String group, String consumerName, long minIdleTime, XClaimParams params, StreamEntryID... ids) { - return appendCommand(commandObjects.xclaim(key, group, consumerName, minIdleTime, params, ids)); - } - - @Override - public Response> xclaimJustId(String key, String group, String consumerName, long minIdleTime, XClaimParams params, StreamEntryID... ids) { - return appendCommand(commandObjects.xclaimJustId(key, group, consumerName, minIdleTime, params, ids)); - } - - @Override - public Response>> xautoclaim(String key, String group, String consumerName, long minIdleTime, StreamEntryID start, XAutoClaimParams params) { - return appendCommand(commandObjects.xautoclaim(key, group, consumerName, minIdleTime, start, params)); - } - - @Override - public Response>> xautoclaimJustId(String key, String group, String consumerName, long minIdleTime, StreamEntryID start, XAutoClaimParams params) { - return appendCommand(commandObjects.xautoclaimJustId(key, group, consumerName, minIdleTime, start, params)); - } - - @Override - public Response xinfoStream(String key) { - return appendCommand(commandObjects.xinfoStream(key)); - } - - @Override - public Response xinfoStreamFull(String key) { - return appendCommand(commandObjects.xinfoStreamFull(key)); - } - - @Override - public Response xinfoStreamFull(String key, int count) { - return appendCommand(commandObjects.xinfoStreamFull(key, count)); - } - - @Override - @Deprecated - public Response> xinfoGroup(String key) { - return appendCommand(commandObjects.xinfoGroup(key)); - } - - @Override - public Response> xinfoGroups(String key) { - return appendCommand(commandObjects.xinfoGroups(key)); - } - - @Override - public Response> xinfoConsumers(String key, String group) { - return appendCommand(commandObjects.xinfoConsumers(key, group)); - } - - @Override - public Response>>> xread(XReadParams xReadParams, Map streams) { - return appendCommand(commandObjects.xread(xReadParams, streams)); - } - - @Override - public Response>>> xreadGroup(String groupName, String consumer, XReadGroupParams xReadGroupParams, Map streams) { - return appendCommand(commandObjects.xreadGroup(groupName, consumer, xReadGroupParams, streams)); - } - - @Override - public Response eval(String script) { - return appendCommand(commandObjects.eval(script)); - } - - @Override - public Response eval(String script, int keyCount, String... params) { - return appendCommand(commandObjects.eval(script, keyCount, params)); - } - - @Override - public Response eval(String script, List keys, List args) { - return appendCommand(commandObjects.eval(script, keys, args)); - } - - @Override - public Response evalReadonly(String script, List keys, List args) { - return appendCommand(commandObjects.evalReadonly(script, keys, args)); - } - - @Override - public Response evalsha(String sha1) { - return appendCommand(commandObjects.evalsha(sha1)); - } - - @Override - public Response evalsha(String sha1, int keyCount, String... params) { - return appendCommand(commandObjects.evalsha(sha1, keyCount, params)); - } - - @Override - public Response evalsha(String sha1, List keys, List args) { - return appendCommand(commandObjects.evalsha(sha1, keys, args)); - } - - @Override - public Response evalshaReadonly(String sha1, List keys, List args) { - return appendCommand(commandObjects.evalshaReadonly(sha1, keys, args)); - } - - - @Override - public Response waitReplicas(String sampleKey, int replicas, long timeout) { - return appendCommand(commandObjects.waitReplicas(sampleKey, replicas, timeout)); - } - - @Override - public Response eval(String script, String sampleKey) { - return appendCommand(commandObjects.eval(script, sampleKey)); - } - - @Override - public Response evalsha(String sha1, String sampleKey) { - return appendCommand(commandObjects.evalsha(sha1, sampleKey)); - } - - @Override - public Response> scriptExists(String sampleKey, String... sha1) { - return appendCommand(commandObjects.scriptExists(sampleKey, sha1)); - } - - @Override - public Response scriptLoad(String script, String sampleKey) { - return appendCommand(commandObjects.scriptLoad(script, sampleKey)); - } - - @Override - public Response scriptFlush(String sampleKey) { - return appendCommand(commandObjects.scriptFlush(sampleKey)); - } - - @Override - public Response scriptFlush(String sampleKey, FlushMode flushMode) { - return appendCommand(commandObjects.scriptFlush(sampleKey, flushMode)); - } - - @Override - public Response scriptKill(String sampleKey) { - return appendCommand(commandObjects.scriptKill(sampleKey)); - } - - @Override - public Response fcall(byte[] name, List keys, List args) { - return appendCommand(commandObjects.fcall(name, keys, args)); - } - - @Override - public Response fcall(String name, List keys, List args) { - return appendCommand(commandObjects.fcall(name, keys, args)); - } - - @Override - public Response fcallReadonly(byte[] name, List keys, List args) { - return appendCommand(commandObjects.fcallReadonly(name, keys, args)); - } - - @Override - public Response fcallReadonly(String name, List keys, List args) { - return appendCommand(commandObjects.fcallReadonly(name, keys, args)); - } - - @Override - public Response functionDelete(byte[] libraryName) { - return appendCommand(commandObjects.functionDelete(libraryName)); - } - - @Override - public Response functionDelete(String libraryName) { - return appendCommand(commandObjects.functionDelete(libraryName)); - } - - @Override - public Response functionDump() { - return appendCommand(commandObjects.functionDump()); - } - - @Override - public Response> functionList(String libraryNamePattern) { - return appendCommand(commandObjects.functionList(libraryNamePattern)); - } - - @Override - public Response> functionList() { - return appendCommand(commandObjects.functionList()); - } - - @Override - public Response> functionListWithCode(String libraryNamePattern) { - return appendCommand(commandObjects.functionListWithCode(libraryNamePattern)); - } - - @Override - public Response> functionListWithCode() { - return appendCommand(commandObjects.functionListWithCode()); - } - - @Override - public Response> functionListBinary() { - return appendCommand(commandObjects.functionListBinary()); - } - - @Override - public Response> functionList(final byte[] libraryNamePattern) { - return appendCommand(commandObjects.functionList(libraryNamePattern)); - } - - @Override - public Response> functionListWithCodeBinary() { - return appendCommand(commandObjects.functionListWithCodeBinary()); - } - - @Override - public Response> functionListWithCode(final byte[] libraryNamePattern) { - return appendCommand(commandObjects.functionListWithCode(libraryNamePattern)); - } - - @Override - public Response functionLoad(byte[] functionCode) { - return appendCommand(commandObjects.functionLoad(functionCode)); - } - - @Override - public Response functionLoad(String functionCode) { - return appendCommand(commandObjects.functionLoad(functionCode)); - } - - @Override - public Response functionLoadReplace(byte[] functionCode) { - return appendCommand(commandObjects.functionLoadReplace(functionCode)); - } - - @Override - public Response functionLoadReplace(String functionCode) { - return appendCommand(commandObjects.functionLoadReplace(functionCode)); - } - - @Override - public Response functionRestore(byte[] serializedValue) { - return appendCommand(commandObjects.functionRestore(serializedValue)); - } - - @Override - public Response functionRestore(byte[] serializedValue, FunctionRestorePolicy policy) { - return appendCommand(commandObjects.functionRestore(serializedValue, policy)); - } - - @Override - public Response functionFlush() { - return appendCommand(commandObjects.functionFlush()); - } - - @Override - public Response functionFlush(FlushMode mode) { - return appendCommand(commandObjects.functionFlush(mode)); - } - - @Override - public Response functionKill() { - return appendCommand(commandObjects.functionKill()); - } - - @Override - public Response functionStats() { - return appendCommand(commandObjects.functionStats()); - } - - @Override - public Response functionStatsBinary() { - return appendCommand(commandObjects.functionStatsBinary()); - } - - public Response publish(String channel, String message) { - return appendCommand(commandObjects.publish(channel, message)); - } - - public Response strAlgoLCSStrings(String strA, String strB, StrAlgoLCSParams params) { - return appendCommand(commandObjects.strAlgoLCSStrings(strA, strB, params)); - } - - @Override - public Response geoadd(byte[] key, double longitude, double latitude, byte[] member) { - return appendCommand(commandObjects.geoadd(key, longitude, latitude, member)); - } - - @Override - public Response geoadd(byte[] key, Map memberCoordinateMap) { - return appendCommand(commandObjects.geoadd(key, memberCoordinateMap)); - } - - @Override - public Response geoadd(byte[] key, GeoAddParams params, Map memberCoordinateMap) { - return appendCommand(commandObjects.geoadd(key, params, memberCoordinateMap)); - } - - @Override - public Response geodist(byte[] key, byte[] member1, byte[] member2) { - return appendCommand(commandObjects.geodist(key, member1, member2)); - } - - @Override - public Response geodist(byte[] key, byte[] member1, byte[] member2, GeoUnit unit) { - return appendCommand(commandObjects.geodist(key, member1, member2, unit)); - } - - @Override - public Response> geohash(byte[] key, byte[]... members) { - return appendCommand(commandObjects.geohash(key, members)); - } - - @Override - public Response> geopos(byte[] key, byte[]... members) { - return appendCommand(commandObjects.geopos(key, members)); - } - - @Override - public Response> georadius(byte[] key, double longitude, double latitude, double radius, GeoUnit unit) { - return appendCommand(commandObjects.georadius(key, longitude, latitude, radius, unit)); - } - - @Override - public Response> georadiusReadonly(byte[] key, double longitude, double latitude, double radius, GeoUnit unit) { - return appendCommand(commandObjects.georadiusReadonly(key, longitude, latitude, radius, unit)); - } - - @Override - public Response> georadius(byte[] key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param) { - return appendCommand(commandObjects.georadius(key, longitude, latitude, radius, unit, param)); - } - - @Override - public Response> georadiusReadonly(byte[] key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param) { - return appendCommand(commandObjects.georadiusReadonly(key, longitude, latitude, radius, unit, param)); - } - - @Override - public Response> georadiusByMember(byte[] key, byte[] member, double radius, GeoUnit unit) { - return appendCommand(commandObjects.georadiusByMember(key, member, radius, unit)); - } - - @Override - public Response> georadiusByMemberReadonly(byte[] key, byte[] member, double radius, GeoUnit unit) { - return appendCommand(commandObjects.georadiusByMemberReadonly(key, member, radius, unit)); - } - - @Override - public Response> georadiusByMember(byte[] key, byte[] member, double radius, GeoUnit unit, GeoRadiusParam param) { - return appendCommand(commandObjects.georadiusByMember(key, member, radius, unit, param)); - } - - @Override - public Response> georadiusByMemberReadonly(byte[] key, byte[] member, double radius, GeoUnit unit, GeoRadiusParam param) { - return appendCommand(commandObjects.georadiusByMemberReadonly(key, member, radius, unit, param)); - } - - @Override - public Response georadiusStore(byte[] key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param, GeoRadiusStoreParam storeParam) { - return appendCommand(commandObjects.georadiusStore(key, longitude, latitude, radius, unit, param, storeParam)); - } - - @Override - public Response georadiusByMemberStore(byte[] key, byte[] member, double radius, GeoUnit unit, GeoRadiusParam param, GeoRadiusStoreParam storeParam) { - return appendCommand(commandObjects.georadiusByMemberStore(key, member, radius, unit, param, storeParam)); - } - - @Override - public Response> geosearch(byte[] key, byte[] member, double radius, GeoUnit unit) { - return appendCommand(commandObjects.geosearch(key, member, radius, unit)); - } - - @Override - public Response> geosearch(byte[] key, GeoCoordinate coord, double radius, GeoUnit unit) { - return appendCommand(commandObjects.geosearch(key, coord, radius, unit)); - } - - @Override - public Response> geosearch(byte[] key, byte[] member, double width, double height, GeoUnit unit) { - return appendCommand(commandObjects.geosearch(key, member, width, height, unit)); - } - - @Override - public Response> geosearch(byte[] key, GeoCoordinate coord, double width, double height, GeoUnit unit) { - return appendCommand(commandObjects.geosearch(key, coord, width, height, unit)); - } - - @Override - public Response> geosearch(byte[] key, GeoSearchParam params) { - return appendCommand(commandObjects.geosearch(key, params)); - } - - @Override - public Response geosearchStore(byte[] dest, byte[] src, byte[] member, double radius, GeoUnit unit) { - return appendCommand(commandObjects.geosearchStore(dest, src, member, radius, unit)); - } - - @Override - public Response geosearchStore(byte[] dest, byte[] src, GeoCoordinate coord, double radius, GeoUnit unit) { - return appendCommand(commandObjects.geosearchStore(dest, src, coord, radius, unit)); - } - - @Override - public Response geosearchStore(byte[] dest, byte[] src, byte[] member, double width, double height, GeoUnit unit) { - return appendCommand(commandObjects.geosearchStore(dest, src, member, width, height, unit)); - } - - @Override - public Response geosearchStore(byte[] dest, byte[] src, GeoCoordinate coord, double width, double height, GeoUnit unit) { - return appendCommand(commandObjects.geosearchStore(dest, src, coord, width, height, unit)); - } - - @Override - public Response geosearchStore(byte[] dest, byte[] src, GeoSearchParam params) { - return appendCommand(commandObjects.geosearchStore(dest, src, params)); - } - - @Override - public Response geosearchStoreStoreDist(byte[] dest, byte[] src, GeoSearchParam params) { - return appendCommand(commandObjects.geosearchStoreStoreDist(dest, src, params)); - } - - @Override - public Response hset(byte[] key, byte[] field, byte[] value) { - return appendCommand(commandObjects.hset(key, field, value)); - } - - @Override - public Response hset(byte[] key, Map hash) { - return appendCommand(commandObjects.hset(key, hash)); - } - - @Override - public Response hget(byte[] key, byte[] field) { - return appendCommand(commandObjects.hget(key, field)); - } - - @Override - public Response hsetnx(byte[] key, byte[] field, byte[] value) { - return appendCommand(commandObjects.hsetnx(key, field, value)); - } - - @Override - public Response hmset(byte[] key, Map hash) { - return appendCommand(commandObjects.hmset(key, hash)); - } - - @Override - public Response> hmget(byte[] key, byte[]... fields) { - return appendCommand(commandObjects.hmget(key, fields)); - } - - @Override - public Response hincrBy(byte[] key, byte[] field, long value) { - return appendCommand(commandObjects.hincrBy(key, field, value)); - } - - @Override - public Response hincrByFloat(byte[] key, byte[] field, double value) { - return appendCommand(commandObjects.hincrByFloat(key, field, value)); - } - - @Override - public Response hexists(byte[] key, byte[] field) { - return appendCommand(commandObjects.hexists(key, field)); - } - - @Override - public Response hdel(byte[] key, byte[]... field) { - return appendCommand(commandObjects.hdel(key, field)); - } - - @Override - public Response hlen(byte[] key) { - return appendCommand(commandObjects.hlen(key)); - } - - @Override - public Response> hkeys(byte[] key) { - return appendCommand(commandObjects.hkeys(key)); - } - - @Override - public Response> hvals(byte[] key) { - return appendCommand(commandObjects.hvals(key)); - } - - @Override - public Response> hgetAll(byte[] key) { - return appendCommand(commandObjects.hgetAll(key)); - } - - @Override - public Response hrandfield(byte[] key) { - return appendCommand(commandObjects.hrandfield(key)); - } - - @Override - public Response> hrandfield(byte[] key, long count) { - return appendCommand(commandObjects.hrandfield(key, count)); - } - - @Override - public Response> hrandfieldWithValues(byte[] key, long count) { - return appendCommand(commandObjects.hrandfieldWithValues(key, count)); - } - - @Override - public Response>> hscan(byte[] key, byte[] cursor, ScanParams params) { - return appendCommand(commandObjects.hscan(key, cursor, params)); - } - - @Override - public Response hstrlen(byte[] key, byte[] field) { - return appendCommand(commandObjects.hstrlen(key, field)); - } - - @Override - public Response pfadd(byte[] key, byte[]... elements) { - return appendCommand(commandObjects.pfadd(key, elements)); - } - - @Override - public Response pfmerge(byte[] destkey, byte[]... sourcekeys) { - return appendCommand(commandObjects.pfmerge(destkey, sourcekeys)); - } - - @Override - public Response pfcount(byte[] key) { - return appendCommand(commandObjects.pfcount(key)); - } - - @Override - public Response pfcount(byte[]... keys) { - return appendCommand(commandObjects.pfcount(keys)); - } - - @Override - public Response exists(byte[] key) { - return appendCommand(commandObjects.exists(key)); - } - - @Override - public Response exists(byte[]... keys) { - return appendCommand(commandObjects.exists(keys)); - } - - @Override - public Response persist(byte[] key) { - return appendCommand(commandObjects.persist(key)); - } - - @Override - public Response type(byte[] key) { - return appendCommand(commandObjects.type(key)); - } - - @Override - public Response dump(byte[] key) { - return appendCommand(commandObjects.dump(key)); - } - - @Override - public Response restore(byte[] key, long ttl, byte[] serializedValue) { - return appendCommand(commandObjects.restore(key, ttl, serializedValue)); - } - - @Override - public Response restore(byte[] key, long ttl, byte[] serializedValue, RestoreParams params) { - return appendCommand(commandObjects.restore(key, ttl, serializedValue, params)); - } - - @Override - public Response expire(byte[] key, long seconds) { - return appendCommand(commandObjects.expire(key, seconds)); - } - - @Override - public Response expire(byte[] key, long seconds, ExpiryOption expiryOption) { - return appendCommand(commandObjects.expire(key, seconds, expiryOption)); - } - - @Override - public Response pexpire(byte[] key, long milliseconds) { - return appendCommand(commandObjects.pexpire(key, milliseconds)); - } - - @Override - public Response pexpire(byte[] key, long milliseconds, ExpiryOption expiryOption) { - return appendCommand(commandObjects.pexpire(key, milliseconds, expiryOption)); - } - - @Override - public Response expireTime(byte[] key) { - return appendCommand(commandObjects.expireTime(key)); - } - - @Override - public Response pexpireTime(byte[] key) { - return appendCommand(commandObjects.pexpireTime(key)); - } - - @Override - public Response expireAt(byte[] key, long unixTime) { - return appendCommand(commandObjects.expireAt(key, unixTime)); - } - - @Override - public Response expireAt(byte[] key, long unixTime, ExpiryOption expiryOption) { - return appendCommand(commandObjects.expireAt(key, unixTime, expiryOption)); - } - - @Override - public Response pexpireAt(byte[] key, long millisecondsTimestamp) { - return appendCommand(commandObjects.pexpireAt(key, millisecondsTimestamp)); - } - - @Override - public Response pexpireAt(byte[] key, long millisecondsTimestamp, ExpiryOption expiryOption) { - return appendCommand(commandObjects.pexpireAt(key, millisecondsTimestamp, expiryOption)); - } - - @Override - public Response ttl(byte[] key) { - return appendCommand(commandObjects.ttl(key)); - } - - @Override - public Response pttl(byte[] key) { - return appendCommand(commandObjects.pttl(key)); - } - - @Override - public Response touch(byte[] key) { - return appendCommand(commandObjects.touch(key)); - } - - @Override - public Response touch(byte[]... keys) { - return appendCommand(commandObjects.touch(keys)); - } - - @Override - public Response> sort(byte[] key) { - return appendCommand(commandObjects.sort(key)); - } - - @Override - public Response> sort(byte[] key, SortingParams sortingParams) { - return appendCommand(commandObjects.sort(key, sortingParams)); - } - - @Override - public Response> sortReadonly(byte[] key, SortingParams sortingParams) { - return appendCommand(commandObjects.sortReadonly(key, sortingParams)); - } - - @Override - public Response del(byte[] key) { - return appendCommand(commandObjects.del(key)); - } - - @Override - public Response del(byte[]... keys) { - return appendCommand(commandObjects.del(keys)); - } - - @Override - public Response unlink(byte[] key) { - return appendCommand(commandObjects.unlink(key)); - } - - @Override - public Response unlink(byte[]... keys) { - return appendCommand(commandObjects.unlink(keys)); - } - - @Override - public Response copy(byte[] srcKey, byte[] dstKey, boolean replace) { - return appendCommand(commandObjects.copy(srcKey, dstKey, replace)); - } - - @Override - public Response rename(byte[] oldkey, byte[] newkey) { - return appendCommand(commandObjects.rename(oldkey, newkey)); - } - - @Override - public Response renamenx(byte[] oldkey, byte[] newkey) { - return appendCommand(commandObjects.renamenx(oldkey, newkey)); - } - - @Override - public Response sort(byte[] key, SortingParams sortingParams, byte[] dstkey) { - return appendCommand(commandObjects.sort(key, sortingParams, dstkey)); - } - - @Override - public Response sort(byte[] key, byte[] dstkey) { - return appendCommand(commandObjects.sort(key, dstkey)); - } - - @Override - public Response memoryUsage(byte[] key) { - return appendCommand(commandObjects.memoryUsage(key)); - } - - @Override - public Response memoryUsage(byte[] key, int samples) { - return appendCommand(commandObjects.memoryUsage(key, samples)); - } - - @Override - public Response objectRefcount(byte[] key) { - return appendCommand(commandObjects.objectRefcount(key)); - } - - @Override - public Response objectEncoding(byte[] key) { - return appendCommand(commandObjects.objectEncoding(key)); - } - - @Override - public Response objectIdletime(byte[] key) { - return appendCommand(commandObjects.objectIdletime(key)); - } - - @Override - public Response objectFreq(byte[] key) { - return appendCommand(commandObjects.objectFreq(key)); - } - - @Override - public Response migrate(String host, int port, byte[] key, int timeout) { - return appendCommand(commandObjects.migrate(host, port, key, timeout)); - } - - @Override - public Response migrate(String host, int port, int timeout, MigrateParams params, byte[]... keys) { - return appendCommand(commandObjects.migrate(host, port, timeout, params, keys)); - } - - @Override - public Response> keys(byte[] pattern) { - return appendCommand(commandObjects.keys(pattern)); - } - - @Override - public Response> scan(byte[] cursor) { - return appendCommand(commandObjects.scan(cursor)); - } - - @Override - public Response> scan(byte[] cursor, ScanParams params) { - return appendCommand(commandObjects.scan(cursor, params)); - } - - @Override - public Response> scan(byte[] cursor, ScanParams params, byte[] type) { - return appendCommand(commandObjects.scan(cursor, params, type)); - } - - @Override - public Response randomBinaryKey() { - return appendCommand(commandObjects.randomBinaryKey()); - } - - @Override - public Response rpush(byte[] key, byte[]... args) { - return appendCommand(commandObjects.rpush(key, args)); - } - - @Override - public Response lpush(byte[] key, byte[]... args) { - return appendCommand(commandObjects.lpush(key, args)); - } - - @Override - public Response llen(byte[] key) { - return appendCommand(commandObjects.llen(key)); - } - - @Override - public Response> lrange(byte[] key, long start, long stop) { - return appendCommand(commandObjects.lrange(key, start, stop)); - } - - @Override - public Response ltrim(byte[] key, long start, long stop) { - return appendCommand(commandObjects.ltrim(key, start, stop)); - } - - @Override - public Response lindex(byte[] key, long index) { - return appendCommand(commandObjects.lindex(key, index)); - } - - @Override - public Response lset(byte[] key, long index, byte[] value) { - return appendCommand(commandObjects.lset(key, index, value)); - } - - @Override - public Response lrem(byte[] key, long count, byte[] value) { - return appendCommand(commandObjects.lrem(key, count, value)); - } - - @Override - public Response lpop(byte[] key) { - return appendCommand(commandObjects.lpop(key)); - } - - @Override - public Response> lpop(byte[] key, int count) { - return appendCommand(commandObjects.lpop(key, count)); - } - - @Override - public Response lpos(byte[] key, byte[] element) { - return appendCommand(commandObjects.lpos(key, element)); - } - - @Override - public Response lpos(byte[] key, byte[] element, LPosParams params) { - return appendCommand(commandObjects.lpos(key, element, params)); - } - - @Override - public Response> lpos(byte[] key, byte[] element, LPosParams params, long count) { - return appendCommand(commandObjects.lpos(key, element, params, count)); - } - - @Override - public Response rpop(byte[] key) { - return appendCommand(commandObjects.rpop(key)); - } - - @Override - public Response> rpop(byte[] key, int count) { - return appendCommand(commandObjects.rpop(key, count)); - } - - @Override - public Response linsert(byte[] key, ListPosition where, byte[] pivot, byte[] value) { - return appendCommand(commandObjects.linsert(key, where, pivot, value)); - } - - @Override - public Response lpushx(byte[] key, byte[]... args) { - return appendCommand(commandObjects.lpushx(key, args)); - } - - @Override - public Response rpushx(byte[] key, byte[]... args) { - return appendCommand(commandObjects.rpushx(key, args)); - } - - @Override - public Response> blpop(int timeout, byte[]... keys) { - return appendCommand(commandObjects.blpop(timeout, keys)); - } - - @Override - public Response> blpop(double timeout, byte[]... keys) { - return appendCommand(commandObjects.blpop(timeout, keys)); - } - - @Override - public Response> brpop(int timeout, byte[]... keys) { - return appendCommand(commandObjects.brpop(timeout, keys)); - } - - @Override - public Response> brpop(double timeout, byte[]... keys) { - return appendCommand(commandObjects.brpop(timeout, keys)); - } - - @Override - public Response rpoplpush(byte[] srckey, byte[] dstkey) { - return appendCommand(commandObjects.rpoplpush(srckey, dstkey)); - } - - @Override - public Response brpoplpush(byte[] source, byte[] destination, int timeout) { - return appendCommand(commandObjects.brpoplpush(source, destination, timeout)); - } - - @Override - public Response lmove(byte[] srcKey, byte[] dstKey, ListDirection from, ListDirection to) { - return appendCommand(commandObjects.lmove(srcKey, dstKey, from, to)); - } - - @Override - public Response blmove(byte[] srcKey, byte[] dstKey, ListDirection from, ListDirection to, double timeout) { - return appendCommand(commandObjects.blmove(srcKey, dstKey, from, to, timeout)); - } - - @Override - public Response>> lmpop(ListDirection direction, byte[]... keys) { - return appendCommand(commandObjects.lmpop(direction, keys)); - } - - @Override - public Response>> lmpop(ListDirection direction, int count, byte[]... keys) { - return appendCommand(commandObjects.lmpop(direction, count, keys)); - } - - @Override - public Response>> blmpop(long timeout, ListDirection direction, byte[]... keys) { - return appendCommand(commandObjects.blmpop(timeout, direction, keys)); - } - - @Override - public Response>> blmpop(long timeout, ListDirection direction, int count, byte[]... keys) { - return appendCommand(commandObjects.blmpop(timeout, direction, count, keys)); - } - - public Response publish(byte[] channel, byte[] message) { - return appendCommand(commandObjects.publish(channel, message)); - } - - public Response strAlgoLCSStrings(byte[] strA, byte[] strB, StrAlgoLCSParams params) { - return appendCommand(commandObjects.strAlgoLCSStrings(strA, strB, params)); - } - - @Override - public Response waitReplicas(byte[] sampleKey, int replicas, long timeout) { - return appendCommand(commandObjects.waitReplicas(sampleKey, replicas, timeout)); - } - - @Override - public Response eval(byte[] script, byte[] sampleKey) { - return appendCommand(commandObjects.eval(script, sampleKey)); - } - - @Override - public Response evalsha(byte[] sha1, byte[] sampleKey) { - return appendCommand(commandObjects.evalsha(sha1, sampleKey)); - } - - @Override - public Response> scriptExists(byte[] sampleKey, byte[]... sha1s) { - return appendCommand(commandObjects.scriptExists(sampleKey, sha1s)); - } - - @Override - public Response scriptLoad(byte[] script, byte[] sampleKey) { - return appendCommand(commandObjects.scriptLoad(script, sampleKey)); - } - - @Override - public Response scriptFlush(byte[] sampleKey) { - return appendCommand(commandObjects.scriptFlush(sampleKey)); - } - - @Override - public Response scriptFlush(byte[] sampleKey, FlushMode flushMode) { - return appendCommand(commandObjects.scriptFlush(sampleKey, flushMode)); - } - - @Override - public Response scriptKill(byte[] sampleKey) { - return appendCommand(commandObjects.scriptKill(sampleKey)); - } - - @Override - public Response eval(byte[] script) { - return appendCommand(commandObjects.eval(script)); - } - - @Override - public Response eval(byte[] script, int keyCount, byte[]... params) { - return appendCommand(commandObjects.eval(script, keyCount, params)); - } - - @Override - public Response eval(byte[] script, List keys, List args) { - return appendCommand(commandObjects.eval(script, keys, args)); - } - - @Override - public Response evalReadonly(byte[] script, List keys, List args) { - return appendCommand(commandObjects.evalReadonly(script, keys, args)); - } - - @Override - public Response evalsha(byte[] sha1) { - return appendCommand(commandObjects.evalsha(sha1)); - } - - @Override - public Response evalsha(byte[] sha1, int keyCount, byte[]... params) { - return appendCommand(commandObjects.evalsha(sha1, keyCount, params)); - } - - @Override - public Response evalsha(byte[] sha1, List keys, List args) { - return appendCommand(commandObjects.evalsha(sha1, keys, args)); - } - - @Override - public Response evalshaReadonly(byte[] sha1, List keys, List args) { - return appendCommand(commandObjects.evalshaReadonly(sha1, keys, args)); - } - - @Override - public Response sadd(byte[] key, byte[]... members) { - return appendCommand(commandObjects.sadd(key, members)); - } - - @Override - public Response> smembers(byte[] key) { - return appendCommand(commandObjects.smembers(key)); - } - - @Override - public Response srem(byte[] key, byte[]... members) { - return appendCommand(commandObjects.srem(key, members)); - } - - @Override - public Response spop(byte[] key) { - return appendCommand(commandObjects.spop(key)); - } - - @Override - public Response> spop(byte[] key, long count) { - return appendCommand(commandObjects.spop(key, count)); - } - - @Override - public Response scard(byte[] key) { - return appendCommand(commandObjects.scard(key)); - } - - @Override - public Response sismember(byte[] key, byte[] member) { - return appendCommand(commandObjects.sismember(key, member)); - } - - @Override - public Response> smismember(byte[] key, byte[]... members) { - return appendCommand(commandObjects.smismember(key, members)); - } - - @Override - public Response srandmember(byte[] key) { - return appendCommand(commandObjects.srandmember(key)); - } - - @Override - public Response> srandmember(byte[] key, int count) { - return appendCommand(commandObjects.srandmember(key, count)); - } - - @Override - public Response> sscan(byte[] key, byte[] cursor, ScanParams params) { - return appendCommand(commandObjects.sscan(key, cursor, params)); - } - - @Override - public Response> sdiff(byte[]... keys) { - return appendCommand(commandObjects.sdiff(keys)); - } - - @Override - public Response sdiffstore(byte[] dstkey, byte[]... keys) { - return appendCommand(commandObjects.sdiffstore(dstkey, keys)); - } - - @Override - public Response> sinter(byte[]... keys) { - return appendCommand(commandObjects.sinter(keys)); - } - - @Override - public Response sinterstore(byte[] dstkey, byte[]... keys) { - return appendCommand(commandObjects.sinterstore(dstkey, keys)); - } - - @Override - public Response sintercard(byte[]... keys) { - return appendCommand(commandObjects.sintercard(keys)); - } - - @Override - public Response sintercard(int limit, byte[]... keys) { - return appendCommand(commandObjects.sintercard(limit, keys)); - } - - @Override - public Response> sunion(byte[]... keys) { - return appendCommand(commandObjects.sunion(keys)); - } - - @Override - public Response sunionstore(byte[] dstkey, byte[]... keys) { - return appendCommand(commandObjects.sunionstore(dstkey, keys)); - } - - @Override - public Response smove(byte[] srckey, byte[] dstkey, byte[] member) { - return appendCommand(commandObjects.smove(srckey, dstkey, member)); - } - - @Override - public Response zadd(byte[] key, double score, byte[] member) { - return appendCommand(commandObjects.zadd(key, score, member)); - } - - @Override - public Response zadd(byte[] key, double score, byte[] member, ZAddParams params) { - return appendCommand(commandObjects.zadd(key, score, member, params)); - } - - @Override - public Response zadd(byte[] key, Map scoreMembers) { - return appendCommand(commandObjects.zadd(key, scoreMembers)); - } - - @Override - public Response zadd(byte[] key, Map scoreMembers, ZAddParams params) { - return appendCommand(commandObjects.zadd(key, scoreMembers, params)); - } - - @Override - public Response zaddIncr(byte[] key, double score, byte[] member, ZAddParams params) { - return appendCommand(commandObjects.zaddIncr(key, score, member, params)); - } - - @Override - public Response zrem(byte[] key, byte[]... members) { - return appendCommand(commandObjects.zrem(key, members)); - } - - @Override - public Response zincrby(byte[] key, double increment, byte[] member) { - return appendCommand(commandObjects.zincrby(key, increment, member)); - } - - @Override - public Response zincrby(byte[] key, double increment, byte[] member, ZIncrByParams params) { - return appendCommand(commandObjects.zincrby(key, increment, member, params)); - } - - @Override - public Response zrank(byte[] key, byte[] member) { - return appendCommand(commandObjects.zrank(key, member)); - } - - @Override - public Response zrevrank(byte[] key, byte[] member) { - return appendCommand(commandObjects.zrevrank(key, member)); - } - - @Override - public Response> zrange(byte[] key, long start, long stop) { - return appendCommand(commandObjects.zrange(key, start, stop)); - } - - @Override - public Response> zrevrange(byte[] key, long start, long stop) { - return appendCommand(commandObjects.zrevrange(key, start, stop)); - } - - @Override - public Response> zrangeWithScores(byte[] key, long start, long stop) { - return appendCommand(commandObjects.zrangeWithScores(key, start, stop)); - } - - @Override - public Response> zrevrangeWithScores(byte[] key, long start, long stop) { - return appendCommand(commandObjects.zrevrangeWithScores(key, start, stop)); - } - - @Override - public Response> zrange(byte[] key, ZRangeParams zRangeParams) { - return appendCommand(commandObjects.zrange(key, zRangeParams)); - } - - @Override - public Response> zrangeWithScores(byte[] key, ZRangeParams zRangeParams) { - return appendCommand(commandObjects.zrangeWithScores(key, zRangeParams)); - } - - @Override - public Response zrangestore(byte[] dest, byte[] src, ZRangeParams zRangeParams) { - return appendCommand(commandObjects.zrangestore(dest, src, zRangeParams)); - } - - @Override - public Response zrandmember(byte[] key) { - return appendCommand(commandObjects.zrandmember(key)); - } - - @Override - public Response> zrandmember(byte[] key, long count) { - return appendCommand(commandObjects.zrandmember(key, count)); - } - - @Override - public Response> zrandmemberWithScores(byte[] key, long count) { - return appendCommand(commandObjects.zrandmemberWithScores(key, count)); - } - - @Override - public Response zcard(byte[] key) { - return appendCommand(commandObjects.zcard(key)); - } - - @Override - public Response zscore(byte[] key, byte[] member) { - return appendCommand(commandObjects.zscore(key, member)); - } - - @Override - public Response> zmscore(byte[] key, byte[]... members) { - return appendCommand(commandObjects.zmscore(key, members)); - } - - @Override - public Response zpopmax(byte[] key) { - return appendCommand(commandObjects.zpopmax(key)); - } - - @Override - public Response> zpopmax(byte[] key, int count) { - return appendCommand(commandObjects.zpopmax(key, count)); - } - - @Override - public Response zpopmin(byte[] key) { - return appendCommand(commandObjects.zpopmin(key)); - } - - @Override - public Response> zpopmin(byte[] key, int count) { - return appendCommand(commandObjects.zpopmin(key, count)); - } - - @Override - public Response zcount(byte[] key, double min, double max) { - return appendCommand(commandObjects.zcount(key, min, max)); - } - - @Override - public Response zcount(byte[] key, byte[] min, byte[] max) { - return appendCommand(commandObjects.zcount(key, min, max)); - } - - @Override - public Response> zrangeByScore(byte[] key, double min, double max) { - return appendCommand(commandObjects.zrangeByScore(key, min, max)); - } - - @Override - public Response> zrangeByScore(byte[] key, byte[] min, byte[] max) { - return appendCommand(commandObjects.zrangeByScore(key, min, max)); - } - - @Override - public Response> zrevrangeByScore(byte[] key, double max, double min) { - return appendCommand(commandObjects.zrevrangeByScore(key, max, min)); - } - - @Override - public Response> zrangeByScore(byte[] key, double min, double max, int offset, int count) { - return appendCommand(commandObjects.zrangeByScore(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByScore(byte[] key, byte[] max, byte[] min) { - return appendCommand(commandObjects.zrevrangeByScore(key, max, min)); - } - - @Override - public Response> zrangeByScore(byte[] key, byte[] min, byte[] max, int offset, int count) { - return appendCommand(commandObjects.zrangeByScore(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByScore(byte[] key, double max, double min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByScore(key, max, min, offset, count)); - } - - @Override - public Response> zrangeByScoreWithScores(byte[] key, double min, double max) { - return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max)); - } - - @Override - public Response> zrevrangeByScoreWithScores(byte[] key, double max, double min) { - return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min)); - } - - @Override - public Response> zrangeByScoreWithScores(byte[] key, double min, double max, int offset, int count) { - return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByScore(byte[] key, byte[] max, byte[] min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByScore(key, max, min, offset, count)); - } - - @Override - public Response> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max) { - return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max)); - } - - @Override - public Response> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min) { - return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min)); - } - - @Override - public Response> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max, int offset, int count) { - return appendCommand(commandObjects.zrangeByScoreWithScores(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByScoreWithScores(byte[] key, double max, double min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min, offset, count)); - } - - @Override - public Response> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByScoreWithScores(key, max, min, offset, count)); - } - - @Override - public Response zremrangeByRank(byte[] key, long start, long stop) { - return appendCommand(commandObjects.zremrangeByRank(key, start, stop)); - } - - @Override - public Response zremrangeByScore(byte[] key, double min, double max) { - return appendCommand(commandObjects.zremrangeByScore(key, min, max)); - } - - @Override - public Response zremrangeByScore(byte[] key, byte[] min, byte[] max) { - return appendCommand(commandObjects.zremrangeByScore(key, min, max)); - } - - @Override - public Response zlexcount(byte[] key, byte[] min, byte[] max) { - return appendCommand(commandObjects.zlexcount(key, min, max)); - } - - @Override - public Response> zrangeByLex(byte[] key, byte[] min, byte[] max) { - return appendCommand(commandObjects.zrangeByLex(key, min, max)); - } - - @Override - public Response> zrangeByLex(byte[] key, byte[] min, byte[] max, int offset, int count) { - return appendCommand(commandObjects.zrangeByLex(key, min, max, offset, count)); - } - - @Override - public Response> zrevrangeByLex(byte[] key, byte[] max, byte[] min) { - return appendCommand(commandObjects.zrevrangeByLex(key, min, max)); - } - - @Override - public Response> zrevrangeByLex(byte[] key, byte[] max, byte[] min, int offset, int count) { - return appendCommand(commandObjects.zrevrangeByLex(key, min, max, offset, count)); - } - - @Override - public Response zremrangeByLex(byte[] key, byte[] min, byte[] max) { - return appendCommand(commandObjects.zremrangeByLex(key, min, max)); - } - - @Override - public Response> zscan(byte[] key, byte[] cursor, ScanParams params) { - return appendCommand(commandObjects.zscan(key, cursor, params)); - } - - @Override - public Response> bzpopmax(double timeout, byte[]... keys) { - return appendCommand(commandObjects.bzpopmax(timeout, keys)); - } - - @Override - public Response> bzpopmin(double timeout, byte[]... keys) { - return appendCommand(commandObjects.bzpopmin(timeout, keys)); - } - - @Override - public Response>> zmpop(SortedSetOption option, byte[]... keys) { - return appendCommand(commandObjects.zmpop(option, keys)); - } - - @Override - public Response>> zmpop(SortedSetOption option, int count, byte[]... keys) { - return appendCommand(commandObjects.zmpop(option, count, keys)); - } - - @Override - public Response>> bzmpop(long timeout, SortedSetOption option, byte[]... keys) { - return appendCommand(commandObjects.bzmpop(timeout, option, keys)); - } - - @Override - public Response>> bzmpop(long timeout, SortedSetOption option, int count, byte[]... keys) { - return appendCommand(commandObjects.bzmpop(timeout, option, count, keys)); - } - - @Override - public Response> zdiff(byte[]... keys) { - return appendCommand(commandObjects.zdiff(keys)); - } - - @Override - public Response> zdiffWithScores(byte[]... keys) { - return appendCommand(commandObjects.zdiffWithScores(keys)); - } - - @Override - public Response zdiffStore(byte[] dstkey, byte[]... keys) { - return appendCommand(commandObjects.zdiffStore(dstkey, keys)); - } - - @Override - public Response> zinter(ZParams params, byte[]... keys) { - return appendCommand(commandObjects.zinter(params, keys)); - } - - @Override - public Response> zinterWithScores(ZParams params, byte[]... keys) { - return appendCommand(commandObjects.zinterWithScores(params, keys)); - } - - @Override - public Response zinterstore(byte[] dstkey, byte[]... sets) { - return appendCommand(commandObjects.zinterstore(dstkey, sets)); - } - - @Override - public Response zinterstore(byte[] dstkey, ZParams params, byte[]... sets) { - return appendCommand(commandObjects.zinterstore(dstkey, params, sets)); - } - - @Override - public Response zintercard(byte[]... keys) { - return appendCommand(commandObjects.zintercard(keys)); - } - - @Override - public Response zintercard(long limit, byte[]... keys) { - return appendCommand(commandObjects.zintercard(limit, keys)); - } - - @Override - public Response> zunion(ZParams params, byte[]... keys) { - return appendCommand(commandObjects.zunion(params, keys)); - } - - @Override - public Response> zunionWithScores(ZParams params, byte[]... keys) { - return appendCommand(commandObjects.zunionWithScores(params, keys)); - } - - @Override - public Response zunionstore(byte[] dstkey, byte[]... sets) { - return appendCommand(commandObjects.zunionstore(dstkey, sets)); - } - - @Override - public Response zunionstore(byte[] dstkey, ZParams params, byte[]... sets) { - return appendCommand(commandObjects.zunionstore(dstkey, params, sets)); - } - - @Override - public Response xadd(byte[] key, XAddParams params, Map hash) { - return appendCommand(commandObjects.xadd(key, params, hash)); - } - - @Override - public Response xlen(byte[] key) { - return appendCommand(commandObjects.xlen(key)); - } - - @Override - public Response> xrange(byte[] key, byte[] start, byte[] end) { - return appendCommand(commandObjects.xrange(key, start, end)); - } - - @Override - public Response> xrange(byte[] key, byte[] start, byte[] end, int count) { - return appendCommand(commandObjects.xrange(key, start, end, count)); - } - - @Override - public Response> xrevrange(byte[] key, byte[] end, byte[] start) { - return appendCommand(commandObjects.xrevrange(key, end, start)); - } - - @Override - public Response> xrevrange(byte[] key, byte[] end, byte[] start, int count) { - return appendCommand(commandObjects.xrevrange(key, end, start, count)); - } - - @Override - public Response xack(byte[] key, byte[] group, byte[]... ids) { - return appendCommand(commandObjects.xack(key, group, ids)); - } - - @Override - public Response xgroupCreate(byte[] key, byte[] groupName, byte[] id, boolean makeStream) { - return appendCommand(commandObjects.xgroupCreate(key, groupName, id, makeStream)); - } - - @Override - public Response xgroupSetID(byte[] key, byte[] groupName, byte[] id) { - return appendCommand(commandObjects.xgroupSetID(key, groupName, id)); - } - - @Override - public Response xgroupDestroy(byte[] key, byte[] groupName) { - return appendCommand(commandObjects.xgroupDestroy(key, groupName)); - } - - @Override - public Response xgroupCreateConsumer(byte[] key, byte[] groupName, byte[] consumerName) { - return appendCommand(commandObjects.xgroupCreateConsumer(key, groupName, consumerName)); - } - - @Override - public Response xgroupDelConsumer(byte[] key, byte[] groupName, byte[] consumerName) { - return appendCommand(commandObjects.xgroupDelConsumer(key, groupName, consumerName)); - } - - @Override - public Response xdel(byte[] key, byte[]... ids) { - return appendCommand(commandObjects.xdel(key, ids)); - } - - @Override - public Response xtrim(byte[] key, long maxLen, boolean approximateLength) { - return appendCommand(commandObjects.xtrim(key, maxLen, approximateLength)); - } - - @Override - public Response xtrim(byte[] key, XTrimParams params) { - return appendCommand(commandObjects.xtrim(key, params)); - } - - @Override - public Response xpending(byte[] key, byte[] groupName) { - return appendCommand(commandObjects.xpending(key, groupName)); - } - - @Override - public Response> xpending(byte[] key, byte[] groupName, byte[] start, byte[] end, int count, byte[] consumerName) { - return appendCommand(commandObjects.xpending(key, groupName, start, end, count, consumerName)); - } - - @Override - public Response> xpending(byte[] key, byte[] groupName, XPendingParams params) { - return appendCommand(commandObjects.xpending(key, groupName, params)); - } - - @Override - public Response> xclaim(byte[] key, byte[] group, byte[] consumerName, long minIdleTime, XClaimParams params, byte[]... ids) { - return appendCommand(commandObjects.xclaim(key, group, consumerName, minIdleTime, params, ids)); - } - - @Override - public Response> xclaimJustId(byte[] key, byte[] group, byte[] consumerName, long minIdleTime, XClaimParams params, byte[]... ids) { - return appendCommand(commandObjects.xclaimJustId(key, group, consumerName, minIdleTime, params, ids)); - } - - @Override - public Response> xautoclaim(byte[] key, byte[] groupName, byte[] consumerName, long minIdleTime, byte[] start, XAutoClaimParams params) { - return appendCommand(commandObjects.xautoclaim(key, groupName, consumerName, minIdleTime, start, params)); - } - - @Override - public Response> xautoclaimJustId(byte[] key, byte[] groupName, byte[] consumerName, long minIdleTime, byte[] start, XAutoClaimParams params) { - return appendCommand(commandObjects.xautoclaimJustId(key, groupName, consumerName, minIdleTime, start, params)); - } - - @Override - public Response xinfoStream(byte[] key) { - return appendCommand(commandObjects.xinfoStream(key)); - } - - @Override - public Response xinfoStreamFull(byte[] key) { - return appendCommand(commandObjects.xinfoStreamFull(key)); - } - - @Override - public Response xinfoStreamFull(byte[] key, int count) { - return appendCommand(commandObjects.xinfoStreamFull(key, count)); - } - - @Override - @Deprecated - public Response> xinfoGroup(byte[] key) { - return appendCommand(commandObjects.xinfoGroup(key)); - } - - @Override - public Response> xinfoGroups(byte[] key) { - return appendCommand(commandObjects.xinfoGroups(key)); - } - - @Override - public Response> xinfoConsumers(byte[] key, byte[] group) { - return appendCommand(commandObjects.xinfoConsumers(key, group)); - } - - @Override - public Response> xread(XReadParams xReadParams, Map.Entry... streams) { - return appendCommand(commandObjects.xread(xReadParams, streams)); - } - - @Override - public Response> xreadGroup(byte[] groupName, byte[] consumer, XReadGroupParams xReadGroupParams, Map.Entry... streams) { - return appendCommand(commandObjects.xreadGroup(groupName, consumer, xReadGroupParams, streams)); - } - - @Override - public Response set(byte[] key, byte[] value) { - return appendCommand(commandObjects.set(key, value)); - } - - @Override - public Response set(byte[] key, byte[] value, SetParams params) { - return appendCommand(commandObjects.set(key, value, params)); - } - - @Override - public Response get(byte[] key) { - return appendCommand(commandObjects.get(key)); - } - - @Override - public Response setGet(byte[] key, byte[] value, SetParams params) { - return appendCommand(commandObjects.setGet(key, value, params)); - } - - @Override - public Response getDel(byte[] key) { - return appendCommand(commandObjects.getDel(key)); - } - - @Override - public Response getEx(byte[] key, GetExParams params) { - return appendCommand(commandObjects.getEx(key, params)); - } - - @Override - public Response setbit(byte[] key, long offset, boolean value) { - return appendCommand(commandObjects.setbit(key, offset, value)); - } - - @Override - public Response getbit(byte[] key, long offset) { - return appendCommand(commandObjects.getbit(key, offset)); - } - - @Override - public Response setrange(byte[] key, long offset, byte[] value) { - return appendCommand(commandObjects.setrange(key, offset, value)); - } - - @Override - public Response getrange(byte[] key, long startOffset, long endOffset) { - return appendCommand(commandObjects.getrange(key, startOffset, endOffset)); - } - - @Override - public Response getSet(byte[] key, byte[] value) { - return appendCommand(commandObjects.getSet(key, value)); - } - - @Override - public Response setnx(byte[] key, byte[] value) { - return appendCommand(commandObjects.setnx(key, value)); - } - - @Override - public Response setex(byte[] key, long seconds, byte[] value) { - return appendCommand(commandObjects.setex(key, seconds, value)); - } - - @Override - public Response psetex(byte[] key, long milliseconds, byte[] value) { - return appendCommand(commandObjects.psetex(key, milliseconds, value)); - } - - @Override - public Response> mget(byte[]... keys) { - return appendCommand(commandObjects.mget(keys)); - } - - @Override - public Response mset(byte[]... keysvalues) { - return appendCommand(commandObjects.mset(keysvalues)); - } - - @Override - public Response msetnx(byte[]... keysvalues) { - return appendCommand(commandObjects.msetnx(keysvalues)); - } - - @Override - public Response incr(byte[] key) { - return appendCommand(commandObjects.incr(key)); - } - - @Override - public Response incrBy(byte[] key, long increment) { - return appendCommand(commandObjects.incrBy(key, increment)); - } - - @Override - public Response incrByFloat(byte[] key, double increment) { - return appendCommand(commandObjects.incrByFloat(key, increment)); - } - - @Override - public Response decr(byte[] key) { - return appendCommand(commandObjects.decr(key)); - } - - @Override - public Response decrBy(byte[] key, long decrement) { - return appendCommand(commandObjects.decrBy(key, decrement)); - } - - @Override - public Response append(byte[] key, byte[] value) { - return appendCommand(commandObjects.append(key, value)); - } - - @Override - public Response substr(byte[] key, int start, int end) { - return appendCommand(commandObjects.substr(key, start, end)); - } - - @Override - public Response strlen(byte[] key) { - return appendCommand(commandObjects.strlen(key)); - } - - @Override - public Response bitcount(byte[] key) { - return appendCommand(commandObjects.bitcount(key)); - } - - @Override - public Response bitcount(byte[] key, long start, long end) { - return appendCommand(commandObjects.bitcount(key, start, end)); - } - - @Override - public Response bitcount(byte[] key, long start, long end, BitCountOption option) { - return appendCommand(commandObjects.bitcount(key, start, end, option)); - } - - @Override - public Response bitpos(byte[] key, boolean value) { - return appendCommand(commandObjects.bitpos(key, value)); - } - - @Override - public Response bitpos(byte[] key, boolean value, BitPosParams params) { - return appendCommand(commandObjects.bitpos(key, value, params)); - } - - @Override - public Response> bitfield(byte[] key, byte[]... arguments) { - return appendCommand(commandObjects.bitfield(key, arguments)); - } - - @Override - public Response> bitfieldReadonly(byte[] key, byte[]... arguments) { - return appendCommand(commandObjects.bitfieldReadonly(key, arguments)); - } - - @Override - public Response bitop(BitOP op, byte[] destKey, byte[]... srcKeys) { - return appendCommand(commandObjects.bitop(op, destKey, srcKeys)); - } - - @Override - public Response strAlgoLCSKeys(byte[] keyA, byte[] keyB, StrAlgoLCSParams params) { - return appendCommand(commandObjects.strAlgoLCSKeys(keyA, keyB, params)); - } - - // RediSearch commands - @Override - public Response ftCreate(String indexName, IndexOptions indexOptions, Schema schema) { - return appendCommand(commandObjects.ftCreate(indexName, indexOptions, schema)); - } - - @Override - public Response ftCreate(String indexName, FTCreateParams createParams, Iterable schemaFields) { - return appendCommand(commandObjects.ftCreate(indexName, createParams, schemaFields)); - } - - @Override - public Response ftAlter(String indexName, Schema schema) { - return appendCommand(commandObjects.ftAlter(indexName, schema)); - } - - @Override - public Response ftAlter(String indexName, Iterable schemaFields) { - return appendCommand(commandObjects.ftAlter(indexName, schemaFields)); - } - - @Override - public Response ftSearch(String indexName, String query) { - return appendCommand(commandObjects.ftSearch(indexName, query)); - } - - @Override - public Response ftSearch(String indexName, String query, FTSearchParams searchParams) { - return appendCommand(commandObjects.ftSearch(indexName, query, searchParams)); - } - - @Override - public Response ftSearch(String indexName, Query query) { - return appendCommand(commandObjects.ftSearch(indexName, query)); - } - - @Override - public Response ftSearch(byte[] indexName, Query query) { - return appendCommand(commandObjects.ftSearch(indexName, query)); - } - - @Override - public Response ftExplain(String indexName, Query query) { - return appendCommand(commandObjects.ftExplain(indexName, query)); - } - - @Override - public Response> ftExplainCLI(String indexName, Query query) { - return appendCommand(commandObjects.ftExplainCLI(indexName, query)); - } - - @Override - public Response ftAggregate(String indexName, AggregationBuilder aggr) { - return appendCommand(commandObjects.ftAggregate(indexName, aggr)); - } - - @Override - public Response ftCursorRead(String indexName, long cursorId, int count) { - return appendCommand(commandObjects.ftCursorRead(indexName, cursorId, count)); - } - - @Override - public Response ftCursorDel(String indexName, long cursorId) { - return appendCommand(commandObjects.ftCursorDel(indexName, cursorId)); - } - - @Override - public Response ftDropIndex(String indexName) { - return appendCommand(commandObjects.ftDropIndex(indexName)); - } - - @Override - public Response ftDropIndexDD(String indexName) { - return appendCommand(commandObjects.ftDropIndexDD(indexName)); - } - - @Override - public Response ftSynUpdate(String indexName, String synonymGroupId, String... terms) { - return appendCommand(commandObjects.ftSynUpdate(indexName, synonymGroupId, terms)); - } - - @Override - public Response>> ftSynDump(String indexName) { - return appendCommand(commandObjects.ftSynDump(indexName)); - } - - @Override - public Response ftDictAdd(String dictionary, String... terms) { - return appendCommand(commandObjects.ftDictAdd(dictionary, terms)); - } - - @Override - public Response ftDictDel(String dictionary, String... terms) { - return appendCommand(commandObjects.ftDictDel(dictionary, terms)); - } - - @Override - public Response> ftDictDump(String dictionary) { - return appendCommand(commandObjects.ftDictDump(dictionary)); - } - - @Override - public Response ftDictAddBySampleKey(String indexName, String dictionary, String... terms) { - return appendCommand(commandObjects.ftDictAddBySampleKey(indexName, dictionary, terms)); - } - - @Override - public Response ftDictDelBySampleKey(String indexName, String dictionary, String... terms) { - return appendCommand(commandObjects.ftDictDelBySampleKey(indexName, dictionary, terms)); - } - - @Override - public Response> ftDictDumpBySampleKey(String indexName, String dictionary) { - return appendCommand(commandObjects.ftDictDumpBySampleKey(indexName, dictionary)); - } - - @Override - public Response>> ftSpellCheck(String index, String query) { - return appendCommand(commandObjects.ftSpellCheck(index, query)); - } - - @Override - public Response>> ftSpellCheck(String index, String query, FTSpellCheckParams spellCheckParams) { - return appendCommand(commandObjects.ftSpellCheck(index, query, spellCheckParams)); - } - - @Override - public Response> ftInfo(String indexName) { - return appendCommand(commandObjects.ftInfo(indexName)); - } - - @Override - public Response> ftTagVals(String indexName, String fieldName) { - return appendCommand(commandObjects.ftTagVals(indexName, fieldName)); - } - - @Override - public Response ftAliasAdd(String aliasName, String indexName) { - return appendCommand(commandObjects.ftAliasAdd(aliasName, indexName)); - } - - @Override - public Response ftAliasUpdate(String aliasName, String indexName) { - return appendCommand(commandObjects.ftAliasUpdate(aliasName, indexName)); - } - - @Override - public Response ftAliasDel(String aliasName) { - return appendCommand(commandObjects.ftAliasDel(aliasName)); - } - - @Override - public Response> ftConfigGet(String option) { - return appendCommand(commandObjects.ftConfigGet(option)); - } - - @Override - public Response> ftConfigGet(String indexName, String option) { - return appendCommand(commandObjects.ftConfigGet(indexName, option)); - } - - @Override - public Response ftConfigSet(String option, String value) { - return appendCommand(commandObjects.ftConfigSet(option, value)); - } - - @Override - public Response ftConfigSet(String indexName, String option, String value) { - return appendCommand(commandObjects.ftConfigSet(indexName, option, value)); - } - - @Override - public Response ftSugAdd(String key, String string, double score) { - return appendCommand(commandObjects.ftSugAdd(key, string, score)); - } - - @Override - public Response ftSugAddIncr(String key, String string, double score) { - return appendCommand(commandObjects.ftSugAddIncr(key, string, score)); - } - - @Override - public Response> ftSugGet(String key, String prefix) { - return appendCommand(commandObjects.ftSugGet(key, prefix)); - } - - @Override - public Response> ftSugGet(String key, String prefix, boolean fuzzy, int max) { - return appendCommand(commandObjects.ftSugGet(key, prefix, fuzzy, max)); - } - - @Override - public Response> ftSugGetWithScores(String key, String prefix) { - return appendCommand(commandObjects.ftSugGetWithScores(key, prefix)); - } - - @Override - public Response> ftSugGetWithScores(String key, String prefix, boolean fuzzy, int max) { - return appendCommand(commandObjects.ftSugGetWithScores(key, prefix, fuzzy, max)); - } - - @Override - public Response ftSugDel(String key, String string) { - return appendCommand(commandObjects.ftSugDel(key, string)); - } - - @Override - public Response ftSugLen(String key) { - return appendCommand(commandObjects.ftSugLen(key)); - } - // RediSearch commands - - // RedisJSON commands - @Override - public Response lcs(byte[] keyA, byte[] keyB, LCSParams params) { - return appendCommand(commandObjects.lcs(keyA, keyB, params)); - } - - - @Override - public Response jsonSet(String key, Path2 path, Object object) { - return appendCommand(commandObjects.jsonSet(key, path, object)); - } - - @Override - public Response jsonSetWithEscape(String key, Path2 path, Object object) { - return appendCommand(commandObjects.jsonSetWithEscape(key, path, object)); - } - - @Override - public Response jsonSet(String key, Path path, Object object) { - return appendCommand(commandObjects.jsonSet(key, path, object)); - } - - @Override - public Response jsonSet(String key, Path2 path, Object object, JsonSetParams params) { - return appendCommand(commandObjects.jsonSet(key, path, object, params)); - } - - @Override - public Response jsonSetWithEscape(String key, Path2 path, Object object, JsonSetParams params) { - return appendCommand(commandObjects.jsonSetWithEscape(key, path, object, params)); - } - - @Override - public Response jsonSet(String key, Path path, Object object, JsonSetParams params) { - return appendCommand(commandObjects.jsonSet(key, path, object, params)); - } - - @Override - public Response jsonGet(String key) { - return appendCommand(commandObjects.jsonGet(key)); - } - - @Override - public Response jsonGet(String key, Class clazz) { - return appendCommand(commandObjects.jsonGet(key, clazz)); - } - - @Override - public Response jsonGet(String key, Path2... paths) { - return appendCommand(commandObjects.jsonGet(key, paths)); - } - - @Override - public Response jsonGet(String key, Path... paths) { - return appendCommand(commandObjects.jsonGet(key, paths)); - } - - @Override - public Response jsonGet(String key, Class clazz, Path... paths) { - return appendCommand(commandObjects.jsonGet(key, clazz, paths)); - } - - @Override - public Response> jsonMGet(Path2 path, String... keys) { - return appendCommand(commandObjects.jsonMGet(path, keys)); - } - - @Override - public Response> jsonMGet(Path path, Class clazz, String... keys) { - return appendCommand(commandObjects.jsonMGet(path, clazz, keys)); - } - - @Override - public Response jsonDel(String key) { - return appendCommand(commandObjects.jsonDel(key)); - } - - @Override - public Response jsonDel(String key, Path2 path) { - return appendCommand(commandObjects.jsonDel(key, path)); - } - - @Override - public Response jsonDel(String key, Path path) { - return appendCommand(commandObjects.jsonDel(key, path)); - } - - @Override - public Response jsonClear(String key) { - return appendCommand(commandObjects.jsonClear(key)); - } - - @Override - public Response jsonClear(String key, Path2 path) { - return appendCommand(commandObjects.jsonClear(key, path)); - } - - @Override - public Response jsonClear(String key, Path path) { - return appendCommand(commandObjects.jsonClear(key, path)); - } - - @Override - public Response> jsonToggle(String key, Path2 path) { - return appendCommand(commandObjects.jsonToggle(key, path)); - } - - @Override - public Response jsonToggle(String key, Path path) { - return appendCommand(commandObjects.jsonToggle(key, path)); - } - - @Override - public Response> jsonType(String key) { - return appendCommand(commandObjects.jsonType(key)); - } - - @Override - public Response>> jsonType(String key, Path2 path) { - return appendCommand(commandObjects.jsonType(key, path)); - } - - @Override - public Response> jsonType(String key, Path path) { - return appendCommand(commandObjects.jsonType(key, path)); - } - - @Override - public Response jsonStrAppend(String key, Object string) { - return appendCommand(commandObjects.jsonStrAppend(key, string)); - } - - @Override - public Response> jsonStrAppend(String key, Path2 path, Object string) { - return appendCommand(commandObjects.jsonStrAppend(key, path, string)); - } - - @Override - public Response jsonStrAppend(String key, Path path, Object string) { - return appendCommand(commandObjects.jsonStrAppend(key, path, string)); - } - - @Override - public Response jsonStrLen(String key) { - return appendCommand(commandObjects.jsonStrLen(key)); - } - - @Override - public Response> jsonStrLen(String key, Path2 path) { - return appendCommand(commandObjects.jsonStrLen(key, path)); - } - - @Override - public Response jsonStrLen(String key, Path path) { - return appendCommand(commandObjects.jsonStrLen(key, path)); - } - - @Override - public Response jsonNumIncrBy(String key, Path2 path, double value) { - return appendCommand(commandObjects.jsonNumIncrBy(key, path, value)); - } - - @Override - public Response jsonNumIncrBy(String key, Path path, double value) { - return appendCommand(commandObjects.jsonNumIncrBy(key, path, value)); - } - - @Override - public Response> jsonArrAppend(String key, Path2 path, Object... objects) { - return appendCommand(commandObjects.jsonArrAppend(key, path, objects)); - } - - @Override - public Response> jsonArrAppendWithEscape(String key, Path2 path, Object... objects) { - return appendCommand(commandObjects.jsonArrAppendWithEscape(key, path, objects)); - } - - @Override - public Response jsonArrAppend(String key, Path path, Object... objects) { - return appendCommand(commandObjects.jsonArrAppend(key, path, objects)); - } - - @Override - public Response> jsonArrIndex(String key, Path2 path, Object scalar) { - return appendCommand(commandObjects.jsonArrIndex(key, path, scalar)); - } - - @Override - public Response> jsonArrIndexWithEscape(String key, Path2 path, Object scalar) { - return appendCommand(commandObjects.jsonArrIndexWithEscape(key, path, scalar)); - } - - @Override - public Response jsonArrIndex(String key, Path path, Object scalar) { - return appendCommand(commandObjects.jsonArrIndex(key, path, scalar)); - } - - @Override - public Response> jsonArrInsert(String key, Path2 path, int index, Object... objects) { - return appendCommand(commandObjects.jsonArrInsert(key, path, index, objects)); - } - - @Override - public Response> jsonArrInsertWithEscape(String key, Path2 path, int index, Object... objects) { - return appendCommand(commandObjects.jsonArrInsertWithEscape(key, path, index, objects)); - } - - @Override - public Response jsonArrInsert(String key, Path path, int index, Object... pojos) { - return appendCommand(commandObjects.jsonArrInsert(key, path, index, pojos)); - } - - @Override - public Response jsonArrPop(String key) { - return appendCommand(commandObjects.jsonArrPop(key)); - } - - @Override - public Response jsonArrLen(String key, Path path) { - return appendCommand(commandObjects.jsonArrLen(key, path)); - } - - @Override - public Response> jsonArrTrim(String key, Path2 path, int start, int stop) { - return appendCommand(commandObjects.jsonArrTrim(key, path, start, stop)); - } - - @Override - public Response jsonArrTrim(String key, Path path, int start, int stop) { - return appendCommand(commandObjects.jsonArrTrim(key, path, start, stop)); - } - - @Override - public Response jsonArrPop(String key, Class clazz, Path path) { - return appendCommand(commandObjects.jsonArrPop(key, clazz, path)); - } - - @Override - public Response> jsonArrPop(String key, Path2 path, int index) { - return appendCommand(commandObjects.jsonArrPop(key, path, index)); - } - - @Override - public Response jsonArrPop(String key, Path path, int index) { - return appendCommand(commandObjects.jsonArrPop(key, path, index)); - } - - @Override - public Response jsonArrPop(String key, Class clazz, Path path, int index) { - return appendCommand(commandObjects.jsonArrPop(key, clazz, path, index)); - } - - @Override - public Response jsonArrLen(String key) { - return appendCommand(commandObjects.jsonArrLen(key)); - } - - @Override - public Response> jsonArrLen(String key, Path2 path) { - return appendCommand(commandObjects.jsonArrLen(key, path)); - } - - @Override - public Response jsonArrPop(String key, Class clazz) { - return appendCommand(commandObjects.jsonArrPop(key, clazz)); - } - - @Override - public Response> jsonArrPop(String key, Path2 path) { - return appendCommand(commandObjects.jsonArrPop(key, path)); - } - - @Override - public Response jsonArrPop(String key, Path path) { - return appendCommand(commandObjects.jsonArrPop(key, path)); - } - // RedisJSON commands - - // RedisTimeSeries commands - @Override - public Response tsCreate(String key) { - return appendCommand(commandObjects.tsCreate(key)); - } - - @Override - public Response tsCreate(String key, TSCreateParams createParams) { - return appendCommand(commandObjects.tsCreate(key, createParams)); - } - - @Override - public Response tsDel(String key, long fromTimestamp, long toTimestamp) { - return appendCommand(commandObjects.tsDel(key, fromTimestamp, toTimestamp)); - } - - @Override - public Response tsAlter(String key, TSAlterParams alterParams) { - return appendCommand(commandObjects.tsAlter(key, alterParams)); - } - - @Override - public Response tsAdd(String key, double value) { - return appendCommand(commandObjects.tsAdd(key, value)); - } - - @Override - public Response tsAdd(String key, long timestamp, double value) { - return appendCommand(commandObjects.tsAdd(key, timestamp, value)); - } - - @Override - public Response tsAdd(String key, long timestamp, double value, TSCreateParams createParams) { - return appendCommand(commandObjects.tsAdd(key, timestamp, value, createParams)); - } - - @Override - public Response> tsMAdd(Map.Entry... entries) { - return appendCommand(commandObjects.tsMAdd(entries)); - } - - @Override - public Response tsIncrBy(String key, double value) { - return appendCommand(commandObjects.tsIncrBy(key, value)); - } - - @Override - public Response tsIncrBy(String key, double value, long timestamp) { - return appendCommand(commandObjects.tsIncrBy(key, value, timestamp)); - } - - @Override - public Response tsDecrBy(String key, double value) { - return appendCommand(commandObjects.tsDecrBy(key, value)); - } - - @Override - public Response tsDecrBy(String key, double value, long timestamp) { - return appendCommand(commandObjects.tsDecrBy(key, value, timestamp)); - } - - @Override - public Response> tsRange(String key, long fromTimestamp, long toTimestamp) { - return appendCommand(commandObjects.tsRange(key, fromTimestamp, toTimestamp)); - } - - @Override - public Response> tsRange(String key, TSRangeParams rangeParams) { - return appendCommand(commandObjects.tsRange(key, rangeParams)); - } - - @Override - public Response> tsRevRange(String key, long fromTimestamp, long toTimestamp) { - return appendCommand(commandObjects.tsRevRange(key, fromTimestamp, toTimestamp)); - } - - @Override - public Response> tsRevRange(String key, TSRangeParams rangeParams) { - return appendCommand(commandObjects.tsRevRange(key, rangeParams)); - } - - @Override - public Response> tsMRange(long fromTimestamp, long toTimestamp, String... filters) { - return appendCommand(commandObjects.tsMRange(fromTimestamp, toTimestamp, filters)); - } - - @Override - public Response> tsMRange(TSMRangeParams multiRangeParams) { - return appendCommand(commandObjects.tsMRange(multiRangeParams)); - } - - @Override - public Response> tsMRevRange(long fromTimestamp, long toTimestamp, String... filters) { - return appendCommand(commandObjects.tsMRevRange(fromTimestamp, toTimestamp, filters)); - } - - @Override - public Response> tsMRevRange(TSMRangeParams multiRangeParams) { - return appendCommand(commandObjects.tsMRevRange(multiRangeParams)); - } - - @Override - public Response tsGet(String key) { - return appendCommand(commandObjects.tsGet(key)); - } - - @Override - public Response tsGet(String key, TSGetParams getParams) { - return appendCommand(commandObjects.tsGet(key, getParams)); - } - - @Override - public Response>> tsMGet(TSMGetParams multiGetParams, String... filters) { - return appendCommand(commandObjects.tsMGet(multiGetParams, filters)); - } - - @Override - public Response tsCreateRule(String sourceKey, String destKey, AggregationType aggregationType, long timeBucket) { - return appendCommand(commandObjects.tsCreateRule(sourceKey, destKey, aggregationType, timeBucket)); - } - - @Override - public Response tsCreateRule(String sourceKey, String destKey, AggregationType aggregationType, long bucketDuration, long alignTimestamp) { - return appendCommand(commandObjects.tsCreateRule(sourceKey, destKey, aggregationType, bucketDuration, alignTimestamp)); - } - - @Override - public Response tsDeleteRule(String sourceKey, String destKey) { - return appendCommand(commandObjects.tsDeleteRule(sourceKey, destKey)); - } - - @Override - public Response> tsQueryIndex(String... filters) { - return appendCommand(commandObjects.tsQueryIndex(filters)); - } - // RedisTimeSeries commands - - // RedisBloom commands - @Override - public Response bfReserve(String key, double errorRate, long capacity) { - return appendCommand(commandObjects.bfReserve(key, errorRate, capacity)); - } - - @Override - public Response bfReserve(String key, double errorRate, long capacity, BFReserveParams reserveParams) { - return appendCommand(commandObjects.bfReserve(key, errorRate, capacity, reserveParams)); - } - - @Override - public Response bfAdd(String key, String item) { - return appendCommand(commandObjects.bfAdd(key, item)); - } - - @Override - public Response> bfMAdd(String key, String... items) { - return appendCommand(commandObjects.bfMAdd(key, items)); - } - - @Override - public Response> bfInsert(String key, String... items) { - return appendCommand(commandObjects.bfInsert(key, items)); - } - - @Override - public Response> bfInsert(String key, BFInsertParams insertParams, String... items) { - return appendCommand(commandObjects.bfInsert(key, insertParams, items)); - } - - @Override - public Response bfExists(String key, String item) { - return appendCommand(commandObjects.bfExists(key, item)); - } - - @Override - public Response> bfMExists(String key, String... items) { - return appendCommand(commandObjects.bfMExists(key, items)); - } - - @Override - public Response> bfScanDump(String key, long iterator) { - return appendCommand(commandObjects.bfScanDump(key, iterator)); - } - - @Override - public Response bfLoadChunk(String key, long iterator, byte[] data) { - return appendCommand(commandObjects.bfLoadChunk(key, iterator, data)); - } - - @Override - public Response bfCard(String key) { - return appendCommand(commandObjects.bfCard(key)); - } - - @Override - public Response> bfInfo(String key) { - return appendCommand(commandObjects.bfInfo(key)); - } - - @Override - public Response cfReserve(String key, long capacity) { - return appendCommand(commandObjects.cfReserve(key, capacity)); - } - - @Override - public Response cfReserve(String key, long capacity, CFReserveParams reserveParams) { - return appendCommand(commandObjects.cfReserve(key, capacity, reserveParams)); - } - - @Override - public Response cfAdd(String key, String item) { - return appendCommand(commandObjects.cfAdd(key, item)); - } - - @Override - public Response cfAddNx(String key, String item) { - return appendCommand(commandObjects.cfAddNx(key, item)); - } - - @Override - public Response> cfInsert(String key, String... items) { - return appendCommand(commandObjects.cfInsert(key, items)); - } - - @Override - public Response> cfInsert(String key, CFInsertParams insertParams, String... items) { - return appendCommand(commandObjects.cfInsert(key, insertParams, items)); - } - - @Override - public Response> cfInsertNx(String key, String... items) { - return appendCommand(commandObjects.cfInsertNx(key, items)); - } - - @Override - public Response> cfInsertNx(String key, CFInsertParams insertParams, String... items) { - return appendCommand(commandObjects.cfInsertNx(key, insertParams, items)); - } - - @Override - public Response cfExists(String key, String item) { - return appendCommand(commandObjects.cfExists(key, item)); - } - - @Override - public Response cfDel(String key, String item) { - return appendCommand(commandObjects.cfDel(key, item)); - } - - @Override - public Response cfCount(String key, String item) { - return appendCommand(commandObjects.cfCount(key, item)); - } - - @Override - public Response> cfScanDump(String key, long iterator) { - return appendCommand(commandObjects.cfScanDump(key, iterator)); - } - - @Override - public Response cfLoadChunk(String key, long iterator, byte[] data) { - return appendCommand(commandObjects.cfLoadChunk(key, iterator, data)); - } - - @Override - public Response> cfInfo(String key) { - return appendCommand(commandObjects.cfInfo(key)); - } - - @Override - public Response cmsInitByDim(String key, long width, long depth) { - return appendCommand(commandObjects.cmsInitByDim(key, width, depth)); - } - - @Override - public Response cmsInitByProb(String key, double error, double probability) { - return appendCommand(commandObjects.cmsInitByProb(key, error, probability)); - } - - @Override - public Response> cmsIncrBy(String key, Map itemIncrements) { - return appendCommand(commandObjects.cmsIncrBy(key, itemIncrements)); - } - - @Override - public Response> cmsQuery(String key, String... items) { - return appendCommand(commandObjects.cmsQuery(key, items)); - } - - @Override - public Response cmsMerge(String destKey, String... keys) { - return appendCommand(commandObjects.cmsMerge(destKey, keys)); - } - - @Override - public Response cmsMerge(String destKey, Map keysAndWeights) { - return appendCommand(commandObjects.cmsMerge(destKey, keysAndWeights)); - } - - @Override - public Response> cmsInfo(String key) { - return appendCommand(commandObjects.cmsInfo(key)); - } - - @Override - public Response topkReserve(String key, long topk) { - return appendCommand(commandObjects.topkReserve(key, topk)); - } - - @Override - public Response topkReserve(String key, long topk, long width, long depth, double decay) { - return appendCommand(commandObjects.topkReserve(key, topk, width, depth, decay)); - } - - @Override - public Response> topkAdd(String key, String... items) { - return appendCommand(commandObjects.topkAdd(key, items)); - } - - @Override - public Response> topkIncrBy(String key, Map itemIncrements) { - return appendCommand(commandObjects.topkIncrBy(key, itemIncrements)); - } - - @Override - public Response> topkQuery(String key, String... items) { - return appendCommand(commandObjects.topkQuery(key, items)); - } - - @Override - public Response> topkCount(String key, String... items) { - return appendCommand(commandObjects.topkCount(key, items)); - } - - @Override - public Response> topkList(String key) { - return appendCommand(commandObjects.topkList(key)); - } - - @Override - public Response> topkInfo(String key) { - return appendCommand(commandObjects.topkInfo(key)); - } - - @Override - public Response tdigestCreate(String key) { - return appendCommand(commandObjects.tdigestCreate(key)); - } - - @Override - public Response tdigestCreate(String key, int compression) { - return appendCommand(commandObjects.tdigestCreate(key, compression)); - } - - @Override - public Response tdigestReset(String key) { - return appendCommand(commandObjects.tdigestReset(key)); - } - - @Override - public Response tdigestMerge(String destinationKey, String... sourceKeys) { - return appendCommand(commandObjects.tdigestMerge(destinationKey, sourceKeys)); - } - - @Override - public Response tdigestMerge(TDigestMergeParams mergeParams, String destinationKey, String... sourceKeys) { - return appendCommand(commandObjects.tdigestMerge(mergeParams, destinationKey, sourceKeys)); - } - - @Override - public Response> tdigestInfo(String key) { - return appendCommand(commandObjects.tdigestInfo(key)); - } - - @Override - public Response tdigestAdd(String key, double... values) { - return appendCommand(commandObjects.tdigestAdd(key, values)); - } - - @Override - public Response> tdigestCDF(String key, double... values) { - return appendCommand(commandObjects.tdigestCDF(key, values)); - } - - @Override - public Response> tdigestQuantile(String key, double... quantiles) { - return appendCommand(commandObjects.tdigestQuantile(key, quantiles)); - } - - @Override - public Response tdigestMin(String key) { - return appendCommand(commandObjects.tdigestMin(key)); - } - - @Override - public Response tdigestMax(String key) { - return appendCommand(commandObjects.tdigestMax(key)); - } - - @Override - public Response tdigestTrimmedMean(String key, double lowCutQuantile, double highCutQuantile) { - return appendCommand(commandObjects.tdigestTrimmedMean(key, lowCutQuantile, highCutQuantile)); - } - - @Override - public Response> tdigestRank(String key, double... values) { - return appendCommand(commandObjects.tdigestRank(key, values)); - } - - @Override - public Response> tdigestRevRank(String key, double... values) { - return appendCommand(commandObjects.tdigestRevRank(key, values)); - } - - @Override - public Response> tdigestByRank(String key, long... ranks) { - return appendCommand(commandObjects.tdigestByRank(key, ranks)); - } - - @Override - public Response> tdigestByRevRank(String key, long... ranks) { - return appendCommand(commandObjects.tdigestByRevRank(key, ranks)); - } - // RedisBloom commands - - // RedisGraph commands - @Override - public Response graphQuery(String name, String query) { - return appendCommand(graphCommandObjects.graphQuery(name, query)); - } - - @Override - public Response graphReadonlyQuery(String name, String query) { - return appendCommand(graphCommandObjects.graphReadonlyQuery(name, query)); - } - - @Override - public Response graphQuery(String name, String query, long timeout) { - return appendCommand(graphCommandObjects.graphQuery(name, query, timeout)); - } - - @Override - public Response graphReadonlyQuery(String name, String query, long timeout) { - return appendCommand(graphCommandObjects.graphReadonlyQuery(name, query, timeout)); - } - - @Override - public Response graphQuery(String name, String query, Map params) { - return appendCommand(graphCommandObjects.graphQuery(name, query, params)); - } - - @Override - public Response graphReadonlyQuery(String name, String query, Map params) { - return appendCommand(graphCommandObjects.graphReadonlyQuery(name, query, params)); - } - - @Override - public Response graphQuery(String name, String query, Map params, long timeout) { - return appendCommand(graphCommandObjects.graphQuery(name, query, params, timeout)); - } - - @Override - public Response graphReadonlyQuery(String name, String query, Map params, long timeout) { - return appendCommand(graphCommandObjects.graphReadonlyQuery(name, query, params, timeout)); - } - - @Override - public Response graphDelete(String name) { - return appendCommand(graphCommandObjects.graphDelete(name)); - } - - @Override - public Response> graphProfile(String graphName, String query) { - return appendCommand(commandObjects.graphProfile(graphName, query)); - } - // RedisGraph commands - - public Response waitReplicas(int replicas, long timeout) { - return appendCommand(commandObjects.waitReplicas(replicas, timeout)); - } - - public Response sendCommand(ProtocolCommand cmd, String... args) { - return sendCommand(new CommandArguments(cmd).addObjects((Object[]) args)); - } - - public Response sendCommand(ProtocolCommand cmd, byte[]... args) { - return sendCommand(new CommandArguments(cmd).addObjects((Object[]) args)); - } - - public Response sendCommand(CommandArguments args) { - return executeCommand(new CommandObject<>(args, BuilderFactory.RAW_OBJECT)); - } - - public Response executeCommand(CommandObject command) { - return appendCommand(command); +/** + * @deprecated Use {@link AbstractTransaction}. + */ +@Deprecated +public abstract class TransactionBase extends AbstractTransaction { + + protected TransactionBase() { + super(); } } diff --git a/src/main/java/redis/clients/jedis/UnifiedJedis.java b/src/main/java/redis/clients/jedis/UnifiedJedis.java index 7a03f2ca3c..3ab2e43c88 100644 --- a/src/main/java/redis/clients/jedis/UnifiedJedis.java +++ b/src/main/java/redis/clients/jedis/UnifiedJedis.java @@ -17,18 +17,27 @@ import redis.clients.jedis.commands.SampleBinaryKeyedCommands; import redis.clients.jedis.commands.SampleKeyedCommands; import redis.clients.jedis.commands.RedisModuleCommands; +import redis.clients.jedis.exceptions.JedisException; import redis.clients.jedis.executors.*; +import redis.clients.jedis.gears.TFunctionListParams; +import redis.clients.jedis.gears.TFunctionLoadParams; +import redis.clients.jedis.gears.resps.GearsLibraryInfo; import redis.clients.jedis.graph.GraphCommandObjects; import redis.clients.jedis.graph.ResultSet; import redis.clients.jedis.json.JsonSetParams; import redis.clients.jedis.json.Path; import redis.clients.jedis.json.Path2; +import redis.clients.jedis.json.JsonObjectMapper; +import redis.clients.jedis.mcf.CircuitBreakerCommandExecutor; +import redis.clients.jedis.mcf.MultiClusterPipeline; +import redis.clients.jedis.mcf.MultiClusterTransaction; import redis.clients.jedis.params.*; import redis.clients.jedis.providers.*; import redis.clients.jedis.resps.*; import redis.clients.jedis.search.*; import redis.clients.jedis.search.aggr.AggregationBuilder; import redis.clients.jedis.search.aggr.AggregationResult; +import redis.clients.jedis.search.aggr.FtAggregateIteration; import redis.clients.jedis.search.schemafields.SchemaField; import redis.clients.jedis.timeseries.*; import redis.clients.jedis.util.IOUtils; @@ -39,10 +48,12 @@ public class UnifiedJedis implements JedisCommands, JedisBinaryCommands, SampleKeyedCommands, SampleBinaryKeyedCommands, RedisModuleCommands, AutoCloseable { + protected RedisProtocol protocol = null; protected final ConnectionProvider provider; protected final CommandExecutor executor; - private final CommandObjects commandObjects; - private final GraphCommandObjects graphCommandObjects = new GraphCommandObjects(this); + protected final CommandObjects commandObjects; + private final GraphCommandObjects graphCommandObjects; + private JedisBroadcastAndRoundRobinConfig broadcastAndRoundRobinConfig = null; public UnifiedJedis() { this(new HostAndPort(Protocol.DEFAULT_HOST, Protocol.DEFAULT_PORT)); @@ -60,7 +71,8 @@ public UnifiedJedis(final String url) { public UnifiedJedis(final URI uri) { this(JedisURIHelper.getHostAndPort(uri), DefaultJedisClientConfig.builder() .user(JedisURIHelper.getUser(uri)).password(JedisURIHelper.getPassword(uri)) - .database(JedisURIHelper.getDBIndex(uri)).ssl(JedisURIHelper.isRedisSSLScheme(uri)).build()); + .database(JedisURIHelper.getDBIndex(uri)).protocol(JedisURIHelper.getRedisProtocol(uri)) + .ssl(JedisURIHelper.isRedisSSLScheme(uri)).build()); } public UnifiedJedis(final URI uri, JedisClientConfig config) { @@ -70,6 +82,7 @@ public UnifiedJedis(final URI uri, JedisClientConfig config) { .blockingSocketTimeoutMillis(config.getBlockingSocketTimeoutMillis()) .user(JedisURIHelper.getUser(uri)).password(JedisURIHelper.getPassword(uri)) .database(JedisURIHelper.getDBIndex(uri)).clientName(config.getClientName()) + .protocol(JedisURIHelper.getRedisProtocol(uri)) .ssl(JedisURIHelper.isRedisSSLScheme(uri)).sslSocketFactory(config.getSslSocketFactory()) .sslParameters(config.getSslParameters()).hostnameVerifier(config.getHostnameVerifier()) .build()); @@ -78,12 +91,25 @@ public UnifiedJedis(final URI uri, JedisClientConfig config) { public UnifiedJedis(HostAndPort hostAndPort, JedisClientConfig clientConfig) { // this(new Connection(hostAndPort, clientConfig)); this(new PooledConnectionProvider(hostAndPort, clientConfig)); + RedisProtocol proto = clientConfig.getRedisProtocol(); + if (proto != null) commandObjects.setProtocol(proto); } public UnifiedJedis(ConnectionProvider provider) { this.provider = provider; this.executor = new DefaultCommandExecutor(provider); this.commandObjects = new CommandObjects(); + this.graphCommandObjects = new GraphCommandObjects(this); + this.graphCommandObjects.setBaseCommandArgumentsCreator((comm) -> this.commandObjects.commandArguments(comm)); + try (Connection conn = this.provider.getConnection()) { + if (conn != null) { + RedisProtocol proto = conn.getRedisProtocol(); + if (proto != null) commandObjects.setProtocol(proto); + } + //} catch (JedisAccessControlException ace) { + } catch (JedisException je) { // TODO: use specific exception(s) + // use default protocol + } } /** @@ -96,6 +122,16 @@ public UnifiedJedis(JedisSocketFactory socketFactory) { this(new Connection(socketFactory)); } + /** + * The constructor to directly use a custom {@link JedisSocketFactory}. + *

+ * WARNING: Using this constructor means a {@link NullPointerException} will be occurred if + * {@link UnifiedJedis#provider} is accessed. + */ + public UnifiedJedis(JedisSocketFactory socketFactory, JedisClientConfig clientConfig) { + this(new Connection(socketFactory, clientConfig)); + } + /** * The constructor to directly use a {@link Connection}. *

@@ -106,44 +142,84 @@ public UnifiedJedis(Connection connection) { this.provider = null; this.executor = new SimpleCommandExecutor(connection); this.commandObjects = new CommandObjects(); + this.graphCommandObjects = new GraphCommandObjects(this); + RedisProtocol proto = connection.getRedisProtocol(); + if (proto == RedisProtocol.RESP3) this.commandObjects.setProtocol(proto); } public UnifiedJedis(Set jedisClusterNodes, JedisClientConfig clientConfig, int maxAttempts) { this(new ClusterConnectionProvider(jedisClusterNodes, clientConfig), maxAttempts, Duration.ofMillis(maxAttempts * clientConfig.getSocketTimeoutMillis())); + RedisProtocol proto = clientConfig.getRedisProtocol(); + if (proto != null) commandObjects.setProtocol(proto); } public UnifiedJedis(Set jedisClusterNodes, JedisClientConfig clientConfig, int maxAttempts, Duration maxTotalRetriesDuration) { this(new ClusterConnectionProvider(jedisClusterNodes, clientConfig), maxAttempts, maxTotalRetriesDuration); + RedisProtocol proto = clientConfig.getRedisProtocol(); + if (proto != null) commandObjects.setProtocol(proto); } public UnifiedJedis(Set jedisClusterNodes, JedisClientConfig clientConfig, GenericObjectPoolConfig poolConfig, int maxAttempts, Duration maxTotalRetriesDuration) { this(new ClusterConnectionProvider(jedisClusterNodes, clientConfig, poolConfig), maxAttempts, maxTotalRetriesDuration); + RedisProtocol proto = clientConfig.getRedisProtocol(); + if (proto != null) commandObjects.setProtocol(proto); } public UnifiedJedis(ClusterConnectionProvider provider, int maxAttempts, Duration maxTotalRetriesDuration) { this.provider = provider; this.executor = new ClusterCommandExecutor(provider, maxAttempts, maxTotalRetriesDuration); this.commandObjects = new ClusterCommandObjects(); + this.graphCommandObjects = new GraphCommandObjects(this); + this.graphCommandObjects.setBaseCommandArgumentsCreator((comm) -> this.commandObjects.commandArguments(comm)); } + /** + * @deprecated Sharding/Sharded feature will be removed in next major release. + */ + @Deprecated public UnifiedJedis(ShardedConnectionProvider provider) { this.provider = provider; this.executor = new DefaultCommandExecutor(provider); this.commandObjects = new ShardedCommandObjects(provider.getHashingAlgo()); + this.graphCommandObjects = new GraphCommandObjects(this); + this.graphCommandObjects.setBaseCommandArgumentsCreator((comm) -> this.commandObjects.commandArguments(comm)); } + /** + * @deprecated Sharding/Sharded feature will be removed in next major release. + */ + @Deprecated public UnifiedJedis(ShardedConnectionProvider provider, Pattern tagPattern) { this.provider = provider; this.executor = new DefaultCommandExecutor(provider); this.commandObjects = new ShardedCommandObjects(provider.getHashingAlgo(), tagPattern); + this.graphCommandObjects = new GraphCommandObjects(this); + this.graphCommandObjects.setBaseCommandArgumentsCreator((comm) -> this.commandObjects.commandArguments(comm)); } public UnifiedJedis(ConnectionProvider provider, int maxAttempts, Duration maxTotalRetriesDuration) { this.provider = provider; this.executor = new RetryableCommandExecutor(provider, maxAttempts, maxTotalRetriesDuration); this.commandObjects = new CommandObjects(); + this.graphCommandObjects = new GraphCommandObjects(this); + this.graphCommandObjects.setBaseCommandArgumentsCreator((comm) -> this.commandObjects.commandArguments(comm)); + } + + /** + * Constructor which supports multiple cluster/database endpoints each with their own isolated connection pool. + *

+ * With this Constructor users can seamlessly failover to Disaster Recovery (DR), Backup, and Active-Active cluster(s) + * by using simple configuration which is passed through from Resilience4j - https://resilience4j.readme.io/docs + *

+ */ + public UnifiedJedis(MultiClusterPooledConnectionProvider provider) { + this.provider = provider; + this.executor = new CircuitBreakerCommandExecutor(provider); + this.commandObjects = new CommandObjects(); + this.graphCommandObjects = new GraphCommandObjects(this); + this.graphCommandObjects.setBaseCommandArgumentsCreator((comm) -> this.commandObjects.commandArguments(comm)); } /** @@ -156,6 +232,8 @@ public UnifiedJedis(CommandExecutor executor) { this.provider = null; this.executor = executor; this.commandObjects = new CommandObjects(); + this.graphCommandObjects = new GraphCommandObjects(this); + this.graphCommandObjects.setBaseCommandArgumentsCreator((comm) -> this.commandObjects.commandArguments(comm)); } @Override @@ -163,10 +241,52 @@ public void close() { IOUtils.closeQuietly(this.executor); } + protected final void setProtocol(RedisProtocol protocol) { + this.protocol = protocol; + this.commandObjects.setProtocol(this.protocol); + } + public final T executeCommand(CommandObject commandObject) { return executor.executeCommand(commandObject); } + public final T broadcastCommand(CommandObject commandObject) { + return executor.broadcastCommand(commandObject); + } + + private T checkAndBroadcastCommand(CommandObject commandObject) { + boolean broadcast = true; + + if (broadcastAndRoundRobinConfig == null) { + } else if (commandObject.getArguments().getCommand() instanceof SearchProtocol.SearchCommand + && broadcastAndRoundRobinConfig.getRediSearchModeInCluster() == JedisBroadcastAndRoundRobinConfig.RediSearchMode.LIGHT) { + broadcast = false; + } + + return broadcast ? broadcastCommand(commandObject) : executeCommand(commandObject); + } + + public void setBroadcastAndRoundRobinConfig(JedisBroadcastAndRoundRobinConfig config) { + this.broadcastAndRoundRobinConfig = config; + this.commandObjects.setBroadcastAndRoundRobinConfig(this.broadcastAndRoundRobinConfig); + } + + public String ping() { + return checkAndBroadcastCommand(commandObjects.ping()); + } + + public String flushDB() { + return checkAndBroadcastCommand(commandObjects.flushDB()); + } + + public String flushAll() { + return checkAndBroadcastCommand(commandObjects.flushAll()); + } + + public String configSet(String parameter, String value) { + return checkAndBroadcastCommand(commandObjects.configSet(parameter, value)); + } + // Key commands @Override public boolean exists(String key) { @@ -542,6 +662,25 @@ public ScanResult scan(String cursor, ScanParams params, String type) { return executeCommand(commandObjects.scan(cursor, params, type)); } + /** + * @param batchCount COUNT for each batch execution + * @param match pattern + * @return scan iteration + */ + public ScanIteration scanIteration(int batchCount, String match) { + return new ScanIteration(provider, batchCount, match); + } + + /** + * @param batchCount COUNT for each batch execution + * @param match pattern + * @param type key type + * @return scan iteration + */ + public ScanIteration scanIteration(int batchCount, String match, String type) { + return new ScanIteration(provider, batchCount, match, type); + } + @Override public Set keys(byte[] pattern) { return executeCommand(commandObjects.keys(pattern)); @@ -589,6 +728,11 @@ public String get(String key) { return executeCommand(commandObjects.get(key)); } + @Override + public String setGet(String key, String value) { + return executeCommand(commandObjects.setGet(key, value)); + } + @Override public String setGet(String key, String value, SetParams params) { return executeCommand(commandObjects.setGet(key, value, params)); @@ -619,6 +763,11 @@ public byte[] get(byte[] key) { return executeCommand(commandObjects.get(key)); } + @Override + public byte[] setGet(byte[] key, byte[] value) { + return executeCommand(commandObjects.setGet(key, value)); + } + @Override public byte[] setGet(byte[] key, byte[] value, SetParams params) { return executeCommand(commandObjects.setGet(key, value, params)); @@ -904,16 +1053,6 @@ public long bitop(BitOP op, byte[] destKey, byte[]... srcKeys) { return executeCommand(commandObjects.bitop(op, destKey, srcKeys)); } - @Override - public LCSMatchResult strAlgoLCSKeys(String keyA, String keyB, StrAlgoLCSParams params) { - return executeCommand(commandObjects.strAlgoLCSKeys(keyA, keyB, params)); - } - - @Override - public LCSMatchResult strAlgoLCSKeys(byte[] keyA, byte[] keyB, StrAlgoLCSParams params) { - return executeCommand(commandObjects.strAlgoLCSKeys(keyA, keyB, params)); - } - @Override public LCSMatchResult lcs(String keyA, String keyB, LCSParams params) { return executeCommand(commandObjects.lcs(keyA, keyB, params)); @@ -1112,7 +1251,7 @@ public List blpop(int timeout, String key) { } @Override - public KeyedListElement blpop(double timeout, String key) { + public KeyValue blpop(double timeout, String key) { return executeCommand(commandObjects.blpop(timeout, key)); } @@ -1122,7 +1261,7 @@ public List brpop(int timeout, String key) { } @Override - public KeyedListElement brpop(double timeout, String key) { + public KeyValue brpop(double timeout, String key) { return executeCommand(commandObjects.brpop(timeout, key)); } @@ -1132,7 +1271,7 @@ public List blpop(int timeout, String... keys) { } @Override - public KeyedListElement blpop(double timeout, String... keys) { + public KeyValue blpop(double timeout, String... keys) { return executeCommand(commandObjects.blpop(timeout, keys)); } @@ -1142,7 +1281,7 @@ public List brpop(int timeout, String... keys) { } @Override - public KeyedListElement brpop(double timeout, String... keys) { + public KeyValue brpop(double timeout, String... keys) { return executeCommand(commandObjects.brpop(timeout, keys)); } @@ -1152,7 +1291,7 @@ public List blpop(int timeout, byte[]... keys) { } @Override - public List blpop(double timeout, byte[]... keys) { + public KeyValue blpop(double timeout, byte[]... keys) { return executeCommand(commandObjects.blpop(timeout, keys)); } @@ -1162,7 +1301,7 @@ public List brpop(int timeout, byte[]... keys) { } @Override - public List brpop(double timeout, byte[]... keys) { + public KeyValue brpop(double timeout, byte[]... keys) { return executeCommand(commandObjects.brpop(timeout, keys)); } @@ -1217,12 +1356,12 @@ public KeyValue> lmpop(ListDirection direction, int count, } @Override - public KeyValue> blmpop(long timeout, ListDirection direction, String... keys) { + public KeyValue> blmpop(double timeout, ListDirection direction, String... keys) { return executeCommand(commandObjects.blmpop(timeout, direction, keys)); } @Override - public KeyValue> blmpop(long timeout, ListDirection direction, int count, String... keys) { + public KeyValue> blmpop(double timeout, ListDirection direction, int count, String... keys) { return executeCommand(commandObjects.blmpop(timeout, direction, count, keys)); } @@ -1237,12 +1376,12 @@ public KeyValue> lmpop(ListDirection direction, int count, } @Override - public KeyValue> blmpop(long timeout, ListDirection direction, byte[]... keys) { + public KeyValue> blmpop(double timeout, ListDirection direction, byte[]... keys) { return executeCommand(commandObjects.blmpop(timeout, direction, keys)); } @Override - public KeyValue> blmpop(long timeout, ListDirection direction, int count, byte[]... keys) { + public KeyValue> blmpop(double timeout, ListDirection direction, int count, byte[]... keys) { return executeCommand(commandObjects.blmpop(timeout, direction, count, keys)); } // List commands @@ -1399,7 +1538,7 @@ public List hrandfield(String key, long count) { } @Override - public Map hrandfieldWithValues(String key, long count) { + public List> hrandfieldWithValues(String key, long count) { return executeCommand(commandObjects.hrandfieldWithValues(key, count)); } @@ -1424,7 +1563,7 @@ public List hrandfield(byte[] key, long count) { } @Override - public Map hrandfieldWithValues(byte[] key, long count) { + public List> hrandfieldWithValues(byte[] key, long count) { return executeCommand(commandObjects.hrandfieldWithValues(key, count)); } @@ -1717,6 +1856,16 @@ public Long zrevrank(String key, String member) { return executeCommand(commandObjects.zrevrank(key, member)); } + @Override + public KeyValue zrankWithScore(String key, String member) { + return executeCommand(commandObjects.zrankWithScore(key, member)); + } + + @Override + public KeyValue zrevrankWithScore(String key, String member) { + return executeCommand(commandObjects.zrevrankWithScore(key, member)); + } + @Override public long zrem(byte[] key, byte[]... members) { return executeCommand(commandObjects.zrem(key, members)); @@ -1742,6 +1891,16 @@ public Long zrevrank(byte[] key, byte[] member) { return executeCommand(commandObjects.zrevrank(key, member)); } + @Override + public KeyValue zrankWithScore(byte[] key, byte[] member) { + return executeCommand(commandObjects.zrankWithScore(key, member)); + } + + @Override + public KeyValue zrevrankWithScore(byte[] key, byte[] member) { + return executeCommand(commandObjects.zrevrankWithScore(key, member)); + } + @Override public String zrandmember(String key) { return executeCommand(commandObjects.zrandmember(key)); @@ -2193,55 +2352,67 @@ public ScanResult zscan(byte[] key, byte[] cursor, ScanParams params) { } @Override - public KeyedZSetElement bzpopmax(double timeout, String... keys) { + public KeyValue bzpopmax(double timeout, String... keys) { return executeCommand(commandObjects.bzpopmax(timeout, keys)); } @Override - public KeyedZSetElement bzpopmin(double timeout, String... keys) { + public KeyValue bzpopmin(double timeout, String... keys) { return executeCommand(commandObjects.bzpopmin(timeout, keys)); } @Override - public List bzpopmax(double timeout, byte[]... keys) { + public KeyValue bzpopmax(double timeout, byte[]... keys) { return executeCommand(commandObjects.bzpopmax(timeout, keys)); } @Override - public List bzpopmin(double timeout, byte[]... keys) { + public KeyValue bzpopmin(double timeout, byte[]... keys) { return executeCommand(commandObjects.bzpopmin(timeout, keys)); } @Override - public Set zdiff(String... keys) { + public List zdiff(String... keys) { return executeCommand(commandObjects.zdiff(keys)); } @Override - public Set zdiffWithScores(String... keys) { + public List zdiffWithScores(String... keys) { return executeCommand(commandObjects.zdiffWithScores(keys)); } @Override + @Deprecated public long zdiffStore(String dstkey, String... keys) { return executeCommand(commandObjects.zdiffStore(dstkey, keys)); } @Override - public Set zdiff(byte[]... keys) { + public long zdiffstore(String dstkey, String... keys) { + return executeCommand(commandObjects.zdiffstore(dstkey, keys)); + } + + @Override + public List zdiff(byte[]... keys) { return executeCommand(commandObjects.zdiff(keys)); } @Override - public Set zdiffWithScores(byte[]... keys) { + public List zdiffWithScores(byte[]... keys) { return executeCommand(commandObjects.zdiffWithScores(keys)); } @Override + @Deprecated public long zdiffStore(byte[] dstkey, byte[]... keys) { return executeCommand(commandObjects.zdiffStore(dstkey, keys)); } + @Override + public long zdiffstore(byte[] dstkey, byte[]... keys) { + return executeCommand(commandObjects.zdiffstore(dstkey, keys)); + } + @Override public long zinterstore(String dstkey, String... sets) { return executeCommand(commandObjects.zinterstore(dstkey, sets)); @@ -2253,12 +2424,12 @@ public long zinterstore(String dstkey, ZParams params, String... sets) { } @Override - public Set zinter(ZParams params, String... keys) { + public List zinter(ZParams params, String... keys) { return executeCommand(commandObjects.zinter(params, keys)); } @Override - public Set zinterWithScores(ZParams params, String... keys) { + public List zinterWithScores(ZParams params, String... keys) { return executeCommand(commandObjects.zinterWithScores(params, keys)); } @@ -2293,22 +2464,22 @@ public long zintercard(long limit, String... keys) { } @Override - public Set zinter(ZParams params, byte[]... keys) { + public List zinter(ZParams params, byte[]... keys) { return executeCommand(commandObjects.zinter(params, keys)); } @Override - public Set zinterWithScores(ZParams params, byte[]... keys) { + public List zinterWithScores(ZParams params, byte[]... keys) { return executeCommand(commandObjects.zinterWithScores(params, keys)); } @Override - public Set zunion(ZParams params, String... keys) { + public List zunion(ZParams params, String... keys) { return executeCommand(commandObjects.zunion(params, keys)); } @Override - public Set zunionWithScores(ZParams params, String... keys) { + public List zunionWithScores(ZParams params, String... keys) { return executeCommand(commandObjects.zunionWithScores(params, keys)); } @@ -2323,12 +2494,12 @@ public long zunionstore(String dstkey, ZParams params, String... sets) { } @Override - public Set zunion(ZParams params, byte[]... keys) { + public List zunion(ZParams params, byte[]... keys) { return executeCommand(commandObjects.zunion(params, keys)); } @Override - public Set zunionWithScores(ZParams params, byte[]... keys) { + public List zunionWithScores(ZParams params, byte[]... keys) { return executeCommand(commandObjects.zunionWithScores(params, keys)); } @@ -2353,12 +2524,12 @@ public KeyValue> zmpop(SortedSetOption option, int count, St } @Override - public KeyValue> bzmpop(long timeout, SortedSetOption option, String... keys) { + public KeyValue> bzmpop(double timeout, SortedSetOption option, String... keys) { return executeCommand(commandObjects.bzmpop(timeout, option, keys)); } @Override - public KeyValue> bzmpop(long timeout, SortedSetOption option, int count, String... keys) { + public KeyValue> bzmpop(double timeout, SortedSetOption option, int count, String... keys) { return executeCommand(commandObjects.bzmpop(timeout, option, count, keys)); } @@ -2373,12 +2544,12 @@ public KeyValue> zmpop(SortedSetOption option, int count, by } @Override - public KeyValue> bzmpop(long timeout, SortedSetOption option, byte[]... keys) { + public KeyValue> bzmpop(double timeout, SortedSetOption option, byte[]... keys) { return executeCommand(commandObjects.bzmpop(timeout, option, keys)); } @Override - public KeyValue> bzmpop(long timeout, SortedSetOption option, int count, byte[]... keys) { + public KeyValue> bzmpop(double timeout, SortedSetOption option, int count, byte[]... keys) { return executeCommand(commandObjects.bzmpop(timeout, option, count, keys)); } // Sorted Set commands @@ -2798,11 +2969,6 @@ public StreamPendingSummary xpending(String key, String groupName) { return executeCommand(commandObjects.xpending(key, groupName)); } - @Override - public List xpending(String key, String groupName, StreamEntryID start, StreamEntryID end, int count, String consumerName) { - return executeCommand(commandObjects.xpending(key, groupName, start, end, count, consumerName)); - } - @Override public List xpending(String key, String groupName, XPendingParams params) { return executeCommand(commandObjects.xpending(key, groupName, params)); @@ -2858,12 +3024,6 @@ public StreamFullInfo xinfoStreamFull(String key, int count) { return executeCommand(commandObjects.xinfoStreamFull(key, count)); } - @Override - @Deprecated - public List xinfoGroup(String key) { - return executeCommand(commandObjects.xinfoGroup(key)); - } - @Override public List xinfoGroups(String key) { return executeCommand(commandObjects.xinfoGroups(key)); @@ -2874,6 +3034,11 @@ public List xinfoConsumers(String key, String group) { return executeCommand(commandObjects.xinfoConsumers(key, group)); } + @Override + public List xinfoConsumers2(String key, String group) { + return executeCommand(commandObjects.xinfoConsumers2(key, group)); + } + @Override public List>> xread(XReadParams xReadParams, Map streams) { return executeCommand(commandObjects.xread(xReadParams, streams)); @@ -2896,22 +3061,22 @@ public long xlen(byte[] key) { } @Override - public List xrange(byte[] key, byte[] start, byte[] end) { + public List xrange(byte[] key, byte[] start, byte[] end) { return executeCommand(commandObjects.xrange(key, start, end)); } @Override - public List xrange(byte[] key, byte[] start, byte[] end, int count) { + public List xrange(byte[] key, byte[] start, byte[] end, int count) { return executeCommand(commandObjects.xrange(key, start, end, count)); } @Override - public List xrevrange(byte[] key, byte[] end, byte[] start) { + public List xrevrange(byte[] key, byte[] end, byte[] start) { return executeCommand(commandObjects.xrevrange(key, end, start)); } @Override - public List xrevrange(byte[] key, byte[] end, byte[] start, int count) { + public List xrevrange(byte[] key, byte[] end, byte[] start, int count) { return executeCommand(commandObjects.xrevrange(key, end, start, count)); } @@ -2965,11 +3130,6 @@ public Object xpending(byte[] key, byte[] groupName) { return executeCommand(commandObjects.xpending(key, groupName)); } - @Override - public List xpending(byte[] key, byte[] groupName, byte[] start, byte[] end, int count, byte[] consumerName) { - return executeCommand(commandObjects.xpending(key, groupName, start, end, count, consumerName)); - } - @Override public List xpending(byte[] key, byte[] groupName, XPendingParams params) { return executeCommand(commandObjects.xpending(key, groupName, params)); @@ -3010,12 +3170,6 @@ public Object xinfoStreamFull(byte[] key, int count) { return executeCommand(commandObjects.xinfoStreamFull(key, count)); } - @Override - @Deprecated - public List xinfoGroup(byte[] key) { - return executeCommand(commandObjects.xinfoGroup(key)); - } - @Override public List xinfoGroups(byte[] key) { return executeCommand(commandObjects.xinfoGroups(key)); @@ -3027,12 +3181,12 @@ public List xinfoConsumers(byte[] key, byte[] group) { } @Override - public List xread(XReadParams xReadParams, Map.Entry... streams) { + public List xread(XReadParams xReadParams, Map.Entry... streams) { return executeCommand(commandObjects.xread(xReadParams, streams)); } @Override - public List xreadGroup(byte[] groupName, byte[] consumer, XReadGroupParams xReadGroupParams, Map.Entry... streams) { + public List xreadGroup(byte[] groupName, byte[] consumer, XReadGroupParams xReadGroupParams, Map.Entry... streams) { return executeCommand(commandObjects.xreadGroup(groupName, consumer, xReadGroupParams, streams)); } // Stream commands @@ -3130,22 +3284,22 @@ public Object fcallReadonly(String name, List keys, List args) { @Override public String functionDelete(String libraryName) { - return executeCommand(commandObjects.functionDelete(libraryName)); + return checkAndBroadcastCommand(commandObjects.functionDelete(libraryName)); } @Override public String functionFlush() { - return executeCommand(commandObjects.functionFlush()); + return checkAndBroadcastCommand(commandObjects.functionFlush()); } @Override public String functionFlush(FlushMode mode) { - return executeCommand(commandObjects.functionFlush(mode)); + return checkAndBroadcastCommand(commandObjects.functionFlush(mode)); } @Override public String functionKill() { - return executeCommand(commandObjects.functionKill()); + return checkAndBroadcastCommand(commandObjects.functionKill()); } @Override @@ -3170,12 +3324,12 @@ public List functionListWithCode(String libraryNamePattern) { @Override public String functionLoad(String functionCode) { - return executeCommand(commandObjects.functionLoad(functionCode)); + return checkAndBroadcastCommand(commandObjects.functionLoad(functionCode)); } @Override public String functionLoadReplace(String functionCode) { - return executeCommand(commandObjects.functionLoadReplace(functionCode)); + return checkAndBroadcastCommand(commandObjects.functionLoadReplace(functionCode)); } @Override @@ -3195,7 +3349,7 @@ public Object fcallReadonly(byte[] name, List keys, List args) { @Override public String functionDelete(byte[] libraryName) { - return executeCommand(commandObjects.functionDelete(libraryName)); + return checkAndBroadcastCommand(commandObjects.functionDelete(libraryName)); } @Override @@ -3225,22 +3379,22 @@ public List functionListWithCode(final byte[] libraryNamePattern) { @Override public String functionLoad(byte[] functionCode) { - return executeCommand(commandObjects.functionLoad(functionCode)); + return checkAndBroadcastCommand(commandObjects.functionLoad(functionCode)); } @Override public String functionLoadReplace(byte[] functionCode) { - return executeCommand(commandObjects.functionLoadReplace(functionCode)); + return checkAndBroadcastCommand(commandObjects.functionLoadReplace(functionCode)); } @Override public String functionRestore(byte[] serializedValue) { - return executeCommand(commandObjects.functionRestore(serializedValue)); + return checkAndBroadcastCommand(commandObjects.functionRestore(serializedValue)); } @Override public String functionRestore(byte[] serializedValue, FunctionRestorePolicy policy) { - return executeCommand(commandObjects.functionRestore(serializedValue, policy)); + return checkAndBroadcastCommand(commandObjects.functionRestore(serializedValue, policy)); } @Override @@ -3322,6 +3476,16 @@ public long waitReplicas(byte[] sampleKey, int replicas, long timeout) { return executeCommand(commandObjects.waitReplicas(sampleKey, replicas, timeout)); } + @Override + public KeyValue waitAOF(String sampleKey, long numLocal, long numReplicas, long timeout) { + return executeCommand(commandObjects.waitAOF(sampleKey, numLocal, numReplicas, timeout)); + } + + @Override + public KeyValue waitAOF(byte[] sampleKey, long numLocal, long numReplicas, long timeout) { + return executeCommand(commandObjects.waitAOF(sampleKey, numLocal, numReplicas, timeout)); + } + @Override public Object eval(String script, String sampleKey) { return executeCommand(commandObjects.eval(script, sampleKey)); @@ -3342,6 +3506,10 @@ public Object evalsha(byte[] sha1, byte[] sampleKey) { return executeCommand(commandObjects.evalsha(sha1, sampleKey)); } + public List scriptExists(List sha1s) { + return checkAndBroadcastCommand(commandObjects.scriptExists(sha1s)); + } + @Override public Boolean scriptExists(String sha1, String sampleKey) { return scriptExists(sampleKey, new String[]{sha1}).get(0); @@ -3362,11 +3530,19 @@ public List scriptExists(byte[] sampleKey, byte[]... sha1s) { return executeCommand(commandObjects.scriptExists(sampleKey, sha1s)); } + public String scriptLoad(String script) { + return checkAndBroadcastCommand(commandObjects.scriptLoad(script)); + } + @Override public String scriptLoad(String script, String sampleKey) { return executeCommand(commandObjects.scriptLoad(script, sampleKey)); } + public String scriptFlush() { + return checkAndBroadcastCommand(commandObjects.scriptFlush()); + } + @Override public String scriptFlush(String sampleKey) { return executeCommand(commandObjects.scriptFlush(sampleKey)); @@ -3377,6 +3553,10 @@ public String scriptFlush(String sampleKey, FlushMode flushMode) { return executeCommand(commandObjects.scriptFlush(sampleKey, flushMode)); } + public String scriptKill() { + return checkAndBroadcastCommand(commandObjects.scriptKill()); + } + @Override public String scriptKill(String sampleKey) { return executeCommand(commandObjects.scriptKill(sampleKey)); @@ -3401,6 +3581,10 @@ public String scriptFlush(byte[] sampleKey, FlushMode flushMode) { public String scriptKill(byte[] sampleKey) { return executeCommand(commandObjects.scriptKill(sampleKey)); } + + public String slowlogReset() { + return checkAndBroadcastCommand(commandObjects.slowlogReset()); + } // Sample key commands // Random node commands @@ -3435,35 +3619,60 @@ public void psubscribe(BinaryJedisPubSub jedisPubSub, final byte[]... patterns) jedisPubSub.proceedWithPatterns(connection, patterns); } } + // Random node commands - public LCSMatchResult strAlgoLCSStrings(final String strA, final String strB, final StrAlgoLCSParams params) { - return executeCommand(commandObjects.strAlgoLCSStrings(strA, strB, params)); + // RediSearch commands + public long hsetObject(String key, String field, Object value) { + return executeCommand(commandObjects.hsetObject(key, field, value)); } - public LCSMatchResult strAlgoLCSStrings(byte[] strA, byte[] strB, StrAlgoLCSParams params) { - return executeCommand(commandObjects.strAlgoLCSStrings(strA, strB, params)); + public long hsetObject(String key, Map hash) { + return executeCommand(commandObjects.hsetObject(key, hash)); } - // Random node commands - // RediSearch commands @Override public String ftCreate(String indexName, IndexOptions indexOptions, Schema schema) { - return executeCommand(commandObjects.ftCreate(indexName, indexOptions, schema)); + return checkAndBroadcastCommand(commandObjects.ftCreate(indexName, indexOptions, schema)); } @Override public String ftCreate(String indexName, FTCreateParams createParams, Iterable schemaFields) { - return executeCommand(commandObjects.ftCreate(indexName, createParams, schemaFields)); + return checkAndBroadcastCommand(commandObjects.ftCreate(indexName, createParams, schemaFields)); } @Override public String ftAlter(String indexName, Schema schema) { - return executeCommand(commandObjects.ftAlter(indexName, schema)); + return checkAndBroadcastCommand(commandObjects.ftAlter(indexName, schema)); } @Override public String ftAlter(String indexName, Iterable schemaFields) { - return executeCommand(commandObjects.ftAlter(indexName, schemaFields)); + return checkAndBroadcastCommand(commandObjects.ftAlter(indexName, schemaFields)); + } + + @Override + public String ftAliasAdd(String aliasName, String indexName) { + return checkAndBroadcastCommand(commandObjects.ftAliasAdd(aliasName, indexName)); + } + + @Override + public String ftAliasUpdate(String aliasName, String indexName) { + return checkAndBroadcastCommand(commandObjects.ftAliasUpdate(aliasName, indexName)); + } + + @Override + public String ftAliasDel(String aliasName) { + return checkAndBroadcastCommand(commandObjects.ftAliasDel(aliasName)); + } + + @Override + public String ftDropIndex(String indexName) { + return checkAndBroadcastCommand(commandObjects.ftDropIndex(indexName)); + } + + @Override + public String ftDropIndexDD(String indexName) { + return checkAndBroadcastCommand(commandObjects.ftDropIndexDD(indexName)); } @Override @@ -3476,12 +3685,36 @@ public SearchResult ftSearch(String indexName, String query, FTSearchParams para return executeCommand(commandObjects.ftSearch(indexName, query, params)); } + /** + * {@link FTSearchParams#limit(int, int)} will be ignored. + * @param batchSize batch size + * @param indexName index name + * @param query query + * @param params limit will be ignored + * @return search iteration + */ + public FtSearchIteration ftSearchIteration(int batchSize, String indexName, String query, FTSearchParams params) { + return new FtSearchIteration(provider, commandObjects.getProtocol(), batchSize, indexName, query, params); + } + @Override public SearchResult ftSearch(String indexName, Query query) { return executeCommand(commandObjects.ftSearch(indexName, query)); } + /** + * {@link Query#limit(java.lang.Integer, java.lang.Integer)} will be ignored. + * @param batchSize batch size + * @param indexName index name + * @param query limit will be ignored + * @return search iteration + */ + public FtSearchIteration ftSearchIteration(int batchSize, String indexName, Query query) { + return new FtSearchIteration(provider, commandObjects.getProtocol(), batchSize, indexName, query); + } + @Override + @Deprecated public SearchResult ftSearch(byte[] indexName, Query query) { return executeCommand(commandObjects.ftSearch(indexName, query)); } @@ -3511,6 +3744,16 @@ public String ftCursorDel(String indexName, long cursorId) { return executeCommand(commandObjects.ftCursorDel(indexName, cursorId)); } + /** + * {@link AggregationBuilder#cursor(int, long) CURSOR} must be set. + * @param indexName index name + * @param aggr cursor must be set + * @return aggregate iteration + */ + public FtAggregateIteration ftAggregateIteration(String indexName, AggregationBuilder aggr) { + return new FtAggregateIteration(provider, indexName, aggr); + } + @Override public Map.Entry> ftProfileAggregate(String indexName, FTProfileParams profileParams, AggregationBuilder aggr) { @@ -3529,16 +3772,6 @@ public Map.Entry> ftProfileSearch(String index return executeCommand(commandObjects.ftProfileSearch(indexName, profileParams, query, searchParams)); } - @Override - public String ftDropIndex(String indexName) { - return executeCommand(commandObjects.ftDropIndex(indexName)); - } - - @Override - public String ftDropIndexDD(String indexName) { - return executeCommand(commandObjects.ftDropIndexDD(indexName)); - } - @Override public String ftSynUpdate(String indexName, String synonymGroupId, String... terms) { return executeCommand(commandObjects.ftSynUpdate(indexName, synonymGroupId, terms)); @@ -3600,27 +3833,12 @@ public Set ftTagVals(String indexName, String fieldName) { } @Override - public String ftAliasAdd(String aliasName, String indexName) { - return executeCommand(commandObjects.ftAliasAdd(aliasName, indexName)); - } - - @Override - public String ftAliasUpdate(String aliasName, String indexName) { - return executeCommand(commandObjects.ftAliasUpdate(aliasName, indexName)); - } - - @Override - public String ftAliasDel(String aliasName) { - return executeCommand(commandObjects.ftAliasDel(aliasName)); - } - - @Override - public Map ftConfigGet(String option) { + public Map ftConfigGet(String option) { return executeCommand(commandObjects.ftConfigGet(option)); } @Override - public Map ftConfigGet(String indexName, String option) { + public Map ftConfigGet(String indexName, String option) { return executeCommand(commandObjects.ftConfigGet(indexName, option)); } @@ -3675,7 +3893,7 @@ public long ftSugLen(String key) { } @Override - public List ftList() { + public Set ftList() { return executeCommand(commandObjects.ftList()); } // RediSearch commands @@ -3692,11 +3910,13 @@ public String jsonSetWithEscape(String key, Path2 path, Object object) { } @Override + @Deprecated public String jsonSet(String key, Path path, Object pojo) { return executeCommand(commandObjects.jsonSet(key, path, pojo)); } @Override + @Deprecated public String jsonSetWithPlainString(String key, Path path, String string) { return executeCommand(commandObjects.jsonSetWithPlainString(key, path, string)); } @@ -3712,16 +3932,29 @@ public String jsonSetWithEscape(String key, Path2 path, Object pojo, JsonSetPara } @Override + @Deprecated public String jsonSet(String key, Path path, Object pojo, JsonSetParams params) { return executeCommand(commandObjects.jsonSet(key, path, pojo, params)); } + @Override + public String jsonMerge(String key, Path2 path, Object object) { + return executeCommand(commandObjects.jsonMerge(key, path, object)); + } + + @Override + @Deprecated + public String jsonMerge(String key, Path path, Object pojo) { + return executeCommand(commandObjects.jsonMerge(key, path, pojo)); + } + @Override public Object jsonGet(String key) { return executeCommand(commandObjects.jsonGet(key)); } @Override + @Deprecated public T jsonGet(String key, Class clazz) { return executeCommand(commandObjects.jsonGet(key, clazz)); } @@ -3732,16 +3965,19 @@ public Object jsonGet(String key, Path2... paths) { } @Override + @Deprecated public Object jsonGet(String key, Path... paths) { return executeCommand(commandObjects.jsonGet(key, paths)); } @Override + @Deprecated public String jsonGetAsPlainString(String key, Path path) { return executeCommand(commandObjects.jsonGetAsPlainString(key, path)); } @Override + @Deprecated public T jsonGet(String key, Class clazz, Path... paths) { return executeCommand(commandObjects.jsonGet(key, clazz, paths)); } @@ -3752,6 +3988,7 @@ public List jsonMGet(Path2 path, String... keys) { } @Override + @Deprecated public List jsonMGet(Path path, Class clazz, String... keys) { return executeCommand(commandObjects.jsonMGet(path, clazz, keys)); } @@ -3767,6 +4004,7 @@ public long jsonDel(String key, Path2 path) { } @Override + @Deprecated public long jsonDel(String key, Path path) { return executeCommand(commandObjects.jsonDel(key, path)); } @@ -3782,6 +4020,7 @@ public long jsonClear(String key, Path2 path) { } @Override + @Deprecated public long jsonClear(String key, Path path) { return executeCommand(commandObjects.jsonClear(key, path)); } @@ -3792,11 +4031,13 @@ public List jsonToggle(String key, Path2 path) { } @Override + @Deprecated public String jsonToggle(String key, Path path) { return executeCommand(commandObjects.jsonToggle(key, path)); } @Override + @Deprecated public Class jsonType(String key) { return executeCommand(commandObjects.jsonType(key)); } @@ -3807,11 +4048,13 @@ public List> jsonType(String key, Path2 path) { } @Override + @Deprecated public Class jsonType(String key, Path path) { return executeCommand(commandObjects.jsonType(key, path)); } @Override + @Deprecated public long jsonStrAppend(String key, Object string) { return executeCommand(commandObjects.jsonStrAppend(key, string)); } @@ -3822,11 +4065,13 @@ public List jsonStrAppend(String key, Path2 path, Object string) { } @Override + @Deprecated public long jsonStrAppend(String key, Path path, Object string) { return executeCommand(commandObjects.jsonStrAppend(key, path, string)); } @Override + @Deprecated public Long jsonStrLen(String key) { return executeCommand(commandObjects.jsonStrLen(key)); } @@ -3837,16 +4082,18 @@ public List jsonStrLen(String key, Path2 path) { } @Override + @Deprecated public Long jsonStrLen(String key, Path path) { return executeCommand(commandObjects.jsonStrLen(key, path)); } @Override - public JSONArray jsonNumIncrBy(String key, Path2 path, double value) { + public Object jsonNumIncrBy(String key, Path2 path, double value) { return executeCommand(commandObjects.jsonNumIncrBy(key, path, value)); } @Override + @Deprecated public double jsonNumIncrBy(String key, Path path, double value) { return executeCommand(commandObjects.jsonNumIncrBy(key, path, value)); } @@ -3862,6 +4109,7 @@ public List jsonArrAppendWithEscape(String key, Path2 path, Object... obje } @Override + @Deprecated public Long jsonArrAppend(String key, Path path, Object... pojos) { return executeCommand(commandObjects.jsonArrAppend(key, path, pojos)); } @@ -3877,6 +4125,7 @@ public List jsonArrIndexWithEscape(String key, Path2 path, Object scalar) } @Override + @Deprecated public long jsonArrIndex(String key, Path path, Object scalar) { return executeCommand(commandObjects.jsonArrIndex(key, path, scalar)); } @@ -3892,16 +4141,19 @@ public List jsonArrInsertWithEscape(String key, Path2 path, int index, Obj } @Override + @Deprecated public long jsonArrInsert(String key, Path path, int index, Object... pojos) { return executeCommand(commandObjects.jsonArrInsert(key, path, index, pojos)); } @Override + @Deprecated public Object jsonArrPop(String key) { return executeCommand(commandObjects.jsonArrPop(key)); } @Override + @Deprecated public T jsonArrPop(String key, Class clazz) { return executeCommand(commandObjects.jsonArrPop(key, clazz)); } @@ -3912,11 +4164,13 @@ public List jsonArrPop(String key, Path2 path) { } @Override + @Deprecated public Object jsonArrPop(String key, Path path) { return executeCommand(commandObjects.jsonArrPop(key, path)); } @Override + @Deprecated public T jsonArrPop(String key, Class clazz, Path path) { return executeCommand(commandObjects.jsonArrPop(key, clazz, path)); } @@ -3927,16 +4181,19 @@ public List jsonArrPop(String key, Path2 path, int index) { } @Override + @Deprecated public Object jsonArrPop(String key, Path path, int index) { return executeCommand(commandObjects.jsonArrPop(key, path, index)); } @Override + @Deprecated public T jsonArrPop(String key, Class clazz, Path path, int index) { return executeCommand(commandObjects.jsonArrPop(key, clazz, path, index)); } @Override + @Deprecated public Long jsonArrLen(String key) { return executeCommand(commandObjects.jsonArrLen(key)); } @@ -3947,6 +4204,7 @@ public List jsonArrLen(String key, Path2 path) { } @Override + @Deprecated public Long jsonArrLen(String key, Path path) { return executeCommand(commandObjects.jsonArrLen(key, path)); } @@ -3957,16 +4215,19 @@ public List jsonArrTrim(String key, Path2 path, int start, int stop) { } @Override + @Deprecated public Long jsonArrTrim(String key, Path path, int start, int stop) { return executeCommand(commandObjects.jsonArrTrim(key, path, start, stop)); } @Override + @Deprecated public Long jsonObjLen(String key) { return executeCommand(commandObjects.jsonObjLen(key)); } @Override + @Deprecated public Long jsonObjLen(String key, Path path) { return executeCommand(commandObjects.jsonObjLen(key, path)); } @@ -3977,11 +4238,13 @@ public List jsonObjLen(String key, Path2 path) { } @Override + @Deprecated public List jsonObjKeys(String key) { return executeCommand(commandObjects.jsonObjKeys(key)); } @Override + @Deprecated public List jsonObjKeys(String key, Path path) { return executeCommand(commandObjects.jsonObjKeys(key, path)); } @@ -3992,11 +4255,13 @@ public List> jsonObjKeys(String key, Path2 path) { } @Override + @Deprecated public long jsonDebugMemory(String key) { return executeCommand(commandObjects.jsonDebugMemory(key)); } @Override + @Deprecated public long jsonDebugMemory(String key, Path path) { return executeCommand(commandObjects.jsonDebugMemory(key, path)); } @@ -4005,21 +4270,6 @@ public long jsonDebugMemory(String key, Path path) { public List jsonDebugMemory(String key, Path2 path) { return executeCommand(commandObjects.jsonDebugMemory(key, path)); } - - @Override - public List jsonResp(String key) { - return executeCommand(commandObjects.jsonResp(key)); - } - - @Override - public List jsonResp(String key, Path path) { - return executeCommand(commandObjects.jsonResp(key, path)); - } - - @Override - public List> jsonResp(String key, Path2 path) { - return executeCommand(commandObjects.jsonResp(key, path)); - } // RedisJSON commands // RedisTimeSeries commands @@ -4104,22 +4354,22 @@ public List tsRevRange(String key, TSRangeParams rangeParams) { } @Override - public List tsMRange(long fromTimestamp, long toTimestamp, String... filters) { + public Map tsMRange(long fromTimestamp, long toTimestamp, String... filters) { return executeCommand(commandObjects.tsMRange(fromTimestamp, toTimestamp, filters)); } @Override - public List tsMRange(TSMRangeParams multiRangeParams) { + public Map tsMRange(TSMRangeParams multiRangeParams) { return executeCommand(commandObjects.tsMRange(multiRangeParams)); } @Override - public List tsMRevRange(long fromTimestamp, long toTimestamp, String... filters) { + public Map tsMRevRange(long fromTimestamp, long toTimestamp, String... filters) { return executeCommand(commandObjects.tsMRevRange(fromTimestamp, toTimestamp, filters)); } @Override - public List tsMRevRange(TSMRangeParams multiRangeParams) { + public Map tsMRevRange(TSMRangeParams multiRangeParams) { return executeCommand(commandObjects.tsMRevRange(multiRangeParams)); } @@ -4134,7 +4384,7 @@ public TSElement tsGet(String key, TSGetParams getParams) { } @Override - public List> tsMGet(TSMGetParams multiGetParams, String... filters) { + public Map tsMGet(TSMGetParams multiGetParams, String... filters) { return executeCommand(commandObjects.tsMGet(multiGetParams, filters)); } @@ -4365,15 +4615,14 @@ public List topkQuery(String key, String... items) { return executeCommand(commandObjects.topkQuery(key, items)); } - @Deprecated @Override - public List topkCount(String key, String... items) { - return executeCommand(commandObjects.topkCount(key, items)); + public List topkList(String key) { + return executeCommand(commandObjects.topkList(key)); } @Override - public List topkList(String key) { - return executeCommand(commandObjects.topkList(key)); + public Map topkListWithCount(String key) { + return executeCommand(commandObjects.topkListWithCount(key)); } @Override @@ -4464,91 +4713,144 @@ public List tdigestByRevRank(String key, long... ranks) { // RedisGraph commands @Override + @Deprecated public ResultSet graphQuery(String name, String query) { return executeCommand(graphCommandObjects.graphQuery(name, query)); } @Override + @Deprecated public ResultSet graphReadonlyQuery(String name, String query) { return executeCommand(graphCommandObjects.graphReadonlyQuery(name, query)); } @Override + @Deprecated public ResultSet graphQuery(String name, String query, long timeout) { return executeCommand(graphCommandObjects.graphQuery(name, query, timeout)); } @Override + @Deprecated public ResultSet graphReadonlyQuery(String name, String query, long timeout) { return executeCommand(graphCommandObjects.graphReadonlyQuery(name, query, timeout)); } @Override + @Deprecated public ResultSet graphQuery(String name, String query, Map params) { return executeCommand(graphCommandObjects.graphQuery(name, query, params)); } @Override + @Deprecated public ResultSet graphReadonlyQuery(String name, String query, Map params) { return executeCommand(graphCommandObjects.graphReadonlyQuery(name, query, params)); } @Override + @Deprecated public ResultSet graphQuery(String name, String query, Map params, long timeout) { return executeCommand(graphCommandObjects.graphQuery(name, query, params, timeout)); } @Override + @Deprecated public ResultSet graphReadonlyQuery(String name, String query, Map params, long timeout) { return executeCommand(graphCommandObjects.graphReadonlyQuery(name, query, params, timeout)); } @Override + @Deprecated public String graphDelete(String name) { return executeCommand(graphCommandObjects.graphDelete(name)); } @Override + @Deprecated public List graphList() { return executeCommand(commandObjects.graphList()); } @Override + @Deprecated public List graphProfile(String graphName, String query) { return executeCommand(commandObjects.graphProfile(graphName, query)); } @Override + @Deprecated public List graphExplain(String graphName, String query) { return executeCommand(commandObjects.graphExplain(graphName, query)); } @Override - public List> graphSlowlog(String graphName) { + @Deprecated + public List> graphSlowlog(String graphName) { return executeCommand(commandObjects.graphSlowlog(graphName)); } @Override + @Deprecated public String graphConfigSet(String configName, Object value) { return executeCommand(commandObjects.graphConfigSet(configName, value)); } @Override + @Deprecated public Map graphConfigGet(String configName) { return executeCommand(commandObjects.graphConfigGet(configName)); } // RedisGraph commands - public JedisBroadcast broadcast() { - return new JedisBroadcast(this); + // RedisGears commands + @Override + public String tFunctionLoad(String libraryCode, TFunctionLoadParams params) { + return executeCommand(commandObjects.tFunctionLoad(libraryCode, params)); + } + + @Override + public String tFunctionDelete(String libraryName) { + return executeCommand(commandObjects.tFunctionDelete(libraryName)); } - public Object pipelined() { + @Override + public List tFunctionList(TFunctionListParams params) { + return executeCommand(commandObjects.tFunctionList(params)); + } + + @Override + public Object tFunctionCall(String library, String function, List keys, List args) { + return executeCommand(commandObjects.tFunctionCall(library, function, keys, args)); + } + + @Override + public Object tFunctionCallAsync(String library, String function, List keys, List args) { + return executeCommand(commandObjects.tFunctionCallAsync(library, function, keys, args)); + } + // RedisGears commands + + /** + * @return pipeline object. Use {@link AbstractPipeline} instead of {@link PipelineBase}. + */ + public PipelineBase pipelined() { + if (provider == null) { + throw new IllegalStateException("It is not allowed to create Pipeline from this " + getClass()); + } else if (provider instanceof MultiClusterPooledConnectionProvider) { + return new MultiClusterPipeline((MultiClusterPooledConnectionProvider) provider); + } else { + return new Pipeline(provider.getConnection(), true); + } + } + + public AbstractTransaction multi() { if (provider == null) { throw new IllegalStateException("It is not allowed to create Pipeline from this " + getClass()); + } else if (provider instanceof MultiClusterPooledConnectionProvider) { + return new MultiClusterTransaction((MultiClusterPooledConnectionProvider) provider); + } else { + return new Transaction(provider.getConnection(), true, true); } - Connection connection = provider.getConnection(); - return new Pipeline(connection, true); } public Object sendCommand(ProtocolCommand cmd) { @@ -4590,4 +4892,12 @@ public Object sendBlockingCommand(String sampleKey, ProtocolCommand cmd, String. public Object executeCommand(CommandArguments args) { return executeCommand(new CommandObject<>(args, BuilderFactory.RAW_OBJECT)); } + + public void setJsonObjectMapper(JsonObjectMapper jsonObjectMapper) { + this.commandObjects.setJsonObjectMapper(jsonObjectMapper); + } + + public void setDefaultSearchDialect(int dialect) { + this.commandObjects.setDefaultSearchDialect(dialect); + } } diff --git a/src/main/java/redis/clients/jedis/args/ClientAttributeOption.java b/src/main/java/redis/clients/jedis/args/ClientAttributeOption.java new file mode 100644 index 0000000000..75bf92a76b --- /dev/null +++ b/src/main/java/redis/clients/jedis/args/ClientAttributeOption.java @@ -0,0 +1,23 @@ +package redis.clients.jedis.args; + +import redis.clients.jedis.util.SafeEncoder; + +/** + * CLIENT SETINFO command attr option + * since redis 7.2 + */ +public enum ClientAttributeOption implements Rawable { + LIB_NAME("LIB-NAME"), + LIB_VER("LIB-VER"); + + private final byte[] raw; + + private ClientAttributeOption(String str) { + this.raw = SafeEncoder.encode(str); + } + + @Override + public byte[] getRaw() { + return raw; + } +} diff --git a/src/main/java/redis/clients/jedis/args/RawableFactory.java b/src/main/java/redis/clients/jedis/args/RawableFactory.java index e5109d5afc..90bcc3c297 100644 --- a/src/main/java/redis/clients/jedis/args/RawableFactory.java +++ b/src/main/java/redis/clients/jedis/args/RawableFactory.java @@ -1,7 +1,9 @@ package redis.clients.jedis.args; import static redis.clients.jedis.Protocol.toByteArray; -import static redis.clients.jedis.util.SafeEncoder.encode; + +import java.util.Arrays; +import redis.clients.jedis.util.SafeEncoder; /** * Factory class to get {@link Rawable} objects. @@ -52,7 +54,7 @@ public static class Raw implements Rawable { private final byte[] raw; public Raw(byte[] raw) { - this.raw = raw; + this.raw = Arrays.copyOf(raw, raw.length); } @Override @@ -64,10 +66,17 @@ public byte[] getRaw() { /** * A {@link Rawable} wrapping a {@link String}. */ - public static class RawString extends Raw { + public static class RawString implements Rawable { + + private final byte[] raw; public RawString(String str) { - super(encode(str)); + this.raw = SafeEncoder.encode(str); + } + + @Override + public byte[] getRaw() { + return raw; } } diff --git a/src/main/java/redis/clients/jedis/bloom/RedisBloomProtocol.java b/src/main/java/redis/clients/jedis/bloom/RedisBloomProtocol.java index 7b103e867a..c60b9fcc4a 100644 --- a/src/main/java/redis/clients/jedis/bloom/RedisBloomProtocol.java +++ b/src/main/java/redis/clients/jedis/bloom/RedisBloomProtocol.java @@ -85,7 +85,6 @@ public enum TopKCommand implements ProtocolCommand { ADD("TOPK.ADD"), INCRBY("TOPK.INCRBY"), QUERY("TOPK.QUERY"), - COUNT("TOPK.COUNT"), LIST("TOPK.LIST"), INFO("TOPK.INFO"); @@ -121,7 +120,7 @@ public byte[] getRaw() { public enum RedisBloomKeyword implements Rawable { CAPACITY, ERROR, NOCREATE, EXPANSION, NONSCALING, BUCKETSIZE, MAXITERATIONS, ITEMS, WEIGHTS, - COMPRESSION, OVERRIDE; + COMPRESSION, OVERRIDE, WITHCOUNT; private final byte[] raw; diff --git a/src/main/java/redis/clients/jedis/bloom/commands/TopKFilterCommands.java b/src/main/java/redis/clients/jedis/bloom/commands/TopKFilterCommands.java index e4ff6bd43a..d16e31a72f 100644 --- a/src/main/java/redis/clients/jedis/bloom/commands/TopKFilterCommands.java +++ b/src/main/java/redis/clients/jedis/bloom/commands/TopKFilterCommands.java @@ -1,5 +1,6 @@ package redis.clients.jedis.bloom.commands; +import java.util.Collections; import java.util.List; import java.util.Map; @@ -35,6 +36,18 @@ public interface TopKFilterCommands { */ List topkAdd(String key, String... items); + /** + * {@code TOPK.INCRBY {key} {item} {increment}} + * + * @param key + * @param item + * @param increment + * @return item dropped from list + */ + default String topkIncrBy(String key, String item, long increment) { + return topkIncrBy(key, Collections.singletonMap(item, increment)).get(0); + } + /** * {@code TOPK.INCRBY {key} {item} {increment} [{item} {increment} ...]} * @@ -54,23 +67,20 @@ public interface TopKFilterCommands { List topkQuery(String key, String... items); /** - * {@code TOPK.COUNT {key} {item ...}} + * {@code TOPK.LIST {key}} * * @param key - * @param items - * @return count for item - * @deprecated As of RedisBloom 2.4, this command is regarded as deprecated. + * @return k (or less) items in Top K list */ - @Deprecated - List topkCount(String key, String... items); + List topkList(String key); /** - * {@code TOPK.LIST {key}} + * {@code TOPK.LIST {key} WITHCOUNT} * * @param key * @return k (or less) items in Top K list */ - List topkList(String key); + Map topkListWithCount(String key); /** * {@code TOPK.INFO {key}} diff --git a/src/main/java/redis/clients/jedis/bloom/commands/TopKFilterPipelineCommands.java b/src/main/java/redis/clients/jedis/bloom/commands/TopKFilterPipelineCommands.java index 5d96489c77..d75b3d7447 100644 --- a/src/main/java/redis/clients/jedis/bloom/commands/TopKFilterPipelineCommands.java +++ b/src/main/java/redis/clients/jedis/bloom/commands/TopKFilterPipelineCommands.java @@ -16,13 +16,9 @@ public interface TopKFilterPipelineCommands { Response> topkQuery(String key, String... items); - /** - * @deprecated As of RedisBloom 2.4, this command is regarded as deprecated. - */ - @Deprecated - Response> topkCount(String key, String... items); - Response> topkList(String key); + Response> topkListWithCount(String key); + Response> topkInfo(String key); } diff --git a/src/main/java/redis/clients/jedis/commands/AccessControlLogBinaryCommands.java b/src/main/java/redis/clients/jedis/commands/AccessControlLogBinaryCommands.java index 925286d38f..98aaec8c61 100644 --- a/src/main/java/redis/clients/jedis/commands/AccessControlLogBinaryCommands.java +++ b/src/main/java/redis/clients/jedis/commands/AccessControlLogBinaryCommands.java @@ -74,30 +74,20 @@ public interface AccessControlLogBinaryCommands { * Create an ACL for the specified user, while specifying the rules. * * @param name user who receives an acl - * @param keys the acl rules for the specified user + * @param rules the acl rules for the specified user * @see ACL SETUSER * @return A string containing OK on success */ - String aclSetUser(byte[] name, byte[]... keys); + String aclSetUser(byte[] name, byte[]... rules); /** * Delete the specified user, from the ACL. * - * @param name The username to delete + * @param names The username to delete * @see ACL DELUSER * @return The number of users delete */ - long aclDelUser(byte[] name); - - /** - * Delete the specified users, from the ACL. - * - * @param name The username to delete - * @param names Other usernames to delete - * @see ACL DELUSER - * @return The number of users delete - */ - long aclDelUser(byte[] name, byte[]... names); + long aclDelUser(byte[]... names); /** * Show the available ACL categories. diff --git a/src/main/java/redis/clients/jedis/commands/AccessControlLogCommands.java b/src/main/java/redis/clients/jedis/commands/AccessControlLogCommands.java index b6f6b85cde..a65207c038 100644 --- a/src/main/java/redis/clients/jedis/commands/AccessControlLogCommands.java +++ b/src/main/java/redis/clients/jedis/commands/AccessControlLogCommands.java @@ -76,30 +76,20 @@ public interface AccessControlLogCommands { * Create an ACL for the specified user, while specifying the rules. * * @param name user who receives an acl - * @param keys the acl rules for the specified user + * @param rules the acl rules for the specified user * @see ACL SETUSER * @return A string containing OK on success */ - String aclSetUser(String name, String... keys); + String aclSetUser(String name, String... rules); /** * Delete the specified user, from the ACL. * - * @param name The username to delete + * @param names The usernames to delete * @see ACL DELUSER * @return The number of users delete */ - long aclDelUser(String name); - - /** - * Delete the specified users, from the ACL. - * - * @param name The username to delete - * @param names Other usernames to delete - * @see ACL DELUSER - * @return The number of users delete - */ - long aclDelUser(String name, String... names); + long aclDelUser(String... names); /** * Show the available ACL categories. diff --git a/src/main/java/redis/clients/jedis/commands/ClientBinaryCommands.java b/src/main/java/redis/clients/jedis/commands/ClientBinaryCommands.java index 8dcbdca122..ef32730a1a 100644 --- a/src/main/java/redis/clients/jedis/commands/ClientBinaryCommands.java +++ b/src/main/java/redis/clients/jedis/commands/ClientBinaryCommands.java @@ -1,5 +1,6 @@ package redis.clients.jedis.commands; +import redis.clients.jedis.args.ClientAttributeOption; import redis.clients.jedis.args.ClientPauseMode; import redis.clients.jedis.args.ClientType; import redis.clients.jedis.args.UnblockType; @@ -45,7 +46,7 @@ public interface ClientBinaryCommands { /** * Returns information and statistics about the client connections server - * in a mostly human readable format. + * in a mostly human-readable format. * * @return All clients info connected to redis-server */ @@ -53,7 +54,7 @@ public interface ClientBinaryCommands { /** * Returns information and statistics about the client connections server - * in a mostly human readable format filter by client type. + * in a mostly human-readable format filter by client type. * * @return all clients info connected to redis-server */ @@ -61,7 +62,7 @@ public interface ClientBinaryCommands { /** * Returns information and statistics about the client connections server - * in a mostly human readable format filter by client ids. + * in a mostly human-readable format filter by client ids. * * @param clientIds Unique 64-bit client IDs * @return All clients info connected to redis-server @@ -70,12 +71,21 @@ public interface ClientBinaryCommands { /** * Returns information and statistics about the current client connection - * in a mostly human readable format. + * in a mostly human-readable format. * * @return Information and statistics about the current client connection */ byte[] clientInfoBinary(); + /** + * client set info command + * Since redis 7.2 + * @param attr the attr option + * @param value the value + * @return OK or error + */ + String clientSetInfo(ClientAttributeOption attr, byte[] value); + /** * Assigns a name to the current connection. * diff --git a/src/main/java/redis/clients/jedis/commands/ClientCommands.java b/src/main/java/redis/clients/jedis/commands/ClientCommands.java index 7052936064..edcfbd602e 100644 --- a/src/main/java/redis/clients/jedis/commands/ClientCommands.java +++ b/src/main/java/redis/clients/jedis/commands/ClientCommands.java @@ -1,5 +1,6 @@ package redis.clients.jedis.commands; +import redis.clients.jedis.args.ClientAttributeOption; import redis.clients.jedis.args.ClientPauseMode; import redis.clients.jedis.args.ClientType; import redis.clients.jedis.args.UnblockType; @@ -45,7 +46,7 @@ public interface ClientCommands { /** * Returns information and statistics about the client connections server - * in a mostly human readable format. + * in a mostly human-readable format. * * @return All clients info connected to redis-server */ @@ -53,7 +54,7 @@ public interface ClientCommands { /** * Returns information and statistics about the client connections server - * in a mostly human readable format filter by client type. + * in a mostly human-readable format filter by client type. * * @return All clients info connected to redis-server */ @@ -61,7 +62,7 @@ public interface ClientCommands { /** * Returns information and statistics about the client connections server - * in a mostly human readable format filter by client ids. + * in a mostly human-readable format filter by client ids. * * @param clientIds Unique 64-bit client IDs * @return All clients info connected to redis-server @@ -70,12 +71,21 @@ public interface ClientCommands { /** * Returns information and statistics about the current client connection - * in a mostly human readable format. + * in a mostly human-readable format. * * @return Information and statistics about the current client connection */ String clientInfo(); + /** + * client set info command + * Since redis 7.2 + * @param attr the attr option + * @param value the value + * @return OK or error + */ + String clientSetInfo(ClientAttributeOption attr, String value); + /** * Assigns a name to the current connection. * @@ -148,4 +158,16 @@ public interface ClientCommands { * @return OK */ String clientNoEvictOff(); + + /** + * Turn on CLIENT NO-TOUCH + * @return OK + */ + String clientNoTouchOn(); + + /** + * Turn off CLIENT NO-TOUCH + * @return OK + */ + String clientNoTouchOff(); } diff --git a/src/main/java/redis/clients/jedis/commands/ClusterCommands.java b/src/main/java/redis/clients/jedis/commands/ClusterCommands.java index 8fdf5d7335..4ad918d12b 100644 --- a/src/main/java/redis/clients/jedis/commands/ClusterCommands.java +++ b/src/main/java/redis/clients/jedis/commands/ClusterCommands.java @@ -5,6 +5,7 @@ import redis.clients.jedis.args.ClusterResetType; import redis.clients.jedis.args.ClusterFailoverOption; +import redis.clients.jedis.resps.ClusterShardInfo; public interface ClusterCommands { @@ -79,8 +80,24 @@ public interface ClusterCommands { String clusterFailover(ClusterFailoverOption failoverOption); + /** + * {@code CLUSTER SLOTS} command is deprecated since Redis 7. + * + * @deprecated Use {@link ClusterCommands#clusterShards()}. + */ + @Deprecated List clusterSlots(); + /** + * {@code CLUSTER SHARDS} returns details about the shards of the cluster. + * This command replaces the {@code CLUSTER SLOTS} command from Redis 7, + * by providing a more efficient and extensible representation of the cluster. + * + * @return a list of shards, with each shard containing two objects, 'slots' and 'nodes'. + * @see CLUSTER SHARDS + */ + List clusterShards(); + String clusterReset(); /** @@ -93,6 +110,8 @@ public interface ClusterCommands { String clusterMyId(); + String clusterMyShardId(); + /** * return the information of all such peer links as an array, where each array element is a map that contains * attributes and their values for an individual link. @@ -106,7 +125,7 @@ public interface ClusterCommands { * Takes a list of slot ranges (specified by start and end slots) to assign to the node * * @param ranges slots range - * @return OK if the command was successful. Otherwise an error is returned. + * @return OK if the command was successful. Otherwise, an error is returned. */ String clusterAddSlotsRange(int... ranges); @@ -114,7 +133,7 @@ public interface ClusterCommands { * Takes a list of slot ranges (specified by start and end slots) to remove to the node. * * @param ranges slots range - * @return OK if the command was successful. Otherwise an error is returned. + * @return OK if the command was successful. Otherwise, an error is returned. */ String clusterDelSlotsRange(int... ranges); } diff --git a/src/main/java/redis/clients/jedis/commands/ConfigCommands.java b/src/main/java/redis/clients/jedis/commands/ConfigCommands.java index 268205b1cb..3c099043da 100644 --- a/src/main/java/redis/clients/jedis/commands/ConfigCommands.java +++ b/src/main/java/redis/clients/jedis/commands/ConfigCommands.java @@ -1,6 +1,6 @@ package redis.clients.jedis.commands; -import java.util.List; +import java.util.Map; /** * The interface about managing configuration parameters of Redis server. @@ -13,7 +13,7 @@ public interface ConfigCommands { * @param pattern name of Redis server's configuration * @return config value of Redis server */ - List configGet(String pattern); + Map configGet(String pattern); /** * Used to read the configuration parameters of Redis server. @@ -21,7 +21,7 @@ public interface ConfigCommands { * @param patterns names of Redis server's configuration * @return values of Redis server's configuration */ - List configGet(String... patterns); + Map configGet(String... patterns); /** * Used to read the configuration parameters of Redis server. @@ -29,7 +29,7 @@ public interface ConfigCommands { * @param pattern name of Redis server's configuration * @return value of Redis server's configuration */ - List configGet(byte[] pattern); + Map configGet(byte[] pattern); /** * Used to read the configuration parameters of Redis server. @@ -37,7 +37,7 @@ public interface ConfigCommands { * @param patterns names of Redis server's configuration * @return values of Redis server's configuration */ - List configGet(byte[]... patterns); + Map configGet(byte[]... patterns); /** * Used in order to reconfigure the Redis server at run time without @@ -52,6 +52,8 @@ public interface ConfigCommands { String configSet(String... parameterValues); + String configSet(Map parameterValues); + /** * Used in order to reconfigure the Redis server at run time without * the need to restart. @@ -65,6 +67,8 @@ public interface ConfigCommands { String configSet(byte[]... parameterValues); + String configSetBinary(Map parameterValues); + /** * Resets the statistics reported by Redis using the INFO command. *

diff --git a/src/main/java/redis/clients/jedis/commands/DatabaseCommands.java b/src/main/java/redis/clients/jedis/commands/DatabaseCommands.java index 8c87bea3e1..7b629bd970 100644 --- a/src/main/java/redis/clients/jedis/commands/DatabaseCommands.java +++ b/src/main/java/redis/clients/jedis/commands/DatabaseCommands.java @@ -18,6 +18,13 @@ public interface DatabaseCommands { */ long dbSize(); + /** + * Delete all the keys of the currently selected DB. This command never fails. The time-complexity + * for this operation is O(N), N being the number of keys in the database. + * @return OK + */ + String flushDB(); + /** * Delete all the keys of the currently selected DB. This command never fails. The time-complexity * for this operation is O(N), N being the number of keys in the database. diff --git a/src/main/java/redis/clients/jedis/commands/HashBinaryCommands.java b/src/main/java/redis/clients/jedis/commands/HashBinaryCommands.java index 2a4fabe51c..196f7512a8 100644 --- a/src/main/java/redis/clients/jedis/commands/HashBinaryCommands.java +++ b/src/main/java/redis/clients/jedis/commands/HashBinaryCommands.java @@ -41,7 +41,7 @@ public interface HashBinaryCommands { List hrandfield(byte[] key, long count); - Map hrandfieldWithValues(byte[] key, long count); + List> hrandfieldWithValues(byte[] key, long count); default ScanResult> hscan(byte[] key, byte[] cursor) { return hscan(key, cursor, new ScanParams()); diff --git a/src/main/java/redis/clients/jedis/commands/HashCommands.java b/src/main/java/redis/clients/jedis/commands/HashCommands.java index 84ad32c6d8..d319c4fa39 100644 --- a/src/main/java/redis/clients/jedis/commands/HashCommands.java +++ b/src/main/java/redis/clients/jedis/commands/HashCommands.java @@ -41,7 +41,7 @@ public interface HashCommands { List hrandfield(String key, long count); - Map hrandfieldWithValues(String key, long count); + List> hrandfieldWithValues(String key, long count); default ScanResult> hscan(String key, String cursor) { return hscan(key, cursor, new ScanParams()); diff --git a/src/main/java/redis/clients/jedis/commands/HashPipelineBinaryCommands.java b/src/main/java/redis/clients/jedis/commands/HashPipelineBinaryCommands.java index e7624a0ca5..e87dcacdb3 100644 --- a/src/main/java/redis/clients/jedis/commands/HashPipelineBinaryCommands.java +++ b/src/main/java/redis/clients/jedis/commands/HashPipelineBinaryCommands.java @@ -42,7 +42,7 @@ public interface HashPipelineBinaryCommands { Response> hrandfield(byte[] key, long count); - Response> hrandfieldWithValues(byte[] key, long count); + Response>> hrandfieldWithValues(byte[] key, long count); default Response>> hscan(byte[] key, byte[] cursor) { return hscan(key, cursor, new ScanParams()); diff --git a/src/main/java/redis/clients/jedis/commands/HashPipelineCommands.java b/src/main/java/redis/clients/jedis/commands/HashPipelineCommands.java index ea11b0b77e..3aa256cb78 100644 --- a/src/main/java/redis/clients/jedis/commands/HashPipelineCommands.java +++ b/src/main/java/redis/clients/jedis/commands/HashPipelineCommands.java @@ -42,7 +42,7 @@ public interface HashPipelineCommands { Response> hrandfield(String key, long count); - Response> hrandfieldWithValues(String key, long count); + Response>> hrandfieldWithValues(String key, long count); default Response>> hscan(String key, String cursor) { return hscan(key, cursor, new ScanParams()); diff --git a/src/main/java/redis/clients/jedis/commands/ListBinaryCommands.java b/src/main/java/redis/clients/jedis/commands/ListBinaryCommands.java index b3a566df9a..cc61fd84be 100644 --- a/src/main/java/redis/clients/jedis/commands/ListBinaryCommands.java +++ b/src/main/java/redis/clients/jedis/commands/ListBinaryCommands.java @@ -47,11 +47,11 @@ public interface ListBinaryCommands { List blpop(int timeout, byte[]... keys); - List blpop(double timeout, byte[]... keys); + KeyValue blpop(double timeout, byte[]... keys); List brpop(int timeout, byte[]... keys); - List brpop(double timeout, byte[]... keys); + KeyValue brpop(double timeout, byte[]... keys); byte[] rpoplpush(byte[] srckey, byte[] dstkey); @@ -65,7 +65,7 @@ public interface ListBinaryCommands { KeyValue> lmpop(ListDirection direction, int count, byte[]... keys); - KeyValue> blmpop(long timeout, ListDirection direction, byte[]... keys); + KeyValue> blmpop(double timeout, ListDirection direction, byte[]... keys); - KeyValue> blmpop(long timeout, ListDirection direction, int count, byte[]... keys); + KeyValue> blmpop(double timeout, ListDirection direction, int count, byte[]... keys); } diff --git a/src/main/java/redis/clients/jedis/commands/ListCommands.java b/src/main/java/redis/clients/jedis/commands/ListCommands.java index 6d25481bcf..9a65009beb 100644 --- a/src/main/java/redis/clients/jedis/commands/ListCommands.java +++ b/src/main/java/redis/clients/jedis/commands/ListCommands.java @@ -5,7 +5,6 @@ import redis.clients.jedis.args.ListDirection; import redis.clients.jedis.args.ListPosition; import redis.clients.jedis.params.LPosParams; -import redis.clients.jedis.resps.KeyedListElement; import redis.clients.jedis.util.KeyValue; public interface ListCommands { @@ -303,13 +302,13 @@ public interface ListCommands { * seconds to block. A timeout of zero can be used to block indefinitely. * @param keys */ - KeyedListElement blpop(double timeout, String... keys); + KeyValue blpop(double timeout, String... keys); /** * @see ListCommands#blpop(double, String...) */ - KeyedListElement blpop(double timeout, String key); + KeyValue blpop(double timeout, String key); /** * The blocking version of {@link ListCommands#rpop(String)} RPOP} because it blocks the connection @@ -334,12 +333,12 @@ public interface ListCommands { * seconds to block. A timeout of zero can be used to block indefinitely. * @param keys */ - KeyedListElement brpop(double timeout, String... keys); + KeyValue brpop(double timeout, String... keys); /** * @see ListCommands#brpop(double, String...) */ - KeyedListElement brpop(double timeout, String key); + KeyValue brpop(double timeout, String key); /** * Atomically return and remove the last (tail) element of the srckey list, and push the element @@ -398,7 +397,7 @@ public interface ListCommands { KeyValue> lmpop(ListDirection direction, int count, String... keys); - KeyValue> blmpop(long timeout, ListDirection direction, String... keys); + KeyValue> blmpop(double timeout, ListDirection direction, String... keys); - KeyValue> blmpop(long timeout, ListDirection direction, int count, String... keys); + KeyValue> blmpop(double timeout, ListDirection direction, int count, String... keys); } diff --git a/src/main/java/redis/clients/jedis/commands/ListPipelineBinaryCommands.java b/src/main/java/redis/clients/jedis/commands/ListPipelineBinaryCommands.java index 2c1926530b..6f0b87f911 100644 --- a/src/main/java/redis/clients/jedis/commands/ListPipelineBinaryCommands.java +++ b/src/main/java/redis/clients/jedis/commands/ListPipelineBinaryCommands.java @@ -48,11 +48,11 @@ public interface ListPipelineBinaryCommands { Response> blpop(int timeout, byte[]... keys); - Response> blpop(double timeout, byte[]... keys); + Response> blpop(double timeout, byte[]... keys); Response> brpop(int timeout, byte[]... keys); - Response> brpop(double timeout, byte[]... keys); + Response> brpop(double timeout, byte[]... keys); Response rpoplpush(byte[] srckey, byte[] dstkey); @@ -66,7 +66,7 @@ public interface ListPipelineBinaryCommands { Response>> lmpop(ListDirection direction, int count, byte[]... keys); - Response>> blmpop(long timeout, ListDirection direction, byte[]... keys); + Response>> blmpop(double timeout, ListDirection direction, byte[]... keys); - Response>> blmpop(long timeout, ListDirection direction, int count, byte[]... keys); + Response>> blmpop(double timeout, ListDirection direction, int count, byte[]... keys); } diff --git a/src/main/java/redis/clients/jedis/commands/ListPipelineCommands.java b/src/main/java/redis/clients/jedis/commands/ListPipelineCommands.java index 2685728c56..5d241b214c 100644 --- a/src/main/java/redis/clients/jedis/commands/ListPipelineCommands.java +++ b/src/main/java/redis/clients/jedis/commands/ListPipelineCommands.java @@ -6,7 +6,6 @@ import redis.clients.jedis.args.ListDirection; import redis.clients.jedis.args.ListPosition; import redis.clients.jedis.params.LPosParams; -import redis.clients.jedis.resps.KeyedListElement; import redis.clients.jedis.util.KeyValue; public interface ListPipelineCommands { @@ -49,19 +48,19 @@ public interface ListPipelineCommands { Response> blpop(int timeout, String key); - Response blpop(double timeout, String key); + Response> blpop(double timeout, String key); Response> brpop(int timeout, String key); - Response brpop(double timeout, String key); + Response> brpop(double timeout, String key); Response> blpop(int timeout, String... keys); - Response blpop(double timeout, String... keys); + Response> blpop(double timeout, String... keys); Response> brpop(int timeout, String... keys); - Response brpop(double timeout, String... keys); + Response> brpop(double timeout, String... keys); Response rpoplpush(String srckey, String dstkey); @@ -75,7 +74,7 @@ public interface ListPipelineCommands { Response>> lmpop(ListDirection direction, int count, String... keys); - Response>> blmpop(long timeout, ListDirection direction, String... keys); + Response>> blmpop(double timeout, ListDirection direction, String... keys); - Response>> blmpop(long timeout, ListDirection direction, int count, String... keys); + Response>> blmpop(double timeout, ListDirection direction, int count, String... keys); } diff --git a/src/main/java/redis/clients/jedis/commands/RedisModuleCommands.java b/src/main/java/redis/clients/jedis/commands/RedisModuleCommands.java index 47d01fa0bd..5e67838720 100644 --- a/src/main/java/redis/clients/jedis/commands/RedisModuleCommands.java +++ b/src/main/java/redis/clients/jedis/commands/RedisModuleCommands.java @@ -1,8 +1,9 @@ package redis.clients.jedis.commands; import redis.clients.jedis.bloom.commands.RedisBloomCommands; +import redis.clients.jedis.gears.RedisGearsCommands; import redis.clients.jedis.graph.RedisGraphCommands; -import redis.clients.jedis.json.RedisJsonCommands; +import redis.clients.jedis.json.commands.RedisJsonCommands; import redis.clients.jedis.search.RediSearchCommands; import redis.clients.jedis.timeseries.RedisTimeSeriesCommands; @@ -11,6 +12,7 @@ public interface RedisModuleCommands extends RedisJsonCommands, RedisTimeSeriesCommands, RedisBloomCommands, - RedisGraphCommands { + RedisGraphCommands, + RedisGearsCommands { } diff --git a/src/main/java/redis/clients/jedis/commands/RedisModulePipelineCommands.java b/src/main/java/redis/clients/jedis/commands/RedisModulePipelineCommands.java index fc768bb60f..ca1d9f1e0c 100644 --- a/src/main/java/redis/clients/jedis/commands/RedisModulePipelineCommands.java +++ b/src/main/java/redis/clients/jedis/commands/RedisModulePipelineCommands.java @@ -2,7 +2,7 @@ import redis.clients.jedis.bloom.commands.RedisBloomPipelineCommands; import redis.clients.jedis.graph.RedisGraphPipelineCommands; -import redis.clients.jedis.json.RedisJsonPipelineCommands; +import redis.clients.jedis.json.commands.RedisJsonPipelineCommands; import redis.clients.jedis.search.RediSearchPipelineCommands; import redis.clients.jedis.timeseries.RedisTimeSeriesPipelineCommands; diff --git a/src/main/java/redis/clients/jedis/commands/SampleBinaryKeyedCommands.java b/src/main/java/redis/clients/jedis/commands/SampleBinaryKeyedCommands.java index b0630cd7c5..ffdbdb6943 100644 --- a/src/main/java/redis/clients/jedis/commands/SampleBinaryKeyedCommands.java +++ b/src/main/java/redis/clients/jedis/commands/SampleBinaryKeyedCommands.java @@ -2,11 +2,14 @@ import java.util.List; import redis.clients.jedis.args.FlushMode; +import redis.clients.jedis.util.KeyValue; public interface SampleBinaryKeyedCommands { long waitReplicas(byte[] sampleKey, int replicas, long timeout); + KeyValue waitAOF(byte[] sampleKey, long numLocal, long numReplicas, long timeout); + Object eval(byte[] script, byte[] sampleKey); Object evalsha(byte[] sha1, byte[] sampleKey); diff --git a/src/main/java/redis/clients/jedis/commands/SampleBinaryKeyedPipelineCommands.java b/src/main/java/redis/clients/jedis/commands/SampleBinaryKeyedPipelineCommands.java index 1ffcb123e7..c1d51de819 100644 --- a/src/main/java/redis/clients/jedis/commands/SampleBinaryKeyedPipelineCommands.java +++ b/src/main/java/redis/clients/jedis/commands/SampleBinaryKeyedPipelineCommands.java @@ -3,11 +3,14 @@ import java.util.List; import redis.clients.jedis.Response; import redis.clients.jedis.args.FlushMode; +import redis.clients.jedis.util.KeyValue; public interface SampleBinaryKeyedPipelineCommands { Response waitReplicas(byte[] sampleKey, int replicas, long timeout); + Response> waitAOF(byte[] sampleKey, long numLocal, long numReplicas, long timeout); + Response eval(byte[] script, byte[] sampleKey); Response evalsha(byte[] sha1, byte[] sampleKey); diff --git a/src/main/java/redis/clients/jedis/commands/SampleKeyedCommands.java b/src/main/java/redis/clients/jedis/commands/SampleKeyedCommands.java index 5a1831938b..3183a6c311 100644 --- a/src/main/java/redis/clients/jedis/commands/SampleKeyedCommands.java +++ b/src/main/java/redis/clients/jedis/commands/SampleKeyedCommands.java @@ -2,11 +2,14 @@ import java.util.List; import redis.clients.jedis.args.FlushMode; +import redis.clients.jedis.util.KeyValue; public interface SampleKeyedCommands { long waitReplicas(String sampleKey, int replicas, long timeout); + KeyValue waitAOF(String sampleKey, long numLocal, long numReplicas, long timeout); + Object eval(String script, String sampleKey); Object evalsha(String sha1, String sampleKey); diff --git a/src/main/java/redis/clients/jedis/commands/SampleKeyedPipelineCommands.java b/src/main/java/redis/clients/jedis/commands/SampleKeyedPipelineCommands.java index 94b89e0e96..d0c3b70d75 100644 --- a/src/main/java/redis/clients/jedis/commands/SampleKeyedPipelineCommands.java +++ b/src/main/java/redis/clients/jedis/commands/SampleKeyedPipelineCommands.java @@ -3,11 +3,14 @@ import java.util.List; import redis.clients.jedis.Response; import redis.clients.jedis.args.FlushMode; +import redis.clients.jedis.util.KeyValue; public interface SampleKeyedPipelineCommands { Response waitReplicas(String sampleKey, int replicas, long timeout); + Response> waitAOF(String sampleKey, long numLocal, long numReplicas, long timeout); + Response eval(String script, String sampleKey); Response evalsha(String sha1, String sampleKey); diff --git a/src/main/java/redis/clients/jedis/commands/ServerCommands.java b/src/main/java/redis/clients/jedis/commands/ServerCommands.java index 1fe92c7d8b..511357ac1d 100644 --- a/src/main/java/redis/clients/jedis/commands/ServerCommands.java +++ b/src/main/java/redis/clients/jedis/commands/ServerCommands.java @@ -5,6 +5,7 @@ import redis.clients.jedis.exceptions.JedisException; import redis.clients.jedis.params.LolwutParams; import redis.clients.jedis.params.ShutdownParams; +import redis.clients.jedis.util.KeyValue; public interface ServerCommands { @@ -21,18 +22,19 @@ public interface ServerCommands { byte[] echo(byte[] arg); /** - * Ask the server to close the connection. The connection is closed as soon as all pending replies - * have been written to the client. + * Delete all the keys of the currently selected DB. This command never fails. The time-complexity + * for this operation is O(N), N being the number of keys in the database. * @return OK */ - String quit(); + String flushDB(); /** * Delete all the keys of the currently selected DB. This command never fails. The time-complexity * for this operation is O(N), N being the number of keys in the database. + * @param flushMode can be SYNC or ASYNC * @return OK */ - String flushDB(); + String flushDB(FlushMode flushMode); /** * Delete all the keys of all the existing databases, not just the currently selected one. @@ -68,7 +70,7 @@ public interface ServerCommands { * The SAVE commands performs a synchronous save of the dataset producing a point in time snapshot * of all the data inside the Redis instance, in the form of an RDB file. You almost never want to * call SAVE in production environments where it will block all the other clients. Instead usually - * BGSAVE is used. However in case of issues preventing Redis to create the background saving + * BGSAVE is used. However, in case of issues preventing Redis to create the background saving * child (for instance errors in the fork(2) system call), the SAVE command can be a good last * resort to perform the dump of the latest dataset. * @return result of the save @@ -114,15 +116,9 @@ public interface ServerCommands { */ void shutdown() throws JedisException; - /** - * @see SaveMode - * @param saveMode modifier to alter the data save behavior of SHUTDOWN. {@code null} would - * trigger the default behavior. - * @throws JedisException - * @deprecated Use {@link ServerCommands#shutdown(redis.clients.jedis.params.ShutdownParams)}. - */ - @Deprecated - void shutdown(SaveMode saveMode) throws JedisException; + default void shutdown(SaveMode saveMode) throws JedisException { + shutdown(ShutdownParams.shutdownParams().saveMode(saveMode)); + } /** * @see SaveMode @@ -200,7 +196,7 @@ public interface ServerCommands { String replicaofNoOne(); /** - * Syncrhonous replication of Redis as described here: http://antirez.com/news/66. + * Synchronous replication of Redis as described here: http://antirez.com/news/66. *

* Blocks until all the previous write commands are successfully transferred and acknowledged by * at least the specified number of replicas. If the timeout, specified in milliseconds, is @@ -215,10 +211,26 @@ public interface ServerCommands { */ long waitReplicas(int replicas, long timeout); + /** + * Blocks the current client until all the previous write commands are acknowledged as having been + * fsynced to the AOF of the local Redis and/or at least the specified number of replicas. + * Redis Documentation + * @param numLocal Number of local instances that are required to acknowledge the sync (0 or 1), + * cannot be non-zero if the local Redis does not have AOF enabled + * @param numReplicas Number of replicas that are required to acknowledge the sync + * @param timeout Timeout in millis of the operation - if 0 timeout is unlimited. If the timeout is reached, + * the command returns even if the specified number of acknowledgments has not been met. + * @return KeyValue where Key is number of local Redises (0 or 1) that have fsynced to AOF all writes + * performed in the context of the current connection, and the value is the number of replicas that have acknowledged doing the same. + */ + KeyValue waitAOF(long numLocal, long numReplicas, long timeout); + String lolwut(); String lolwut(LolwutParams lolwutParams); + String reset(); + /** * The LATENCY DOCTOR command reports about different latency-related issues and advises about * possible remedies. diff --git a/src/main/java/redis/clients/jedis/commands/SetPipelineCommands.java b/src/main/java/redis/clients/jedis/commands/SetPipelineCommands.java index ce1d4a7f43..4d915e31e7 100644 --- a/src/main/java/redis/clients/jedis/commands/SetPipelineCommands.java +++ b/src/main/java/redis/clients/jedis/commands/SetPipelineCommands.java @@ -37,7 +37,7 @@ default Response> sscan(String key, String cursor) { Response> sdiff(String... keys); - Response sdiffstore(String dstKey, String... keys); + Response sdiffStore(String dstKey, String... keys); Response> sinter(String... keys); diff --git a/src/main/java/redis/clients/jedis/commands/SortedSetBinaryCommands.java b/src/main/java/redis/clients/jedis/commands/SortedSetBinaryCommands.java index b222c223ab..747e3370f0 100644 --- a/src/main/java/redis/clients/jedis/commands/SortedSetBinaryCommands.java +++ b/src/main/java/redis/clients/jedis/commands/SortedSetBinaryCommands.java @@ -32,6 +32,10 @@ public interface SortedSetBinaryCommands { Long zrevrank(byte[] key, byte[] member); + KeyValue zrankWithScore(byte[] key, byte[] member); + + KeyValue zrevrankWithScore(byte[] key, byte[] member); + List zrange(byte[] key, long start, long stop); List zrevrange(byte[] key, long start, long stop); @@ -126,19 +130,25 @@ default ScanResult zscan(byte[] key, byte[] cursor) { ScanResult zscan(byte[] key, byte[] cursor, ScanParams params); - List bzpopmax(double timeout, byte[]... keys); + KeyValue bzpopmax(double timeout, byte[]... keys); - List bzpopmin(double timeout, byte[]... keys); + KeyValue bzpopmin(double timeout, byte[]... keys); - Set zdiff(byte[]... keys); + List zdiff(byte[]... keys); - Set zdiffWithScores(byte[]... keys); + List zdiffWithScores(byte[]... keys); + /** + * @deprecated Use {@link #zdiffstore(byte..., byte[]...)}. + */ + @Deprecated long zdiffStore(byte[] dstkey, byte[]... keys); - Set zinter(ZParams params, byte[]... keys); + long zdiffstore(byte[] dstkey, byte[]... keys); + + List zinter(ZParams params, byte[]... keys); - Set zinterWithScores(ZParams params, byte[]... keys); + List zinterWithScores(ZParams params, byte[]... keys); long zinterstore(byte[] dstkey, byte[]... sets); @@ -170,9 +180,9 @@ default ScanResult zscan(byte[] key, byte[] cursor) { */ long zintercard(long limit, byte[]... keys); - Set zunion(ZParams params, byte[]... keys); + List zunion(ZParams params, byte[]... keys); - Set zunionWithScores(ZParams params, byte[]... keys); + List zunionWithScores(ZParams params, byte[]... keys); long zunionstore(byte[] dstkey, byte[]... sets); @@ -182,7 +192,7 @@ default ScanResult zscan(byte[] key, byte[] cursor) { KeyValue> zmpop(SortedSetOption option, int count, byte[]... keys); - KeyValue> bzmpop(long timeout, SortedSetOption option, byte[]... keys); + KeyValue> bzmpop(double timeout, SortedSetOption option, byte[]... keys); - KeyValue> bzmpop(long timeout, SortedSetOption option, int count, byte[]... keys); + KeyValue> bzmpop(double timeout, SortedSetOption option, int count, byte[]... keys); } diff --git a/src/main/java/redis/clients/jedis/commands/SortedSetCommands.java b/src/main/java/redis/clients/jedis/commands/SortedSetCommands.java index 43641776f6..65bf4daa67 100644 --- a/src/main/java/redis/clients/jedis/commands/SortedSetCommands.java +++ b/src/main/java/redis/clients/jedis/commands/SortedSetCommands.java @@ -6,7 +6,6 @@ import redis.clients.jedis.args.SortedSetOption; import redis.clients.jedis.params.*; -import redis.clients.jedis.resps.KeyedZSetElement; import redis.clients.jedis.resps.ScanResult; import redis.clients.jedis.resps.Tuple; import redis.clients.jedis.util.KeyValue; @@ -153,6 +152,24 @@ public interface SortedSetCommands { */ Long zrevrank(String key, String member); + /** + * Returns the rank and the score of member in the sorted set stored at key, with the scores + * ordered from low to high. + * @param key the key + * @param member the member + * @return the KeyValue contains rank and score. + */ + KeyValue zrankWithScore(String key, String member); + + /** + * Returns the rank and the score of member in the sorted set stored at key, with the scores + * ordered from high to low. + * @param key the key + * @param member the member + * @return the KeyValue contains rank and score. + */ + KeyValue zrevrankWithScore(String key, String member); + /** * Returns the specified range of elements in the sorted set stored at key. *

@@ -650,7 +667,7 @@ default ScanResult zscan(String key, String cursor) { * be used to block indefinitely. * @param keys */ - KeyedZSetElement bzpopmax(double timeout, String... keys); + KeyValue bzpopmax(double timeout, String... keys); /** * The blocking version of {@link SortedSetCommands#zpopmin(String) ZPOPMIN} @@ -658,7 +675,7 @@ default ScanResult zscan(String key, String cursor) { * be used to block indefinitely. * @param keys */ - KeyedZSetElement bzpopmin(double timeout, String... keys); + KeyValue bzpopmin(double timeout, String... keys); /** * Compute the difference between all the sets in the given keys. @@ -668,23 +685,33 @@ default ScanResult zscan(String key, String cursor) { * @param keys group of sets * @return The result of the difference */ - Set zdiff(String... keys); + List zdiff(String... keys); /** * Compute the difference between all the sets in the given keys. Return the result with scores. * @param keys group of sets * @return The result of the difference with their scores */ - Set zdiffWithScores(String... keys); + List zdiffWithScores(String... keys); /** * Compute the difference between all the sets in the given keys. Store the result in dstkey. * @param dstkey * @param keys group of sets * @return The number of elements in the resulting sorted set at dstkey. + * @deprecated Use {@link #zdiffstore(java.lang.String, java.lang.String...)}. */ + @Deprecated long zdiffStore(String dstkey, String... keys); + /** + * Compute the difference between all the sets in the given keys. Store the result in dstkey. + * @param dstkey + * @param keys group of sets + * @return The number of elements in the resulting sorted set at dstkey. + */ + long zdiffstore(String dstkey, String... keys); + /** * Compute the intersection between all the sets in the given keys. *

@@ -694,7 +721,7 @@ default ScanResult zscan(String key, String cursor) { * @param keys group of sets * @return The result of the intersection */ - Set zinter(ZParams params, String... keys); + List zinter(ZParams params, String... keys); /** * Compute the intersection between all the sets in the given keys. Return the result with scores. @@ -702,7 +729,7 @@ default ScanResult zscan(String key, String cursor) { * @param keys group of sets * @return The result of the intersection with their scores */ - Set zinterWithScores(ZParams params, String... keys); + List zinterWithScores(ZParams params, String... keys); /** * Compute the intersection between all the sets in the given keys. Store the result in dstkey. @@ -756,7 +783,7 @@ default ScanResult zscan(String key, String cursor) { * @param keys group of sets * @return The result of the union */ - Set zunion(ZParams params, String... keys); + List zunion(ZParams params, String... keys); /** * Compute the union between all the sets in the given keys. Return the result with scores. @@ -764,7 +791,7 @@ default ScanResult zscan(String key, String cursor) { * @param keys group of sets * @return The result of the union with their scores */ - Set zunionWithScores(ZParams params, String... keys); + List zunionWithScores(ZParams params, String... keys); /** * Compute the union between all the sets in the given keys. Store the result in dstkey. @@ -787,7 +814,7 @@ default ScanResult zscan(String key, String cursor) { KeyValue> zmpop(SortedSetOption option, int count, String... keys); - KeyValue> bzmpop(long timeout, SortedSetOption option, String... keys); + KeyValue> bzmpop(double timeout, SortedSetOption option, String... keys); - KeyValue> bzmpop(long timeout, SortedSetOption option, int count, String... keys); + KeyValue> bzmpop(double timeout, SortedSetOption option, int count, String... keys); } diff --git a/src/main/java/redis/clients/jedis/commands/SortedSetPipelineBinaryCommands.java b/src/main/java/redis/clients/jedis/commands/SortedSetPipelineBinaryCommands.java index 0ac3437201..128b61822b 100644 --- a/src/main/java/redis/clients/jedis/commands/SortedSetPipelineBinaryCommands.java +++ b/src/main/java/redis/clients/jedis/commands/SortedSetPipelineBinaryCommands.java @@ -33,6 +33,10 @@ public interface SortedSetPipelineBinaryCommands { Response zrevrank(byte[] key, byte[] member); + Response> zrankWithScore(byte[] key, byte[] member); + + Response> zrevrankWithScore(byte[] key, byte[] member); + Response> zrange(byte[] key, long start, long stop); Response> zrevrange(byte[] key, long start, long stop); @@ -127,19 +131,25 @@ default Response> zscan(byte[] key, byte[] cursor) { Response> zscan(byte[] key, byte[] cursor, ScanParams params); - Response> bzpopmax(double timeout, byte[]... keys); + Response> bzpopmax(double timeout, byte[]... keys); - Response> bzpopmin(double timeout, byte[]... keys); + Response> bzpopmin(double timeout, byte[]... keys); - Response> zdiff(byte[]... keys); + Response> zdiff(byte[]... keys); - Response> zdiffWithScores(byte[]... keys); + Response> zdiffWithScores(byte[]... keys); + /** + * @deprecated Use {@link #zdiffstore(byte..., byte[]...)}. + */ + @Deprecated Response zdiffStore(byte[] dstkey, byte[]... keys); - Response> zinter(ZParams params, byte[]... keys); + Response zdiffstore(byte[] dstkey, byte[]... keys); + + Response> zinter(ZParams params, byte[]... keys); - Response> zinterWithScores(ZParams params, byte[]... keys); + Response> zinterWithScores(ZParams params, byte[]... keys); Response zinterstore(byte[] dstkey, byte[]... sets); @@ -149,9 +159,9 @@ default Response> zscan(byte[] key, byte[] cursor) { Response zintercard(long limit, byte[]... keys); - Response> zunion(ZParams params, byte[]... keys); + Response> zunion(ZParams params, byte[]... keys); - Response> zunionWithScores(ZParams params, byte[]... keys); + Response> zunionWithScores(ZParams params, byte[]... keys); Response zunionstore(byte[] dstkey, byte[]... sets); @@ -161,7 +171,7 @@ default Response> zscan(byte[] key, byte[] cursor) { Response>> zmpop(SortedSetOption option, int count, byte[]... keys); - Response>> bzmpop(long timeout, SortedSetOption option, byte[]... keys); + Response>> bzmpop(double timeout, SortedSetOption option, byte[]... keys); - Response>> bzmpop(long timeout, SortedSetOption option, int count, byte[]... keys); + Response>> bzmpop(double timeout, SortedSetOption option, int count, byte[]... keys); } diff --git a/src/main/java/redis/clients/jedis/commands/SortedSetPipelineCommands.java b/src/main/java/redis/clients/jedis/commands/SortedSetPipelineCommands.java index 0e173c3ac2..b938f25d4e 100644 --- a/src/main/java/redis/clients/jedis/commands/SortedSetPipelineCommands.java +++ b/src/main/java/redis/clients/jedis/commands/SortedSetPipelineCommands.java @@ -7,7 +7,6 @@ import redis.clients.jedis.Response; import redis.clients.jedis.args.SortedSetOption; import redis.clients.jedis.params.*; -import redis.clients.jedis.resps.KeyedZSetElement; import redis.clients.jedis.resps.ScanResult; import redis.clients.jedis.resps.Tuple; import redis.clients.jedis.util.KeyValue; @@ -34,6 +33,10 @@ public interface SortedSetPipelineCommands { Response zrevrank(String key, String member); + Response> zrankWithScore(String key, String member); + + Response> zrevrankWithScore(String key, String member); + Response> zrange(String key, long start, long stop); Response> zrevrange(String key, long start, long stop); @@ -128,31 +131,37 @@ default Response> zscan(String key, String cursor) { Response> zscan(String key, String cursor, ScanParams params); - Response bzpopmax(double timeout, String... keys); + Response> bzpopmax(double timeout, String... keys); - Response bzpopmin(double timeout, String... keys); + Response> bzpopmin(double timeout, String... keys); - Response> zdiff(String... keys); + Response> zdiff(String... keys); - Response> zdiffWithScores(String... keys); + Response> zdiffWithScores(String... keys); + /** + * @deprecated Use {@link #zdiffstore(java.lang.String, java.lang.String...)}. + */ + @Deprecated Response zdiffStore(String dstKey, String... keys); + Response zdiffstore(String dstKey, String... keys); + Response zinterstore(String dstKey, String... sets); Response zinterstore(String dstKey, ZParams params, String... sets); - Response> zinter(ZParams params, String... keys); + Response> zinter(ZParams params, String... keys); - Response> zinterWithScores(ZParams params, String... keys); + Response> zinterWithScores(ZParams params, String... keys); Response zintercard(String... keys); Response zintercard(long limit, String... keys); - Response> zunion(ZParams params, String... keys); + Response> zunion(ZParams params, String... keys); - Response> zunionWithScores(ZParams params, String... keys); + Response> zunionWithScores(ZParams params, String... keys); Response zunionstore(String dstKey, String... sets); @@ -162,7 +171,7 @@ default Response> zscan(String key, String cursor) { Response>> zmpop(SortedSetOption option, int count, String... keys); - Response>> bzmpop(long timeout, SortedSetOption option, String... keys); + Response>> bzmpop(double timeout, SortedSetOption option, String... keys); - Response>> bzmpop(long timeout, SortedSetOption option, int count, String... keys); + Response>> bzmpop(double timeout, SortedSetOption option, int count, String... keys); } diff --git a/src/main/java/redis/clients/jedis/commands/StreamBinaryCommands.java b/src/main/java/redis/clients/jedis/commands/StreamBinaryCommands.java index 4d7ca6ba13..01dec14d2d 100644 --- a/src/main/java/redis/clients/jedis/commands/StreamBinaryCommands.java +++ b/src/main/java/redis/clients/jedis/commands/StreamBinaryCommands.java @@ -15,13 +15,13 @@ default byte[] xadd(byte[] key, Map hash, XAddParams params) { long xlen(byte[] key); - List xrange(byte[] key, byte[] start, byte[] end); + List xrange(byte[] key, byte[] start, byte[] end); - List xrange(byte[] key, byte[] start, byte[] end, int count); + List xrange(byte[] key, byte[] start, byte[] end, int count); - List xrevrange(byte[] key, byte[] end, byte[] start); + List xrevrange(byte[] key, byte[] end, byte[] start); - List xrevrange(byte[] key, byte[] end, byte[] start, int count); + List xrevrange(byte[] key, byte[] end, byte[] start, int count); long xack(byte[] key, byte[] group, byte[]... ids); @@ -43,12 +43,6 @@ default byte[] xadd(byte[] key, Map hash, XAddParams params) { Object xpending(byte[] key, byte[] groupName); - /** - * @deprecated Use {@link StreamBinaryCommands#xpending(byte[], byte[], redis.clients.jedis.params.XPendingParams)}. - */ - @Deprecated - List xpending(byte[] key, byte[] groupName, byte[] start, byte[] end, int count, byte[] consumerName); - List xpending(byte[] key, byte[] groupName, XPendingParams params); List xclaim(byte[] key, byte[] group, byte[] consumerName, long minIdleTime, XClaimParams params, byte[]... ids); @@ -76,19 +70,13 @@ List xautoclaimJustId(byte[] key, byte[] groupName, byte[] consumerName, */ Object xinfoStreamFull(byte[] key, int count); - /** - * @deprecated Use {@link StreamBinaryCommands#xinfoGroups(byte[])}. - */ - @Deprecated - List xinfoGroup(byte[] key); - List xinfoGroups(byte[] key); List xinfoConsumers(byte[] key, byte[] group); - List xread(XReadParams xReadParams, Map.Entry... streams); + List xread(XReadParams xReadParams, Map.Entry... streams); - List xreadGroup(byte[] groupName, byte[] consumer, XReadGroupParams xReadGroupParams, + List xreadGroup(byte[] groupName, byte[] consumer, XReadGroupParams xReadGroupParams, Map.Entry... streams); } diff --git a/src/main/java/redis/clients/jedis/commands/StreamCommands.java b/src/main/java/redis/clients/jedis/commands/StreamCommands.java index 4d7caf0bc5..9c34cbc6a6 100644 --- a/src/main/java/redis/clients/jedis/commands/StreamCommands.java +++ b/src/main/java/redis/clients/jedis/commands/StreamCommands.java @@ -123,25 +123,6 @@ default StreamEntryID xadd(String key, Map hash, XAddParams para */ long xgroupDelConsumer(String key, String groupName, String consumerName); - /** - * XPENDING key group - */ - StreamPendingSummary xpending(String key, String groupName); - - /** - * XPENDING key group [start end count] [consumer] - * - * @deprecated Use {@link StreamCommands#xpending(java.lang.String, java.lang.String, redis.clients.jedis.params.XPendingParams)}. - */ - @Deprecated - List xpending(String key, String groupName, StreamEntryID start, - StreamEntryID end, int count, String consumerName); - - /** - * XPENDING key group [[IDLE min-idle-time] start end count [consumer]] - */ - List xpending(String key, String groupName, XPendingParams params); - /** * XDEL key ID [ID ...] */ @@ -157,6 +138,16 @@ List xpending(String key, String groupName, StreamEntryID st */ long xtrim(String key, XTrimParams params); + /** + * XPENDING key group + */ + StreamPendingSummary xpending(String key, String groupName); + + /** + * XPENDING key group [[IDLE min-idle-time] start end count [consumer]] + */ + List xpending(String key, String groupName, XPendingParams params); + /** * {@code XCLAIM key group consumer min-idle-time ... * [IDLE ] [TIME ] [RETRYCOUNT ] @@ -223,12 +214,6 @@ Map.Entry> xautoclaimJustId(String key, Strin */ StreamFullInfo xinfoStreamFull(String key, int count); - /** - * @deprecated Use {@link StreamCommands#xinfoGroups(java.lang.String)}. - */ - @Deprecated - List xinfoGroup(String key); - /** * Introspection command used in order to retrieve different information about groups in the stream * @param key Stream name @@ -241,10 +226,21 @@ Map.Entry> xautoclaimJustId(String key, Strin * @param key Stream name * @param group Group name * @return List of {@link StreamConsumersInfo} containing information about consumers that belong - * to the the group + * to the group + * @deprecated Use {@link #xinfoConsumers2(java.lang.String, java.lang.String)}. */ + @Deprecated // keep it till at least Jedis 6/7 List xinfoConsumers(String key, String group); + /** + * Introspection command used in order to retrieve different information about consumers in the group + * @param key Stream name + * @param group Group name + * @return List of {@link StreamConsumerInfo} containing information about consumers that belong + * to the group + */ + List xinfoConsumers2(String key, String group); + /** * XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] ID [ID ...] */ diff --git a/src/main/java/redis/clients/jedis/commands/StreamPipelineBinaryCommands.java b/src/main/java/redis/clients/jedis/commands/StreamPipelineBinaryCommands.java index d1cade2533..8198443009 100644 --- a/src/main/java/redis/clients/jedis/commands/StreamPipelineBinaryCommands.java +++ b/src/main/java/redis/clients/jedis/commands/StreamPipelineBinaryCommands.java @@ -7,8 +7,6 @@ import redis.clients.jedis.params.*; public interface StreamPipelineBinaryCommands { -// -// byte[] xadd(byte[] key, byte[] id, Map hash, long maxLen, boolean approximateLength); default Response xadd(byte[] key, Map hash, XAddParams params) { return xadd(key, params, hash); @@ -18,13 +16,13 @@ default Response xadd(byte[] key, Map hash, XAddParams p Response xlen(byte[] key); - Response> xrange(byte[] key, byte[] start, byte[] end); + Response> xrange(byte[] key, byte[] start, byte[] end); - Response> xrange(byte[] key, byte[] start, byte[] end, int count); + Response> xrange(byte[] key, byte[] start, byte[] end, int count); - Response> xrevrange(byte[] key, byte[] end, byte[] start); + Response> xrevrange(byte[] key, byte[] end, byte[] start); - Response> xrevrange(byte[] key, byte[] end, byte[] start, int count); + Response> xrevrange(byte[] key, byte[] end, byte[] start, int count); Response xack(byte[] key, byte[] group, byte[]... ids); @@ -46,12 +44,6 @@ default Response xadd(byte[] key, Map hash, XAddParams p Response xpending(byte[] key, byte[] groupName); - /** - * @deprecated Use {@link StreamPipelineBinaryCommands#xpending(byte[], byte[], redis.clients.jedis.params.XPendingParams)}. - */ - @Deprecated - Response> xpending(byte[] key, byte[] groupName, byte[] start, byte[] end, int count, byte[] consumerName); - Response> xpending(byte[] key, byte[] groupName, XPendingParams params); Response> xclaim(byte[] key, byte[] group, byte[] consumerName, long minIdleTime, XClaimParams params, byte[]... ids); @@ -79,19 +71,13 @@ Response> xautoclaimJustId(byte[] key, byte[] groupName, byte[] con */ Response xinfoStreamFull(byte[] key, int count); - /** - * @deprecated Use {@link StreamPipelineBinaryCommands#xinfoGroups(byte[])}. - */ - @Deprecated - Response> xinfoGroup(byte[] key); - Response> xinfoGroups(byte[] key); Response> xinfoConsumers(byte[] key, byte[] group); - Response> xread(XReadParams xReadParams, Map.Entry... streams); + Response> xread(XReadParams xReadParams, Map.Entry... streams); - Response> xreadGroup(byte[] groupName, byte[] consumer, XReadGroupParams xReadGroupParams, - Map.Entry... streams); + Response> xreadGroup(byte[] groupName, byte[] consumer, + XReadGroupParams xReadGroupParams, Map.Entry... streams); } diff --git a/src/main/java/redis/clients/jedis/commands/StreamPipelineCommands.java b/src/main/java/redis/clients/jedis/commands/StreamPipelineCommands.java index dc745c6f56..e435c02341 100644 --- a/src/main/java/redis/clients/jedis/commands/StreamPipelineCommands.java +++ b/src/main/java/redis/clients/jedis/commands/StreamPipelineCommands.java @@ -121,15 +121,6 @@ default Response xadd(String key, Map hash, XAddP */ Response xpending(String key, String groupName); - /** - * XPENDING key group [start end count] [consumer] - * - * @deprecated Use {@link StreamPipelineCommands#xpending(java.lang.String, java.lang.String, redis.clients.jedis.params.XPendingParams)}. - */ - @Deprecated - Response> xpending(String key, String groupName, StreamEntryID start, - StreamEntryID end, int count, String consumerName); - /** * XPENDING key group [[IDLE min-idle-time] start end count [consumer]] */ @@ -216,12 +207,6 @@ Response>> xautoclaimJustId(String */ Response xinfoStreamFull(String key, int count); - /** - * @deprecated Use {@link StreamPipelineCommands#xinfoGroups(java.lang.String)}. - */ - @Deprecated - Response> xinfoGroup(String key); - /** * Introspection command used in order to retrieve different information about groups in the stream * @param key Stream name @@ -234,10 +219,21 @@ Response>> xautoclaimJustId(String * @param key Stream name * @param group Group name * @return List of {@link StreamConsumersInfo} containing information about consumers that belong - * to the the group + * to the group + * @deprecated Use {@link #xinfoConsumers2(java.lang.String, java.lang.String)}. */ + @Deprecated // keep it till at least Jedis 6/7 Response> xinfoConsumers(String key, String group); + /** + * Introspection command used in order to retrieve different information about consumers in the group + * @param key Stream name + * @param group Group name + * @return List of {@link StreamConsumerInfo} containing information about consumers that belong + * to the group + */ + Response> xinfoConsumers2(String key, String group); + /** * XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] ID [ID ...] */ diff --git a/src/main/java/redis/clients/jedis/commands/StringBinaryCommands.java b/src/main/java/redis/clients/jedis/commands/StringBinaryCommands.java index c64f3701fa..ca51b1a1af 100644 --- a/src/main/java/redis/clients/jedis/commands/StringBinaryCommands.java +++ b/src/main/java/redis/clients/jedis/commands/StringBinaryCommands.java @@ -4,7 +4,6 @@ import redis.clients.jedis.params.GetExParams; import redis.clients.jedis.params.SetParams; -import redis.clients.jedis.params.StrAlgoLCSParams; import redis.clients.jedis.params.LCSParams; import redis.clients.jedis.resps.LCSMatchResult; @@ -16,9 +15,8 @@ public interface StringBinaryCommands extends BitBinaryCommands { byte[] get(byte[] key); - /** - * WARNING: {@link SetParams#get()} MUST NOT be used with this method. - */ + byte[] setGet(byte[] key, byte[] value); + byte[] setGet(byte[] key, byte[] value, SetParams params); byte[] getDel(byte[] key); @@ -59,13 +57,6 @@ public interface StringBinaryCommands extends BitBinaryCommands { long strlen(byte[] key); - /** - * @deprecated STRALGO LCS command will be removed from Redis 7. - * {@link StringBinaryCommands#lcs(byte[], byte[], LCSParams) LCS} can be used instead of this method. - */ - @Deprecated - LCSMatchResult strAlgoLCSKeys(byte[] keyA, byte[] keyB, StrAlgoLCSParams params); - /** * Calculate the longest common subsequence of keyA and keyB. * @param keyA diff --git a/src/main/java/redis/clients/jedis/commands/StringCommands.java b/src/main/java/redis/clients/jedis/commands/StringCommands.java index 62627db710..0621bc9334 100644 --- a/src/main/java/redis/clients/jedis/commands/StringCommands.java +++ b/src/main/java/redis/clients/jedis/commands/StringCommands.java @@ -4,7 +4,6 @@ import redis.clients.jedis.params.GetExParams; import redis.clients.jedis.params.SetParams; -import redis.clients.jedis.params.StrAlgoLCSParams; import redis.clients.jedis.params.LCSParams; import redis.clients.jedis.resps.LCSMatchResult; @@ -47,9 +46,8 @@ public interface StringCommands extends BitCommands { */ String get(String key); - /** - * WARNING: {@link SetParams#get()} MUST NOT be used with this method. - */ + String setGet(String key, String value); + String setGet(String key, String value, SetParams params); /** @@ -174,7 +172,7 @@ public interface StringCommands extends BitCommands { /** * MSet Command - * Set the the respective keys to the respective values. MSET will replace old values with new + * Set the respective keys to the respective values. MSET will replace old values with new * values, while {@link StringCommands#msetnx(String...) MSETNX} will not perform any operation at all even * if just a single key already exists. *

@@ -215,10 +213,10 @@ public interface StringCommands extends BitCommands { * Increment the number stored at key by one. If the key does not exist or contains a value of a * wrong type, set the key to the value of "0" before to perform the increment operation. *

- * INCR commands are limited to 64 bit signed integers. + * INCR commands are limited to 64-bit signed integers. *

* Note: this is actually a string operation, that is, in Redis there are not "integer" types. - * Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented, + * Simply the string stored at the key is parsed as a base 10 64-bit signed integer, incremented, * and then converted back as a string. *

* Time complexity: O(1) @@ -232,10 +230,10 @@ public interface StringCommands extends BitCommands { * INCRBY work just like {@link StringCommands#incr(String) INCR} but instead to increment by 1 the * increment is integer. *

- * INCR commands are limited to 64 bit signed integers. + * INCR commands are limited to 64-bit signed integers. *

* Note: this is actually a string operation, that is, in Redis there are not "integer" types. - * Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented, + * Simply the string stored at the key is parsed as a base 10 64-bit signed integer, incremented, * and then converted back as a string. *

* Time complexity: O(1) @@ -269,10 +267,10 @@ public interface StringCommands extends BitCommands { * Decrement the number stored at key by one. If the key does not exist or contains a value of a * wrong type, set the key to the value of "0" before to perform the decrement operation. *

- * DECR commands are limited to 64 bit signed integers. + * DECR commands are limited to 64-bit signed integers. *

* Note: this is actually a string operation, that is, in Redis there are not "integer" types. - * Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented, + * Simply the string stored at the key is parsed as a base 10 64-bit signed integer, incremented, * and then converted back as a string. *

* Time complexity: O(1) @@ -286,10 +284,10 @@ public interface StringCommands extends BitCommands { * DECRBY work just like {@link StringCommands#decr(String) DECR} but instead to decrement by 1 the * decrement is integer. *

- * DECRBY commands are limited to 64 bit signed integers. + * DECRBY commands are limited to 64-bit signed integers. *

* Note: this is actually a string operation, that is, in Redis there are not "integer" types. - * Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented, + * Simply the string stored at the key is parsed as a base 10 64-bit signed integer, incremented, * and then converted back as a string. *

* Time complexity: O(1) @@ -341,18 +339,6 @@ public interface StringCommands extends BitCommands { */ long strlen(String key); - /** - * Calculate the longest common subsequence of keyA and keyB. - * @deprecated STRALGO LCS command will be removed from Redis 7. - * {@link StringCommands#lcs(String, String, LCSParams) LCS} can be used instead of this method. - * @param keyA - * @param keyB - * @param params - * @return According to StrAlgoLCSParams to decide to return content to fill LCSMatchResult. - */ - @Deprecated - LCSMatchResult strAlgoLCSKeys(String keyA, String keyB, StrAlgoLCSParams params); - /** * Calculate the longest common subsequence of keyA and keyB. * @param keyA diff --git a/src/main/java/redis/clients/jedis/commands/StringPipelineBinaryCommands.java b/src/main/java/redis/clients/jedis/commands/StringPipelineBinaryCommands.java index 35c2965c64..b4a114d565 100644 --- a/src/main/java/redis/clients/jedis/commands/StringPipelineBinaryCommands.java +++ b/src/main/java/redis/clients/jedis/commands/StringPipelineBinaryCommands.java @@ -5,7 +5,6 @@ import redis.clients.jedis.Response; import redis.clients.jedis.params.GetExParams; import redis.clients.jedis.params.SetParams; -import redis.clients.jedis.params.StrAlgoLCSParams; import redis.clients.jedis.params.LCSParams; import redis.clients.jedis.resps.LCSMatchResult; @@ -17,9 +16,6 @@ public interface StringPipelineBinaryCommands extends BitPipelineBinaryCommands Response get(byte[] key); - /** - * WARNING: {@link SetParams#get()} MUST NOT be used with this method. - */ Response setGet(byte[] key, byte[] value, SetParams params); Response getDel(byte[] key); @@ -60,12 +56,5 @@ public interface StringPipelineBinaryCommands extends BitPipelineBinaryCommands Response strlen(byte[] key); - /** - * @deprecated STRALGO LCS command will be removed from Redis 7. - * {@link StringPipelineBinaryCommands#lcs(byte[], byte[], LCSParams) LCS} can be used instead of this method. - */ - @Deprecated - Response strAlgoLCSKeys(byte[] keyA, byte[] keyB, StrAlgoLCSParams params); - Response lcs(byte[] keyA, byte[] keyB, LCSParams params); } diff --git a/src/main/java/redis/clients/jedis/commands/StringPipelineCommands.java b/src/main/java/redis/clients/jedis/commands/StringPipelineCommands.java index f02299711e..6af9968ebe 100644 --- a/src/main/java/redis/clients/jedis/commands/StringPipelineCommands.java +++ b/src/main/java/redis/clients/jedis/commands/StringPipelineCommands.java @@ -3,7 +3,6 @@ import redis.clients.jedis.Response; import redis.clients.jedis.params.GetExParams; import redis.clients.jedis.params.SetParams; -import redis.clients.jedis.params.StrAlgoLCSParams; import redis.clients.jedis.params.LCSParams; import redis.clients.jedis.resps.LCSMatchResult; @@ -17,9 +16,6 @@ public interface StringPipelineCommands extends BitPipelineCommands { Response get(String key); - /** - * WARNING: {@link SetParams#get()} MUST NOT be used with this method. - */ Response setGet(String key, String value, SetParams params); Response getDel(String key); @@ -60,12 +56,5 @@ public interface StringPipelineCommands extends BitPipelineCommands { Response strlen(String key); - /** - * @deprecated STRALGO LCS command will be removed from Redis 7. - * {@link StringPipelineCommands#lcs(String, String, LCSParams) LCS} can be used instead of this method. - */ - @Deprecated - Response strAlgoLCSKeys(String keyA, String keyB, StrAlgoLCSParams params); - Response lcs(String keyA, String keyB, LCSParams params); } diff --git a/src/main/java/redis/clients/jedis/exceptions/AbortedTransactionException.java b/src/main/java/redis/clients/jedis/exceptions/AbortedTransactionException.java deleted file mode 100644 index 25f857a6c0..0000000000 --- a/src/main/java/redis/clients/jedis/exceptions/AbortedTransactionException.java +++ /dev/null @@ -1,16 +0,0 @@ -package redis.clients.jedis.exceptions; - -public class AbortedTransactionException extends JedisDataException { - - public AbortedTransactionException(final String message) { - super(message); - } - - public AbortedTransactionException(final Throwable cause) { - super(cause); - } - - public AbortedTransactionException(final String message, final Throwable cause) { - super(message, cause); - } -} diff --git a/src/main/java/redis/clients/jedis/exceptions/JedisBroadcastException.java b/src/main/java/redis/clients/jedis/exceptions/JedisBroadcastException.java new file mode 100644 index 0000000000..172449c34d --- /dev/null +++ b/src/main/java/redis/clients/jedis/exceptions/JedisBroadcastException.java @@ -0,0 +1,30 @@ +package redis.clients.jedis.exceptions; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import redis.clients.jedis.HostAndPort; + +/** + * Note: This exception extends {@link JedisDataException} just so existing applications catching + * JedisDataException do not get broken. + */ +// TODO: extends JedisException +public class JedisBroadcastException extends JedisDataException { + + private static final String BROADCAST_ERROR_MESSAGE = "A failure occurred while broadcasting the command."; + + private final Map replies = new HashMap<>(); + + public JedisBroadcastException() { + super(BROADCAST_ERROR_MESSAGE); + } + + public void addReply(HostAndPort node, Object reply) { + replies.put(node, reply); + } + + public Map getReplies() { + return Collections.unmodifiableMap(replies); + } +} diff --git a/src/main/java/redis/clients/jedis/exceptions/JedisValidationException.java b/src/main/java/redis/clients/jedis/exceptions/JedisValidationException.java new file mode 100644 index 0000000000..07c3455e90 --- /dev/null +++ b/src/main/java/redis/clients/jedis/exceptions/JedisValidationException.java @@ -0,0 +1,21 @@ +package redis.clients.jedis.exceptions; + +/** + * A validation error. + */ +public class JedisValidationException extends JedisException { + + private static final long serialVersionUID = 1134169242443303479L; + + public JedisValidationException(String message) { + super(message); + } + + public JedisValidationException(Throwable cause) { + super(cause); + } + + public JedisValidationException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/redis/clients/jedis/executors/ClusterCommandExecutor.java b/src/main/java/redis/clients/jedis/executors/ClusterCommandExecutor.java index eade78c2f8..4cc25c42a9 100644 --- a/src/main/java/redis/clients/jedis/executors/ClusterCommandExecutor.java +++ b/src/main/java/redis/clients/jedis/executors/ClusterCommandExecutor.java @@ -2,6 +2,7 @@ import java.time.Duration; import java.time.Instant; +import java.util.Map; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import org.slf4j.Logger; @@ -9,6 +10,8 @@ import redis.clients.jedis.CommandObject; import redis.clients.jedis.Connection; +import redis.clients.jedis.ConnectionPool; +import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Protocol; import redis.clients.jedis.exceptions.*; import redis.clients.jedis.providers.ClusterConnectionProvider; @@ -34,6 +37,39 @@ public void close() { this.provider.close(); } + @Override + public final T broadcastCommand(CommandObject commandObject) { + Map connectionMap = provider.getConnectionMap(); + + boolean isErrored = false; + T reply = null; + JedisBroadcastException bcastError = new JedisBroadcastException(); + for (Map.Entry entry : connectionMap.entrySet()) { + HostAndPort node = HostAndPort.from(entry.getKey()); + ConnectionPool pool = entry.getValue(); + try (Connection connection = pool.getResource()) { + T aReply = execute(connection, commandObject); + bcastError.addReply(node, aReply); + if (isErrored) { // already errored + } else if (reply == null) { + reply = aReply; // ok + } else if (reply.equals(aReply)) { + // ok + } else { + isErrored = true; + reply = null; + } + } catch (Exception anError) { + bcastError.addReply(node, anError); + isErrored = true; + } + } + if (isErrored) { + throw bcastError; + } + return reply; + } + @Override public final T executeCommand(CommandObject commandObject) { Instant deadline = Instant.now().plus(maxTotalRetriesDuration); diff --git a/src/main/java/redis/clients/jedis/executors/CommandExecutor.java b/src/main/java/redis/clients/jedis/executors/CommandExecutor.java index 374c63a7dc..85ec034b02 100644 --- a/src/main/java/redis/clients/jedis/executors/CommandExecutor.java +++ b/src/main/java/redis/clients/jedis/executors/CommandExecutor.java @@ -5,4 +5,8 @@ public interface CommandExecutor extends AutoCloseable { T executeCommand(CommandObject commandObject); + + default T broadcastCommand(CommandObject commandObject) { + return executeCommand(commandObject); + } } diff --git a/src/main/java/redis/clients/jedis/gears/RedisGearsCommands.java b/src/main/java/redis/clients/jedis/gears/RedisGearsCommands.java new file mode 100644 index 0000000000..f5adb42c9e --- /dev/null +++ b/src/main/java/redis/clients/jedis/gears/RedisGearsCommands.java @@ -0,0 +1,26 @@ +package redis.clients.jedis.gears; + +import redis.clients.jedis.gears.resps.GearsLibraryInfo; + +import java.util.List; + +public interface RedisGearsCommands { + + default String tFunctionLoad(String libraryCode) { + return tFunctionLoad(libraryCode, TFunctionLoadParams.loadParams()); + } + + String tFunctionLoad(String libraryCode, TFunctionLoadParams params); + + default List tFunctionList() { + return tFunctionList(TFunctionListParams.listParams()); + } + + List tFunctionList(TFunctionListParams params); + + String tFunctionDelete(String libraryName); + + Object tFunctionCall(String library, String function, List keys, List args); + + Object tFunctionCallAsync(String library, String function, List keys, List args); +} diff --git a/src/main/java/redis/clients/jedis/gears/RedisGearsProtocol.java b/src/main/java/redis/clients/jedis/gears/RedisGearsProtocol.java new file mode 100644 index 0000000000..fc43f29e66 --- /dev/null +++ b/src/main/java/redis/clients/jedis/gears/RedisGearsProtocol.java @@ -0,0 +1,49 @@ +package redis.clients.jedis.gears; + +import redis.clients.jedis.args.Rawable; +import redis.clients.jedis.commands.ProtocolCommand; +import redis.clients.jedis.util.SafeEncoder; + +public class RedisGearsProtocol { + + public enum GearsCommand implements ProtocolCommand { + + TFUNCTION, + TFCALL, + TFCALLASYNC; + + private final byte[] raw; + + private GearsCommand() { + this.raw = SafeEncoder.encode(name()); + } + + @Override + public byte[] getRaw() { + return raw; + } + } + + public enum GearsKeyword implements Rawable { + + CONFIG, + REPLACE, + LOAD, + DELETE, + LIST, + WITHCODE, + LIBRARY, + VERBOSE; + + private final byte[] raw; + + private GearsKeyword() { + this.raw = SafeEncoder.encode(name()); + } + + @Override + public byte[] getRaw() { + return raw; + } + } +} diff --git a/src/main/java/redis/clients/jedis/gears/TFunctionListParams.java b/src/main/java/redis/clients/jedis/gears/TFunctionListParams.java new file mode 100644 index 0000000000..d3f867e92b --- /dev/null +++ b/src/main/java/redis/clients/jedis/gears/TFunctionListParams.java @@ -0,0 +1,49 @@ +package redis.clients.jedis.gears; + +import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.gears.RedisGearsProtocol.GearsKeyword; +import redis.clients.jedis.params.IParams; + +import java.util.Collections; + +public class TFunctionListParams implements IParams { + private boolean withCode = false; + private int verbose; + private String libraryName; + + public static TFunctionListParams listParams() { + return new TFunctionListParams(); + } + + @Override + public void addParams(CommandArguments args) { + if (withCode) { + args.add(GearsKeyword.WITHCODE); + } + + if (verbose > 0 && verbose < 4) { + args.add(String.join("", Collections.nCopies(verbose, "v"))); + } else if (verbose != 0) { // verbose == 0 is the default, so we don't need to throw an error + throw new IllegalArgumentException("verbose must be between 1 and 3"); + } + + if (libraryName != null) { + args.add(GearsKeyword.LIBRARY).add(libraryName); + } + } + + public TFunctionListParams withCode() { + this.withCode = true; + return this; + } + + public TFunctionListParams verbose(int verbose) { + this.verbose = verbose; + return this; + } + + public TFunctionListParams library(String libraryName) { + this.libraryName = libraryName; + return this; + } +} diff --git a/src/main/java/redis/clients/jedis/gears/TFunctionLoadParams.java b/src/main/java/redis/clients/jedis/gears/TFunctionLoadParams.java new file mode 100644 index 0000000000..d155727ec5 --- /dev/null +++ b/src/main/java/redis/clients/jedis/gears/TFunctionLoadParams.java @@ -0,0 +1,35 @@ +package redis.clients.jedis.gears; + +import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.gears.RedisGearsProtocol.GearsKeyword; +import redis.clients.jedis.params.IParams; + +public class TFunctionLoadParams implements IParams { + private boolean replace = false; + private String config; + + public static TFunctionLoadParams loadParams() { + return new TFunctionLoadParams(); + } + + @Override + public void addParams(CommandArguments args) { + if (replace) { + args.add(GearsKeyword.REPLACE); + } + + if (config != null && !config.isEmpty()) { + args.add(GearsKeyword.CONFIG).add(config); + } + } + + public TFunctionLoadParams replace() { + this.replace = true; + return this; + } + + public TFunctionLoadParams config(String config) { + this.config = config; + return this; + } +} diff --git a/src/main/java/redis/clients/jedis/gears/resps/FunctionInfo.java b/src/main/java/redis/clients/jedis/gears/resps/FunctionInfo.java new file mode 100644 index 0000000000..ccb8785812 --- /dev/null +++ b/src/main/java/redis/clients/jedis/gears/resps/FunctionInfo.java @@ -0,0 +1,97 @@ +package redis.clients.jedis.gears.resps; + +import redis.clients.jedis.Builder; +import redis.clients.jedis.util.KeyValue; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import static redis.clients.jedis.BuilderFactory.*; + +public class FunctionInfo { + private final String name; + private final String description; + private final boolean isAsync; + + private final List flags; + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public boolean isAsync() { + return isAsync; + } + + public List getFlags() { + return flags; + } + + public FunctionInfo(String name, String description, boolean isAsync, List flags) { + this.name = name; + this.description = description; + this.isAsync = isAsync; + this.flags = flags; + } + + public static final Builder> FUNCTION_INFO_LIST = new Builder>() { + @Override + public List build(Object data) { + List dataAsList = (List) data; + if (!dataAsList.isEmpty()) { + boolean isListOfList = dataAsList.get(0).getClass().isAssignableFrom(ArrayList.class); + + if (isListOfList) { + if (((List>)data).get(0).get(0) instanceof KeyValue) { + List> dataAsKeyValues = (List>)data; + return dataAsKeyValues.stream().map(keyValues -> { + String name = null; + String description = null; + List flags = Collections.emptyList(); + boolean isAsync = false; + for (KeyValue kv : keyValues) { + switch (STRING.build(kv.getKey())) { + case "name": + name = STRING.build(kv.getValue()); + break; + case "description": + description = STRING.build(kv.getValue()); + break; + case "raw-arguments": + flags = STRING_LIST.build(kv.getValue()); + break; + case "is_async": + isAsync = BOOLEAN.build(kv.getValue()); + break; + } + } + return new FunctionInfo(name, description, isAsync, flags); + }).collect(Collectors.toList()); + } else { + return dataAsList.stream().map((pairObject) -> (List) pairObject) + .map((pairList) -> new FunctionInfo( // + STRING.build(pairList.get(7)), // name + STRING.build(pairList.get(1)), // description + BOOLEAN.build(pairList.get(5)), // is_async + STRING_LIST.build(pairList.get(3)) // flags + )).collect(Collectors.toList()); + } + } else { + return dataAsList.stream() // + .map(STRING::build) // + .map((name) -> new FunctionInfo(name, null, false, null)) // + .collect(Collectors.toList()); + } + } else { + return Collections.emptyList(); + } + } + }; +} + diff --git a/src/main/java/redis/clients/jedis/gears/resps/FunctionStreamInfo.java b/src/main/java/redis/clients/jedis/gears/resps/FunctionStreamInfo.java new file mode 100644 index 0000000000..f4b607d6a3 --- /dev/null +++ b/src/main/java/redis/clients/jedis/gears/resps/FunctionStreamInfo.java @@ -0,0 +1,88 @@ +package redis.clients.jedis.gears.resps; + +import redis.clients.jedis.Builder; +import redis.clients.jedis.BuilderFactory; + +import java.util.List; +import java.util.stream.Collectors; + +public class FunctionStreamInfo { + private final String name; + private final String idToReadFrom; + private final String lastError; + private final long lastLag; + private final long lastProcessedTime; + private final long totalLag; + private final long totalProcessedTime; + private final long totalRecordProcessed; + private final List pendingIds; + + public String getName() { + return name; + } + + public String getIdToReadFrom() { + return idToReadFrom; + } + + public String getLastError() { + return lastError; + } + + public long getLastLag() { + return lastLag; + } + + public long getLastProcessedTime() { + return lastProcessedTime; + } + + public long getTotalLag() { + return totalLag; + } + + public long getTotalProcessedTime() { + return totalProcessedTime; + } + + public long getTotalRecordProcessed() { + return totalRecordProcessed; + } + + public List getPendingIds() { + return pendingIds; + } + + public FunctionStreamInfo(String name, String idToReadFrom, String lastError, + long lastProcessedTime, long lastLag, long totalLag, long totalProcessedTime, long totalRecordProcessed, + List pendingIds) { + this.name = name; + this.idToReadFrom = idToReadFrom; + this.lastError = lastError; + this.lastProcessedTime = lastProcessedTime; + this.lastLag = lastLag; + this.totalLag = totalLag; + this.totalProcessedTime = totalProcessedTime; + this.totalRecordProcessed = totalRecordProcessed; + this.pendingIds = pendingIds; + } + + public static final Builder> STREAM_INFO_LIST = new Builder>() { + @Override + public List build(Object data) { + return ((List) data).stream().map((pairObject) -> (List) pairObject) + .map((pairList) -> new FunctionStreamInfo( + BuilderFactory.STRING.build(pairList.get(9)), // name + BuilderFactory.STRING.build(pairList.get(1)), // id_to_read_from + BuilderFactory.STRING.build(pairList.get(3)), // last_error + BuilderFactory.LONG.build(pairList.get(7)), // last_processed_time + BuilderFactory.LONG.build(pairList.get(5)), // last_lag + BuilderFactory.LONG.build(pairList.get(13)), // total_lag + BuilderFactory.LONG.build(pairList.get(15)), // total_processed_time + BuilderFactory.LONG.build(pairList.get(17)), // total_record_processed + BuilderFactory.STRING_LIST.build(pairList.get(11)) // pending_ids + ))// + .collect(Collectors.toList()); + } + }; +} diff --git a/src/main/java/redis/clients/jedis/gears/resps/GearsLibraryInfo.java b/src/main/java/redis/clients/jedis/gears/resps/GearsLibraryInfo.java new file mode 100644 index 0000000000..5ed6515ff6 --- /dev/null +++ b/src/main/java/redis/clients/jedis/gears/resps/GearsLibraryInfo.java @@ -0,0 +1,182 @@ +package redis.clients.jedis.gears.resps; + +import redis.clients.jedis.Builder; +import redis.clients.jedis.util.KeyValue; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import static redis.clients.jedis.BuilderFactory.*; +import static redis.clients.jedis.gears.resps.FunctionInfo.FUNCTION_INFO_LIST; +import static redis.clients.jedis.gears.resps.StreamTriggerInfo.STREAM_TRIGGER_INFO_LIST; +import static redis.clients.jedis.gears.resps.TriggerInfo.KEYSPACE_TRIGGER_INFO_LIST; + +public class GearsLibraryInfo { + private final String apiVersion; + private final List clusterFunctions; + private final String code; + private final String configuration; + private final String engine; + private final List functions; + private final List keyspaceTriggers; + private final String name; + private final List pendingAsyncCalls; + private final long pendingJobs; + private final List streamTriggers; + private final String user; + + public GearsLibraryInfo(String apiVersion, List clusterFunctions, String code, String configuration, + String engine, List functions, List keyspaceTriggers, String name, + List pendingAsyncCalls, long pendingJobs, List streamTriggers, String user) { + this.apiVersion = apiVersion; + this.clusterFunctions = clusterFunctions; + this.code = code; + this.configuration = configuration; + this.engine = engine; + this.functions = functions; + this.keyspaceTriggers = keyspaceTriggers; + this.name = name; + this.pendingAsyncCalls = pendingAsyncCalls; + this.pendingJobs = pendingJobs; + this.streamTriggers = streamTriggers; + this.user = user; + } + public String getApiVersion() { + return apiVersion; + } + + public List getClusterFunctions() { + return clusterFunctions; + } + + public String getCode() { + return code; + } + + public String getConfiguration() { + return configuration; + } + + public String getEngine() { + return engine; + } + + public List getFunctions() { + return functions; + } + + public List getKeyspaceTriggers() { + return keyspaceTriggers; + } + + public String getName() { + return name; + } + + public List getPendingAsyncCalls() { + return pendingAsyncCalls; + } + + public long getPendingJobs() { + return pendingJobs; + } + + public List getStreamTriggers() { + return streamTriggers; + } + + public String getUser() { + return user; + } + + public static final Builder GEARS_LIBRARY_INFO = new Builder() { + @Override + public GearsLibraryInfo build(Object data) { + if (data == null) return null; + List list = (List) data; + if (list.isEmpty()) return null; + + String apiVersion = null; + List clusterFunctions = Collections.emptyList(); + String code = null; + String configuration = null; + String engine = null; + List functions = Collections.emptyList(); + List keyspaceTriggers = Collections.emptyList(); + String name = null; + List pendingAsyncCalls = null; + long pendingJobs = 0; + List streamTriggers = Collections.emptyList(); + String user = null; + + if (list.get(0) instanceof KeyValue) { + for (KeyValue kv : (List) list) { + switch (STRING.build(kv.getKey())) { + case "api_version": + apiVersion = STRING.build(kv.getValue()); + break; + case "cluster_functions": + clusterFunctions = STRING_LIST.build(kv.getValue()); + break; + case "configuration": + configuration = STRING.build(kv.getValue()); + break; + case "engine": + engine = STRING.build(kv.getValue()); + break; + case "functions": + functions = FUNCTION_INFO_LIST.build(kv.getValue()); + break; + case "keyspace_triggers": + keyspaceTriggers = KEYSPACE_TRIGGER_INFO_LIST.build(kv.getValue()); + break; + case "name": + name = STRING.build(kv.getValue()); + break; + case "pending_async_calls": + pendingAsyncCalls = STRING_LIST.build(kv.getValue()); + break; + case "pending_jobs": + pendingJobs = LONG.build(kv.getValue()); + break; + case "stream_triggers": + streamTriggers = STREAM_TRIGGER_INFO_LIST.build(kv.getValue()); + break; + case "user": + user = STRING.build(kv.getValue()); + break; + case "code": + code = STRING.build(kv.getValue()); + break; + } + } + } else { + boolean withCode = list.size() > 23; + int offset = withCode ? 2 : 0; + apiVersion = STRING.build(list.get(1)); + clusterFunctions = STRING_LIST.build(list.get(3)); + code = withCode ? STRING.build(list.get(5)) : null; + configuration = STRING.build(list.get(5 + offset)); + engine = STRING.build(list.get(7 + offset)); + functions = FUNCTION_INFO_LIST.build(list.get(9 + offset)); + keyspaceTriggers = KEYSPACE_TRIGGER_INFO_LIST.build(list.get(11 + offset)); + name = STRING.build(list.get(13 + offset)); + pendingAsyncCalls = STRING_LIST.build(list.get(15 + offset)); + pendingJobs = LONG.build(list.get(17 + offset)); + streamTriggers = STREAM_TRIGGER_INFO_LIST.build(list.get(19 + offset)); + user = STRING.build(list.get(21 + offset)); + } + return new GearsLibraryInfo(apiVersion, clusterFunctions, code, configuration, engine, functions, keyspaceTriggers, name, pendingAsyncCalls, pendingJobs, streamTriggers, user); + } + }; + + public static final Builder> GEARS_LIBRARY_INFO_LIST = new Builder>() { + @Override + public List build(Object data) { + List list = (List) data; + return list.stream().map(o -> GearsLibraryInfo.GEARS_LIBRARY_INFO.build(o)).collect(Collectors.toList()); + } + }; + +} \ No newline at end of file diff --git a/src/main/java/redis/clients/jedis/gears/resps/StreamTriggerInfo.java b/src/main/java/redis/clients/jedis/gears/resps/StreamTriggerInfo.java new file mode 100644 index 0000000000..be526e0e71 --- /dev/null +++ b/src/main/java/redis/clients/jedis/gears/resps/StreamTriggerInfo.java @@ -0,0 +1,145 @@ +package redis.clients.jedis.gears.resps; + +import redis.clients.jedis.Builder; +import redis.clients.jedis.util.KeyValue; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import static redis.clients.jedis.BuilderFactory.*; +import static redis.clients.jedis.gears.resps.FunctionStreamInfo.STREAM_INFO_LIST; + +public class StreamTriggerInfo { + private final String name; + private final String description; + private final String prefix; + private final boolean trim; + private final long window; + private final List streams; + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public String getPrefix() { + return prefix; + } + public boolean isTrim() { + return trim; + } + + public long getWindow() { + return window; + } + + public List getStreams() { + return streams; + } + + public StreamTriggerInfo(String name, String description, String prefix, + long window, boolean trim, List streams) { + this.name = name; + this.description = description; + this.prefix = prefix; + this.window = window; + this.trim = trim; + this.streams = streams; + } + public StreamTriggerInfo(String name) { + this(name, null, null, 0, false, Collections.emptyList()); + } + + public StreamTriggerInfo(String name, String description, String prefix, + long window, boolean trim) { + this(name, description, prefix, window, trim, Collections.emptyList()); + } + + public static final Builder> STREAM_TRIGGER_INFO_LIST = new Builder>() { + @Override + public List build(Object data) { + List dataAsList = (List) data; + if (!dataAsList.isEmpty()) { + boolean isListOfList = dataAsList.get(0).getClass().isAssignableFrom(ArrayList.class); + if (isListOfList) { + if (((List>)data).get(0).get(0) instanceof KeyValue) { + List> dataAsKeyValues = (List>)data; + return dataAsKeyValues.stream().map(keyValues -> { + String name = null; + String description = null; + String prefix = null; + long window = 0; + boolean trim = false; + List streams = null; + + for (KeyValue kv : keyValues) { + switch (STRING.build(kv.getKey())) { + case "name": + name = STRING.build(kv.getValue()); + break; + case "description": + description = STRING.build(kv.getValue()); + break; + case "prefix": + prefix = STRING.build(kv.getValue()); + break; + case "window": + window = LONG.build(kv.getValue()); + break; + case "trim": + trim = BOOLEAN.build(kv.getValue()); + break; + case "streams": + streams = STREAM_INFO_LIST.build(kv.getValue()); + break; + } + } + return new StreamTriggerInfo(name, description, prefix, window, trim, streams); + }).collect(Collectors.toList()); + } else { + return dataAsList.stream().map((pairObject) -> (List) pairObject).map((pairList) -> { + StreamTriggerInfo result = null; + switch (pairList.size()) { + case 1: + result = new StreamTriggerInfo(STRING.build(pairList.get(0))); + break; + case 10: + result = new StreamTriggerInfo( // + STRING.build(pairList.get(3)), // name + STRING.build(pairList.get(1)), // description + STRING.build(pairList.get(5)), // prefix + LONG.build(pairList.get(9)), // window + BOOLEAN.build(pairList.get(7)) // trim + ); + break; + case 12: + result = new StreamTriggerInfo( // + STRING.build(pairList.get(3)), // name + STRING.build(pairList.get(1)), // description + STRING.build(pairList.get(5)), // prefix + LONG.build(pairList.get(11)), // window + BOOLEAN.build(pairList.get(9)), // trim + STREAM_INFO_LIST.build(pairList.get(7)) // streams + ); + break; + } + return result; + }) // + .collect(Collectors.toList()); + } + } else { + return dataAsList.stream() // + .map(STRING::build).map((name) -> new StreamTriggerInfo(name, null, null, 0, false)) // + .collect(Collectors.toList()); + } + } else { + return Collections.emptyList(); + } + } + }; +} diff --git a/src/main/java/redis/clients/jedis/gears/resps/TriggerInfo.java b/src/main/java/redis/clients/jedis/gears/resps/TriggerInfo.java new file mode 100644 index 0000000000..8a5b470484 --- /dev/null +++ b/src/main/java/redis/clients/jedis/gears/resps/TriggerInfo.java @@ -0,0 +1,162 @@ +package redis.clients.jedis.gears.resps; + +import redis.clients.jedis.Builder; +import redis.clients.jedis.util.KeyValue; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import static redis.clients.jedis.BuilderFactory.LONG; +import static redis.clients.jedis.BuilderFactory.STRING; + +public class TriggerInfo { + private final String name; + private final String description; + + private final String lastError; + + private final long lastExecutionTime; + + private final long numFailed; + + private final long numFinished; + + private final long numSuccess; + + private final long numTrigger; + + private final long totalExecutionTime; + + + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public String getLastError() { + return lastError; + } + + public long getLastExecutionTime() { + return lastExecutionTime; + } + + public long getNumFailed() { + return numFailed; + } + + public long getNumFinished() { + return numFinished; + } + + public long getNumSuccess() { + return numSuccess; + } + + public long getNumTrigger() { + return numTrigger; + } + + public long getTotalExecutionTime() { + return totalExecutionTime; + } + + public TriggerInfo(String name, String description, String lastError, long numFinished, long numSuccess, + long numFailed, long numTrigger, long lastExecutionTime, long totalExecutionTime) { + this.name = name; + this.description = description; + this.lastError = lastError; + this.numFinished = numFinished; + this.numSuccess = numSuccess; + this.numFailed = numFailed; + this.numTrigger = numTrigger; + this.lastExecutionTime = lastExecutionTime; + this.totalExecutionTime = totalExecutionTime; + } + + public static final Builder> KEYSPACE_TRIGGER_INFO_LIST = new Builder>() { + @Override + public List build(Object data) { + List dataAsList = (List) data; + if (!dataAsList.isEmpty()) { + boolean isListOfList = dataAsList.get(0).getClass().isAssignableFrom(ArrayList.class); + if (isListOfList) { + if (((List>)data).get(0).get(0) instanceof KeyValue) { + List> dataAsKeyValues = (List>)data; + return dataAsKeyValues.stream().map(keyValues -> { + String name = null; + String description = null; + String lastError = null; + long lastExecutionTime = 0; + long numFailed = 0; + long numFinished = 0; + long numSuccess = 0; + long numTrigger = 0; + long totalExecutionTime = 0; + + for (KeyValue kv : keyValues) { + switch (STRING.build(kv.getKey())) { + case "name": + name = STRING.build(kv.getValue()); + break; + case "description": + description = STRING.build(kv.getValue()); + break; + case "last_error": + lastError = STRING.build(kv.getValue()); + break; + case "last_execution_time": + lastExecutionTime = LONG.build(kv.getValue()); + break; + case "num_failed": + numFailed = LONG.build(kv.getValue()); + break; + case "num_finished": + numFinished = LONG.build(kv.getValue()); + break; + case "num_success": + numSuccess = LONG.build(kv.getValue()); + break; + case "num_trigger": + numTrigger = LONG.build(kv.getValue()); + break; + case "total_execution_time": + totalExecutionTime = LONG.build(kv.getValue()); + break; + } + } + return new TriggerInfo(name, description, lastError, numFinished, numSuccess, numFailed, numTrigger, + lastExecutionTime, totalExecutionTime); + }).collect(Collectors.toList()); + } else { + return dataAsList.stream().map((pairObject) -> (List) pairObject) + .map((pairList) -> new TriggerInfo(STRING.build(pairList.get(7)), // name + STRING.build(pairList.get(1)), // description + STRING.build(pairList.get(3)), // last_error + LONG.build(pairList.get(11)), // num_finished + LONG.build(pairList.get(13)), // num_success + LONG.build(pairList.get(9)), // num_failed + LONG.build(pairList.get(15)), // num_trigger + LONG.build(pairList.get(5)), // last_execution_time + LONG.build(pairList.get(17)) // total_execution_time + ))// + .collect(Collectors.toList()); + } + } else { + return dataAsList.stream() // + .map(STRING::build)// + .map((name) -> new TriggerInfo(name, null, null, 0,0,0,0,0,0)) // + .collect(Collectors.toList()); + } + } else { + return Collections.emptyList(); + } + } + }; +} diff --git a/src/main/java/redis/clients/jedis/graph/GraphCache.java b/src/main/java/redis/clients/jedis/graph/GraphCache.java index 5ee78def0b..e168e3ee4c 100644 --- a/src/main/java/redis/clients/jedis/graph/GraphCache.java +++ b/src/main/java/redis/clients/jedis/graph/GraphCache.java @@ -3,7 +3,9 @@ /** * Store a local cache in the client, for a specific graph. Holds the labels, property names and * relationship types. + * @deprecated Redis Graph support is deprecated. */ +@Deprecated interface GraphCache { /** diff --git a/src/main/java/redis/clients/jedis/graph/GraphCommandObjects.java b/src/main/java/redis/clients/jedis/graph/GraphCommandObjects.java index be0d44157c..a9a49c9081 100644 --- a/src/main/java/redis/clients/jedis/graph/GraphCommandObjects.java +++ b/src/main/java/redis/clients/jedis/graph/GraphCommandObjects.java @@ -9,19 +9,27 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.function.Function; import redis.clients.jedis.Builder; import redis.clients.jedis.CommandArguments; import redis.clients.jedis.CommandObject; import redis.clients.jedis.Connection; +import redis.clients.jedis.commands.ProtocolCommand; import redis.clients.jedis.graph.GraphProtocol.GraphCommand; import redis.clients.jedis.providers.ConnectionProvider; +/** + * @deprecated Redis Graph support is deprecated. + */ +@Deprecated public class GraphCommandObjects { private final RedisGraphCommands graph; private final Connection connection; private final ConnectionProvider provider; + private Function commArgs = (comm) -> new CommandArguments(comm); + private final ConcurrentHashMap> builders = new ConcurrentHashMap<>(); public GraphCommandObjects(RedisGraphCommands graphCommands) { @@ -31,24 +39,28 @@ public GraphCommandObjects(RedisGraphCommands graphCommands) { } public GraphCommandObjects(Connection connection) { + this.graph = null; this.connection = connection; this.provider = null; - this.graph = null; } public GraphCommandObjects(ConnectionProvider provider) { - this.provider = provider; - this.connection = null; this.graph = null; + this.connection = null; + this.provider = provider; + } + + public void setBaseCommandArgumentsCreator(Function commArgs) { + this.commArgs = commArgs; } // RedisGraph commands public final CommandObject graphQuery(String name, String query) { - return new CommandObject<>(new CommandArguments(GraphCommand.QUERY).key(name).add(query).add(__COMPACT), getBuilder(name)); + return new CommandObject<>(commArgs.apply(GraphCommand.QUERY).key(name).add(query).add(__COMPACT), getBuilder(name)); } public final CommandObject graphReadonlyQuery(String name, String query) { - return new CommandObject<>(new CommandArguments(GraphCommand.RO_QUERY).key(name).add(query).add(__COMPACT), getBuilder(name)); + return new CommandObject<>(commArgs.apply(GraphCommand.RO_QUERY).key(name).add(query).add(__COMPACT), getBuilder(name)); } public final CommandObject graphQuery(String name, String query, long timeout) { @@ -76,11 +88,13 @@ public final CommandObject graphReadonlyQuery(String name, String que } private CommandObject graphQuery(String name, GraphQueryParams params) { - return new CommandObject<>(params.getArguments(name), getBuilder(name)); + return new CommandObject<>( + commArgs.apply(!params.isReadonly() ? GraphCommand.QUERY : GraphCommand.RO_QUERY) + .key(name).addParams(params), getBuilder(name)); } public final CommandObject graphDelete(String name) { - return new CommandObject<>(new CommandArguments(GraphCommand.DELETE).key(name), STRING); + return new CommandObject<>(commArgs.apply(GraphCommand.DELETE).key(name), STRING); } // RedisGraph commands diff --git a/src/main/java/redis/clients/jedis/graph/GraphProtocol.java b/src/main/java/redis/clients/jedis/graph/GraphProtocol.java index 0e06eb0bc8..6884466c10 100644 --- a/src/main/java/redis/clients/jedis/graph/GraphProtocol.java +++ b/src/main/java/redis/clients/jedis/graph/GraphProtocol.java @@ -4,8 +4,10 @@ import redis.clients.jedis.commands.ProtocolCommand; import redis.clients.jedis.util.SafeEncoder; +@Deprecated public class GraphProtocol { + @Deprecated public enum GraphCommand implements ProtocolCommand { QUERY, @@ -29,6 +31,7 @@ public byte[] getRaw() { } } + @Deprecated public enum GraphKeyword implements Rawable { CYPHER, diff --git a/src/main/java/redis/clients/jedis/graph/GraphQueryParams.java b/src/main/java/redis/clients/jedis/graph/GraphQueryParams.java index c181a8e823..f670c1e5c1 100644 --- a/src/main/java/redis/clients/jedis/graph/GraphQueryParams.java +++ b/src/main/java/redis/clients/jedis/graph/GraphQueryParams.java @@ -2,12 +2,16 @@ import java.util.HashMap; import java.util.Map; + import redis.clients.jedis.CommandArguments; import redis.clients.jedis.exceptions.JedisException; -import redis.clients.jedis.graph.GraphProtocol.GraphCommand; import redis.clients.jedis.graph.GraphProtocol.GraphKeyword; import redis.clients.jedis.params.IParams; +/** + * @deprecated Redis Graph support is deprecated. + */ +@Deprecated public class GraphQueryParams implements IParams { private boolean readonly; @@ -83,8 +87,7 @@ public void addParams(CommandArguments args) { } } - public CommandArguments getArguments(String graphName) { - return new CommandArguments(!readonly ? GraphCommand.QUERY : GraphCommand.RO_QUERY) - .key(graphName).addParams(this); + public boolean isReadonly() { + return readonly; } } diff --git a/src/main/java/redis/clients/jedis/graph/Header.java b/src/main/java/redis/clients/jedis/graph/Header.java index f69b16df09..a9ed7e0314 100644 --- a/src/main/java/redis/clients/jedis/graph/Header.java +++ b/src/main/java/redis/clients/jedis/graph/Header.java @@ -3,8 +3,10 @@ import java.util.List; /** - * Query response header interface. Represents the response schema (column names and types) + * Query response header interface. Represents the response schema (column names and types). + * @deprecated Redis Graph support is deprecated. */ +@Deprecated public interface Header { List getSchemaTypes(); diff --git a/src/main/java/redis/clients/jedis/graph/Record.java b/src/main/java/redis/clients/jedis/graph/Record.java index 46e6abb58d..9e02fd9849 100644 --- a/src/main/java/redis/clients/jedis/graph/Record.java +++ b/src/main/java/redis/clients/jedis/graph/Record.java @@ -6,7 +6,10 @@ * Container for RedisGraph result values. * * List records are returned from RedisGraph statement execution, contained within a ResultSet. + * + * @deprecated Redis Graph support is deprecated. */ +@Deprecated public interface Record { /** @@ -63,7 +66,7 @@ public interface Record { * * @param key header key * - * @return true if the the key exists + * @return true if the key exists */ boolean containsKey(String key); diff --git a/src/main/java/redis/clients/jedis/graph/RedisGraphCommands.java b/src/main/java/redis/clients/jedis/graph/RedisGraphCommands.java index fdcbbf102a..45115a7bfa 100644 --- a/src/main/java/redis/clients/jedis/graph/RedisGraphCommands.java +++ b/src/main/java/redis/clients/jedis/graph/RedisGraphCommands.java @@ -3,6 +3,10 @@ import java.util.List; import java.util.Map; +/** + * @deprecated Redis Graph support is deprecated. + */ +@Deprecated public interface RedisGraphCommands { /** @@ -11,7 +15,9 @@ public interface RedisGraphCommands { * @param name a graph to perform the query on * @param query Cypher query * @return a result set + * @deprecated Redis Graph support is deprecated. */ + @Deprecated ResultSet graphQuery(String name, String query); /** @@ -20,7 +26,9 @@ public interface RedisGraphCommands { * @param name a graph to perform the query on * @param query Cypher query * @return a result set + * @deprecated Redis Graph support is deprecated. */ + @Deprecated ResultSet graphReadonlyQuery(String name, String query); /** @@ -30,7 +38,9 @@ public interface RedisGraphCommands { * @param query Cypher query * @param timeout * @return a result set + * @deprecated Redis Graph support is deprecated. */ + @Deprecated ResultSet graphQuery(String name, String query, long timeout); /** @@ -40,7 +50,9 @@ public interface RedisGraphCommands { * @param query Cypher query * @param timeout * @return a result set + * @deprecated Redis Graph support is deprecated. */ + @Deprecated ResultSet graphReadonlyQuery(String name, String query, long timeout); /** @@ -50,7 +62,9 @@ public interface RedisGraphCommands { * @param query Cypher query. * @param params parameters map. * @return a result set. + * @deprecated Redis Graph support is deprecated. */ + @Deprecated ResultSet graphQuery(String name, String query, Map params); /** @@ -60,7 +74,9 @@ public interface RedisGraphCommands { * @param query Cypher query. * @param params parameters map. * @return a result set. + * @deprecated Redis Graph support is deprecated. */ + @Deprecated ResultSet graphReadonlyQuery(String name, String query, Map params); /** @@ -71,7 +87,9 @@ public interface RedisGraphCommands { * @param params parameters map. * @param timeout * @return a result set. + * @deprecated Redis Graph support is deprecated. */ + @Deprecated ResultSet graphQuery(String name, String query, Map params, long timeout); /** @@ -82,7 +100,9 @@ public interface RedisGraphCommands { * @param params parameters map. * @param timeout * @return a result set. + * @deprecated Redis Graph support is deprecated. */ + @Deprecated ResultSet graphReadonlyQuery(String name, String query, Map params, long timeout); /** @@ -90,32 +110,44 @@ public interface RedisGraphCommands { * * @param name graph to delete * @return delete running time statistics + * @deprecated Redis Graph support is deprecated. */ + @Deprecated String graphDelete(String name); /** * Lists all graph keys in the keyspace. * @return graph keys + * @deprecated Redis Graph support is deprecated. */ + @Deprecated List graphList(); /** * Executes a query and produces an execution plan augmented with metrics for each operation's execution. + * @deprecated Redis Graph support is deprecated. */ + @Deprecated List graphProfile(String graphName, String query); /** * Constructs a query execution plan but does not run it. Inspect this execution plan to better understand how your * query will get executed. + * @deprecated Redis Graph support is deprecated. */ + @Deprecated List graphExplain(String graphName, String query); /** * Returns a list containing up to 10 of the slowest queries issued against the given graph ID. + * @deprecated Redis Graph support is deprecated. */ - List> graphSlowlog(String graphName); + @Deprecated + List> graphSlowlog(String graphName); + @Deprecated String graphConfigSet(String configName, Object value); + @Deprecated Map graphConfigGet(String configName); } diff --git a/src/main/java/redis/clients/jedis/graph/RedisGraphPipelineCommands.java b/src/main/java/redis/clients/jedis/graph/RedisGraphPipelineCommands.java index ecc97a6c8f..b270fc79c8 100644 --- a/src/main/java/redis/clients/jedis/graph/RedisGraphPipelineCommands.java +++ b/src/main/java/redis/clients/jedis/graph/RedisGraphPipelineCommands.java @@ -4,25 +4,39 @@ import java.util.Map; import redis.clients.jedis.Response; +/** + * @deprecated Redis Graph support is deprecated. + */ +@Deprecated public interface RedisGraphPipelineCommands { + @Deprecated Response graphQuery(String name, String query); + @Deprecated Response graphReadonlyQuery(String name, String query); + @Deprecated Response graphQuery(String name, String query, long timeout); + @Deprecated Response graphReadonlyQuery(String name, String query, long timeout); + @Deprecated Response graphQuery(String name, String query, Map params); + @Deprecated Response graphReadonlyQuery(String name, String query, Map params); + @Deprecated Response graphQuery(String name, String query, Map params, long timeout); + @Deprecated Response graphReadonlyQuery(String name, String query, Map params, long timeout); + @Deprecated Response graphDelete(String name); + @Deprecated Response> graphProfile(String graphName, String query); } diff --git a/src/main/java/redis/clients/jedis/graph/RedisGraphQueryUtil.java b/src/main/java/redis/clients/jedis/graph/RedisGraphQueryUtil.java index a98cb49745..d762dc47f6 100644 --- a/src/main/java/redis/clients/jedis/graph/RedisGraphQueryUtil.java +++ b/src/main/java/redis/clients/jedis/graph/RedisGraphQueryUtil.java @@ -6,6 +6,10 @@ import java.util.Map; import java.util.stream.Collectors; +/** + * @deprecated Redis Graph support is deprecated. + */ +@Deprecated public class RedisGraphQueryUtil { public static final List DUMMY_LIST = Collections.emptyList(); @@ -22,7 +26,9 @@ private RedisGraphQueryUtil() { * @param query - query * @param params - query parameters * @return query with parameters header + * @deprecated Redis Graph support is deprecated. */ + @Deprecated public static String prepareQuery(String query, Map params) { StringBuilder sb = new StringBuilder("CYPHER "); for (Map.Entry entry : params.entrySet()) { diff --git a/src/main/java/redis/clients/jedis/graph/ResultSet.java b/src/main/java/redis/clients/jedis/graph/ResultSet.java index da0a5bcce1..795afa207a 100644 --- a/src/main/java/redis/clients/jedis/graph/ResultSet.java +++ b/src/main/java/redis/clients/jedis/graph/ResultSet.java @@ -1,8 +1,10 @@ package redis.clients.jedis.graph; /** - * Hold a query result + * Hold a query result. + * @deprecated Redis Graph support is deprecated. */ +@Deprecated public interface ResultSet extends Iterable { public enum ColumnType { diff --git a/src/main/java/redis/clients/jedis/graph/ResultSetBuilder.java b/src/main/java/redis/clients/jedis/graph/ResultSetBuilder.java index 55839d74c1..9269331cb4 100644 --- a/src/main/java/redis/clients/jedis/graph/ResultSetBuilder.java +++ b/src/main/java/redis/clients/jedis/graph/ResultSetBuilder.java @@ -17,6 +17,10 @@ import redis.clients.jedis.graph.entities.*; import redis.clients.jedis.util.SafeEncoder; +/** + * @deprecated Redis Graph support is deprecated. + */ +@Deprecated class ResultSetBuilder extends Builder { private final GraphCache graphCache; @@ -334,7 +338,7 @@ private static enum ScalarType { UNKNOWN, NULL, STRING, - INTEGER, // 64 bit long. + INTEGER, // 64-bit long. BOOLEAN, DOUBLE, ARRAY, diff --git a/src/main/java/redis/clients/jedis/graph/Statistics.java b/src/main/java/redis/clients/jedis/graph/Statistics.java index f6ad5240f9..332e426bfc 100644 --- a/src/main/java/redis/clients/jedis/graph/Statistics.java +++ b/src/main/java/redis/clients/jedis/graph/Statistics.java @@ -1,5 +1,9 @@ package redis.clients.jedis.graph; +/** + * @deprecated Redis Graph support is deprecated. + */ +@Deprecated public interface Statistics { int nodesCreated(); diff --git a/src/main/java/redis/clients/jedis/graph/entities/Edge.java b/src/main/java/redis/clients/jedis/graph/entities/Edge.java index c02d810000..9595ee8168 100644 --- a/src/main/java/redis/clients/jedis/graph/entities/Edge.java +++ b/src/main/java/redis/clients/jedis/graph/entities/Edge.java @@ -3,9 +3,11 @@ import java.util.Objects; /** - * A class represent an edge (graph entity). In addition to the base class id and properties, an edge shows its source, - * destination and relationship type + * A class represent an edge (graph entity). In addition to the base class id and properties, an + * edge shows its source, destination and relationship type. + * @deprecated Redis Graph support is deprecated. */ +@Deprecated public class Edge extends GraphEntity { //members diff --git a/src/main/java/redis/clients/jedis/graph/entities/GraphEntity.java b/src/main/java/redis/clients/jedis/graph/entities/GraphEntity.java index e075a670d3..8a6b40ad36 100644 --- a/src/main/java/redis/clients/jedis/graph/entities/GraphEntity.java +++ b/src/main/java/redis/clients/jedis/graph/entities/GraphEntity.java @@ -5,7 +5,9 @@ /** * This is an abstract class for representing a graph entity. A graph entity has an id and a set of * properties. The properties are mapped and accessed by their names. + * @deprecated Redis Graph support is deprecated. */ +@Deprecated public abstract class GraphEntity { protected long id; diff --git a/src/main/java/redis/clients/jedis/graph/entities/Node.java b/src/main/java/redis/clients/jedis/graph/entities/Node.java index 68e6015f4c..7265c8202c 100644 --- a/src/main/java/redis/clients/jedis/graph/entities/Node.java +++ b/src/main/java/redis/clients/jedis/graph/entities/Node.java @@ -6,7 +6,9 @@ /** * * A class represent an node (graph entity). In addition to the base class id and properties, a node has labels. + * @deprecated Redis Graph support is deprecated. */ +@Deprecated public class Node extends GraphEntity { //members diff --git a/src/main/java/redis/clients/jedis/graph/entities/Path.java b/src/main/java/redis/clients/jedis/graph/entities/Path.java index ff6471a3db..2efecb309f 100644 --- a/src/main/java/redis/clients/jedis/graph/entities/Path.java +++ b/src/main/java/redis/clients/jedis/graph/entities/Path.java @@ -5,7 +5,9 @@ /** * This class represents a path in the graph. + * @deprecated Redis Graph support is deprecated. */ +@Deprecated public final class Path { private final List nodes; diff --git a/src/main/java/redis/clients/jedis/graph/entities/Point.java b/src/main/java/redis/clients/jedis/graph/entities/Point.java index 552d141c52..a5edd513c4 100644 --- a/src/main/java/redis/clients/jedis/graph/entities/Point.java +++ b/src/main/java/redis/clients/jedis/graph/entities/Point.java @@ -5,7 +5,9 @@ /** * This class represents a (geographical) point in the graph. + * @deprecated Redis Graph support is deprecated. */ +@Deprecated public final class Point { private static final double EPSILON = 1e-5; diff --git a/src/main/java/redis/clients/jedis/graph/entities/Property.java b/src/main/java/redis/clients/jedis/graph/entities/Property.java index cb02899cd1..1f23ad978f 100644 --- a/src/main/java/redis/clients/jedis/graph/entities/Property.java +++ b/src/main/java/redis/clients/jedis/graph/entities/Property.java @@ -4,7 +4,9 @@ /** * A Graph entity property. Has a name, type, and value. + * @deprecated Redis Graph support is deprecated. */ +@Deprecated public class Property { private final String name; diff --git a/src/main/java/redis/clients/jedis/json/DefaultGsonObjectMapper.java b/src/main/java/redis/clients/jedis/json/DefaultGsonObjectMapper.java new file mode 100644 index 0000000000..1c505581db --- /dev/null +++ b/src/main/java/redis/clients/jedis/json/DefaultGsonObjectMapper.java @@ -0,0 +1,26 @@ +package redis.clients.jedis.json; + +import com.google.gson.Gson; + +/** + * Use the default {@link Gson} configuration for serialization and deserialization JSON + * operations. + *

When none is explicitly set, this will be set.

+ * @see JsonObjectMapper Create a custom JSON serializer/deserializer + */ +public class DefaultGsonObjectMapper implements JsonObjectMapper { + /** + * Instance of Gson object with default gson configuration. + */ + private final Gson gson = new Gson(); + + @Override + public T fromJson(String value, Class valueType) { + return gson.fromJson(value, valueType); + } + + @Override + public String toJson(Object value) { + return gson.toJson(value); + } +} diff --git a/src/main/java/redis/clients/jedis/json/JsonBuilderFactory.java b/src/main/java/redis/clients/jedis/json/JsonBuilderFactory.java index 8b4ec686bc..e4c00f7045 100644 --- a/src/main/java/redis/clients/jedis/json/JsonBuilderFactory.java +++ b/src/main/java/redis/clients/jedis/json/JsonBuilderFactory.java @@ -9,6 +9,7 @@ import org.json.JSONException; import org.json.JSONObject; import redis.clients.jedis.Builder; +import redis.clients.jedis.BuilderFactory; import redis.clients.jedis.exceptions.JedisException; public final class JsonBuilderFactory { @@ -60,6 +61,21 @@ public List> build(Object data) { } }; + public static final Builder>>> JSON_TYPE_RESPONSE_RESP3 = new Builder>>>() { + @Override + public List>> build(Object data) { + return ((List) data).stream().map(JSON_TYPE_LIST::build).collect(Collectors.toList()); + } + }; + + public static final Builder>> JSON_TYPE_RESPONSE_RESP3_COMPATIBLE = new Builder>>() { + @Override + public List> build(Object data) { + List>> fullReply = JSON_TYPE_RESPONSE_RESP3.build(data); + return fullReply == null ? null : fullReply.get(0); + } + }; + public static final Builder JSON_OBJECT = new Builder() { @Override public Object build(Object data) { @@ -70,7 +86,6 @@ public Object build(Object data) { if (!(data instanceof byte[])) { return data; } - String str = STRING.build(data); if (str.charAt(0) == '{') { try { @@ -103,6 +118,15 @@ public JSONArray build(Object data) { } }; + public static final Builder JSON_ARRAY_OR_DOUBLE_LIST = new Builder() { + @Override + public Object build(Object data) { + if (data == null) return null; + if (data instanceof List) return BuilderFactory.DOUBLE_LIST.build(data); + return JSON_ARRAY.build(data); + } + }; + public static final Builder> JSON_ARRAY_LIST = new Builder>() { @Override public List build(Object data) { diff --git a/src/main/java/redis/clients/jedis/json/JsonObjectMapper.java b/src/main/java/redis/clients/jedis/json/JsonObjectMapper.java new file mode 100644 index 0000000000..2ceebe9950 --- /dev/null +++ b/src/main/java/redis/clients/jedis/json/JsonObjectMapper.java @@ -0,0 +1,25 @@ +package redis.clients.jedis.json; + +/** + * Represents the ability of serialize an object to JSON format string and deserialize it to the + * typed object. + * @see DefaultGsonObjectMapper Default implementation for JSON serializer/deserializer + * engine with com.google.gson.Gson + */ +public interface JsonObjectMapper { + /** + * Perform deserialization from JSON format string to the given type object as argument. + * @param value the JSON format + * @param valueType the object type to convert + * @param the type object to convert + * @return the instance of an object to the type given argument + */ + T fromJson(String value, Class valueType); + + /** + * Perform serialization from object to JSON format string. + * @param value the object to convert + * @return the JSON format string + */ + String toJson(Object value); +} diff --git a/src/main/java/redis/clients/jedis/json/JsonProtocol.java b/src/main/java/redis/clients/jedis/json/JsonProtocol.java index 1238ae37ff..c153c19f83 100644 --- a/src/main/java/redis/clients/jedis/json/JsonProtocol.java +++ b/src/main/java/redis/clients/jedis/json/JsonProtocol.java @@ -9,6 +9,7 @@ public enum JsonCommand implements ProtocolCommand { DEL("JSON.DEL"), GET("JSON.GET"), MGET("JSON.MGET"), + MERGE("JSON.MERGE"), SET("JSON.SET"), TYPE("JSON.TYPE"), STRAPPEND("JSON.STRAPPEND"), diff --git a/src/main/java/redis/clients/jedis/json/Path.java b/src/main/java/redis/clients/jedis/json/Path.java index e361cab2ea..d225626e89 100644 --- a/src/main/java/redis/clients/jedis/json/Path.java +++ b/src/main/java/redis/clients/jedis/json/Path.java @@ -1,8 +1,10 @@ package redis.clients.jedis.json; /** - * Path is a ReJSON path, representing a valid path into an object + * Path is a RedisJSON (v1) path, representing a valid path into an object. + * @deprecated RedisJSON (v1) support is deprecated. */ +@Deprecated public class Path { public static final Path ROOT_PATH = new Path("."); diff --git a/src/main/java/redis/clients/jedis/json/Path2.java b/src/main/java/redis/clients/jedis/json/Path2.java index 28211bb470..27c2698689 100644 --- a/src/main/java/redis/clients/jedis/json/Path2.java +++ b/src/main/java/redis/clients/jedis/json/Path2.java @@ -1,7 +1,7 @@ package redis.clients.jedis.json; /** - * Path is a ReJSON path, representing a valid path into an object + * Path is a RedisJSON v2 path, representing a valid path or a multi-path into an object. */ public class Path2 { diff --git a/src/main/java/redis/clients/jedis/json/RedisJsonCommands.java b/src/main/java/redis/clients/jedis/json/RedisJsonCommands.java deleted file mode 100644 index 4567f889ba..0000000000 --- a/src/main/java/redis/clients/jedis/json/RedisJsonCommands.java +++ /dev/null @@ -1,175 +0,0 @@ -package redis.clients.jedis.json; - -import java.util.List; -import org.json.JSONArray; - -public interface RedisJsonCommands { - - default String jsonSet(String key, Object object) { - return RedisJsonCommands.this.jsonSet(key, Path2.ROOT_PATH, object); - } - - default String jsonSetWithEscape(String key, Object object) { - return jsonSetWithEscape(key, Path2.ROOT_PATH, object); - } - - default String jsonSetLegacy(String key, Object pojo) { - return jsonSet(key, Path.ROOT_PATH, pojo); - } - - default String jsonSet(String key, Object object, JsonSetParams params) { - return jsonSet(key, Path2.ROOT_PATH, object, params); - } - - default String jsonSetWithEscape(String key, Object object, JsonSetParams params) { - return jsonSetWithEscape(key, Path2.ROOT_PATH, object, params); - } - - default String jsonSetLegacy(String key, Object pojo, JsonSetParams params) { - return jsonSet(key, Path.ROOT_PATH, pojo, params); - } - - String jsonSet(String key, Path2 path, Object object); - - String jsonSetWithEscape(String key, Path2 path, Object object); - - String jsonSet(String key, Path path, Object pojo); - - String jsonSetWithPlainString(String key, Path path, String string); - - String jsonSet(String key, Path2 path, Object object, JsonSetParams params); - - String jsonSetWithEscape(String key, Path2 path, Object object, JsonSetParams params); - - String jsonSet(String key, Path path, Object pojo, JsonSetParams params); - - Object jsonGet(String key); - - T jsonGet(String key, Class clazz); - - Object jsonGet(String key, Path2... paths); - - Object jsonGet(String key, Path... paths); - - String jsonGetAsPlainString(String key, Path path); - - T jsonGet(String key, Class clazz, Path... paths); - - default List jsonMGet(String... keys) { - return jsonMGet(Path2.ROOT_PATH, keys); - } - - default List jsonMGet(Class clazz, String... keys) { - return jsonMGet(Path.ROOT_PATH, clazz, keys); - } - - List jsonMGet(Path2 path, String... keys); - - List jsonMGet(Path path, Class clazz, String... keys); - - long jsonDel(String key); - - long jsonDel(String key, Path2 path); - - long jsonDel(String key, Path path); - - long jsonClear(String key); - - long jsonClear(String key, Path2 path); - - long jsonClear(String key, Path path); - - List jsonToggle(String key, Path2 path); - - String jsonToggle(String key, Path path); - - Class jsonType(String key); - - List> jsonType(String key, Path2 path); - - Class jsonType(String key, Path path); - - long jsonStrAppend(String key, Object string); - - List jsonStrAppend(String key, Path2 path, Object string); - - long jsonStrAppend(String key, Path path, Object string); - - Long jsonStrLen(String key); - - List jsonStrLen(String key, Path2 path); - - Long jsonStrLen(String key, Path path); - - JSONArray jsonNumIncrBy(String key, Path2 path, double value); - - double jsonNumIncrBy(String key, Path path, double value); - - List jsonArrAppend(String key, Path2 path, Object... objects); - - List jsonArrAppendWithEscape(String key, Path2 path, Object... objects); - - Long jsonArrAppend(String key, Path path, Object... pojos); - - List jsonArrIndex(String key, Path2 path, Object scalar); - - List jsonArrIndexWithEscape(String key, Path2 path, Object scalar); - - long jsonArrIndex(String key, Path path, Object scalar); - - List jsonArrInsert(String key, Path2 path, int index, Object... objects); - - List jsonArrInsertWithEscape(String key, Path2 path, int index, Object... objects); - - long jsonArrInsert(String key, Path path, int index, Object... pojos); - - Object jsonArrPop(String key); - - T jsonArrPop(String key, Class clazz); - - List jsonArrPop(String key, Path2 path); - - Object jsonArrPop(String key, Path path); - - T jsonArrPop(String key, Class clazz, Path path); - - List jsonArrPop(String key, Path2 path, int index); - - Object jsonArrPop(String key, Path path, int index); - - T jsonArrPop(String key, Class clazz, Path path, int index); - - Long jsonArrLen(String key); - - List jsonArrLen(String key, Path2 path); - - Long jsonArrLen(String key, Path path); - - List jsonArrTrim(String key, Path2 path, int start, int stop); - - Long jsonArrTrim(String key, Path path, int start, int stop); - - Long jsonObjLen(String key); - - Long jsonObjLen(String key, Path path); - - List jsonObjLen(String key, Path2 path); - - List jsonObjKeys(String key); - - List jsonObjKeys(String key, Path path); - - List> jsonObjKeys(String key, Path2 path); - - long jsonDebugMemory(String key); - - long jsonDebugMemory(String key, Path path); - - List jsonDebugMemory(String key, Path2 path); - - List jsonResp(String key); - - List jsonResp(String key, Path path); - - List> jsonResp(String key, Path2 path); -} diff --git a/src/main/java/redis/clients/jedis/json/RedisJsonPipelineCommands.java b/src/main/java/redis/clients/jedis/json/RedisJsonPipelineCommands.java deleted file mode 100644 index e54373851f..0000000000 --- a/src/main/java/redis/clients/jedis/json/RedisJsonPipelineCommands.java +++ /dev/null @@ -1,153 +0,0 @@ -package redis.clients.jedis.json; - -import org.json.JSONArray; -import redis.clients.jedis.Response; - -import java.util.List; - -public interface RedisJsonPipelineCommands { - - default Response jsonSet(String key, Object object) { - return RedisJsonPipelineCommands.this.jsonSet(key, Path2.ROOT_PATH, object); - } - - default Response jsonSetWithEscape(String key, Object object) { - return jsonSetWithEscape(key, Path2.ROOT_PATH, object); - } - - default Response jsonSetLegacy(String key, Object pojo) { - return jsonSet(key, Path.ROOT_PATH, pojo); - } - - default Response jsonSet(String key, Object object, JsonSetParams params) { - return jsonSet(key, Path2.ROOT_PATH, object, params); - } - - default Response jsonSetWithEscape(String key, Object object, JsonSetParams params) { - return jsonSetWithEscape(key, Path2.ROOT_PATH, object, params); - } - - default Response jsonSetLegacy(String key, Object pojo, JsonSetParams params) { - return jsonSet(key, Path.ROOT_PATH, pojo, params); - } - - // Response jsonGet(String key); - - // Response jsonGet(String key, Path... paths); - - Response jsonSet(String key, Path2 path, Object object); - - Response jsonSetWithEscape(String key, Path2 path, Object object); - - Response jsonSet(String key, Path path, Object pojo); - - Response jsonSet(String key, Path2 path, Object object, JsonSetParams params); - - Response jsonSetWithEscape(String key, Path2 path, Object object, JsonSetParams params); - - Response jsonSet(String key, Path path, Object pojo, JsonSetParams params); - - Response jsonGet(String key); - - Response jsonGet(String key, Class clazz); - - Response jsonGet(String key, Path2... paths); - - Response jsonGet(String key, Path... paths); - - Response jsonGet(String key, Class clazz, Path... paths); - - default Response> jsonMGet(String... keys) { - return jsonMGet(Path2.ROOT_PATH, keys); - } - - default Response> jsonMGet(Class clazz, String... keys) { - return jsonMGet(Path.ROOT_PATH, clazz, keys); - } - - Response> jsonMGet(Path2 path, String... keys); - - Response> jsonMGet(Path path, Class clazz, String... keys); - - Response jsonDel(String key); - - Response jsonDel(String key, Path2 path); - - Response jsonDel(String key, Path path); - - Response jsonClear(String key); - - Response jsonClear(String key, Path2 path); - - Response jsonClear(String key, Path path); - - Response> jsonToggle(String key, Path2 path); - - Response jsonToggle(String key, Path path); - - Response> jsonType(String key); - - Response>> jsonType(String key, Path2 path); - - Response> jsonType(String key, Path path); - - Response jsonStrAppend(String key, Object string); - - Response> jsonStrAppend(String key, Path2 path, Object string); - - Response jsonStrAppend(String key, Path path, Object string); - - Response jsonStrLen(String key); - - Response> jsonStrLen(String key, Path2 path); - - Response jsonStrLen(String key, Path path); - - Response jsonNumIncrBy(String key, Path2 path, double value); - - Response jsonNumIncrBy(String key, Path path, double value); - - Response> jsonArrAppend(String key, Path2 path, Object... objects); - - Response> jsonArrAppendWithEscape(String key, Path2 path, Object... objects); - - Response jsonArrAppend(String key, Path path, Object... pojos); - - Response> jsonArrIndex(String key, Path2 path, Object scalar); - - Response> jsonArrIndexWithEscape(String key, Path2 path, Object scalar); - - Response jsonArrIndex(String key, Path path, Object scalar); - - Response> jsonArrInsert(String key, Path2 path, int index, Object... objects); - - Response> jsonArrInsertWithEscape(String key, Path2 path, int index, Object... objects); - - Response jsonArrInsert(String key, Path path, int index, Object... pojos); - - Response jsonArrPop(String key); - - Response jsonArrPop(String key, Class clazz); - - Response> jsonArrPop(String key, Path2 path); - - Response jsonArrPop(String key, Path path); - - Response jsonArrPop(String key, Class clazz, Path path); - - Response> jsonArrPop(String key, Path2 path, int index); - - Response jsonArrPop(String key, Path path, int index); - - Response jsonArrPop(String key, Class clazz, Path path, int index); - - Response jsonArrLen(String key); - - Response> jsonArrLen(String key, Path2 path); - - Response jsonArrLen(String key, Path path); - - Response> jsonArrTrim(String key, Path2 path, int start, int stop); - - Response jsonArrTrim(String key, Path path, int start, int stop); -} diff --git a/src/main/java/redis/clients/jedis/json/commands/RedisJsonCommands.java b/src/main/java/redis/clients/jedis/json/commands/RedisJsonCommands.java new file mode 100644 index 0000000000..e2d6ae885c --- /dev/null +++ b/src/main/java/redis/clients/jedis/json/commands/RedisJsonCommands.java @@ -0,0 +1,5 @@ +package redis.clients.jedis.json.commands; + +public interface RedisJsonCommands extends RedisJsonV1Commands, RedisJsonV2Commands { + +} diff --git a/src/main/java/redis/clients/jedis/json/commands/RedisJsonPipelineCommands.java b/src/main/java/redis/clients/jedis/json/commands/RedisJsonPipelineCommands.java new file mode 100644 index 0000000000..3aa16a7bc5 --- /dev/null +++ b/src/main/java/redis/clients/jedis/json/commands/RedisJsonPipelineCommands.java @@ -0,0 +1,5 @@ +package redis.clients.jedis.json.commands; + +public interface RedisJsonPipelineCommands extends RedisJsonV1PipelineCommands, RedisJsonV2PipelineCommands { + +} diff --git a/src/main/java/redis/clients/jedis/json/commands/RedisJsonV1Commands.java b/src/main/java/redis/clients/jedis/json/commands/RedisJsonV1Commands.java new file mode 100644 index 0000000000..5d7fe0d8e7 --- /dev/null +++ b/src/main/java/redis/clients/jedis/json/commands/RedisJsonV1Commands.java @@ -0,0 +1,144 @@ +package redis.clients.jedis.json.commands; + +import java.util.List; +import redis.clients.jedis.json.JsonSetParams; +import redis.clients.jedis.json.Path; + +/** + * @deprecated RedisJSON (v1) support is deprecated. + */ +@Deprecated +public interface RedisJsonV1Commands { + + @Deprecated + default String jsonSetLegacy(String key, Object pojo) { + return jsonSet(key, Path.ROOT_PATH, pojo); + } + + @Deprecated + default String jsonSetLegacy(String key, Object pojo, JsonSetParams params) { + return jsonSet(key, Path.ROOT_PATH, pojo, params); + } + + @Deprecated + String jsonSet(String key, Path path, Object pojo); + + @Deprecated + String jsonSetWithPlainString(String key, Path path, String string); + + @Deprecated + String jsonSet(String key, Path path, Object pojo, JsonSetParams params); + + @Deprecated + String jsonMerge(String key, Path path, Object pojo); + + Object jsonGet(String key); // both ver + + @Deprecated + T jsonGet(String key, Class clazz); + + @Deprecated + Object jsonGet(String key, Path... paths); + + @Deprecated + String jsonGetAsPlainString(String key, Path path); + + @Deprecated + T jsonGet(String key, Class clazz, Path... paths); + + @Deprecated + default List jsonMGet(Class clazz, String... keys) { + return jsonMGet(Path.ROOT_PATH, clazz, keys); + } + + @Deprecated + List jsonMGet(Path path, Class clazz, String... keys); + + long jsonDel(String key); // both ver + + @Deprecated + long jsonDel(String key, Path path); + + long jsonClear(String key); // no test + + @Deprecated + long jsonClear(String key, Path path); + + @Deprecated + String jsonToggle(String key, Path path); + + @Deprecated + Class jsonType(String key); + + @Deprecated + Class jsonType(String key, Path path); + + @Deprecated + long jsonStrAppend(String key, Object string); + + @Deprecated + long jsonStrAppend(String key, Path path, Object string); + + @Deprecated + Long jsonStrLen(String key); + + @Deprecated + Long jsonStrLen(String key, Path path); + + @Deprecated + double jsonNumIncrBy(String key, Path path, double value); + + @Deprecated + Long jsonArrAppend(String key, Path path, Object... pojos); + + @Deprecated + long jsonArrIndex(String key, Path path, Object scalar); + + @Deprecated + long jsonArrInsert(String key, Path path, int index, Object... pojos); + + @Deprecated + Object jsonArrPop(String key); + + @Deprecated + T jsonArrPop(String key, Class clazz); + + @Deprecated + Object jsonArrPop(String key, Path path); + + @Deprecated + T jsonArrPop(String key, Class clazz, Path path); + + @Deprecated + Object jsonArrPop(String key, Path path, int index); + + @Deprecated + T jsonArrPop(String key, Class clazz, Path path, int index); + + @Deprecated + Long jsonArrLen(String key); + + @Deprecated + Long jsonArrLen(String key, Path path); + + @Deprecated + Long jsonArrTrim(String key, Path path, int start, int stop); + + @Deprecated + Long jsonObjLen(String key); + + @Deprecated + Long jsonObjLen(String key, Path path); + + @Deprecated + List jsonObjKeys(String key); + + @Deprecated + List jsonObjKeys(String key, Path path); + + @Deprecated + long jsonDebugMemory(String key); + + @Deprecated + long jsonDebugMemory(String key, Path path); +} diff --git a/src/main/java/redis/clients/jedis/json/commands/RedisJsonV1PipelineCommands.java b/src/main/java/redis/clients/jedis/json/commands/RedisJsonV1PipelineCommands.java new file mode 100644 index 0000000000..b447a1e508 --- /dev/null +++ b/src/main/java/redis/clients/jedis/json/commands/RedisJsonV1PipelineCommands.java @@ -0,0 +1,122 @@ +package redis.clients.jedis.json.commands; + +import java.util.List; +import redis.clients.jedis.Response; +import redis.clients.jedis.json.JsonSetParams; +import redis.clients.jedis.json.Path; + +/** + * @deprecated RedisJSON (v1) support is deprecated. + */ +@Deprecated +public interface RedisJsonV1PipelineCommands { + + @Deprecated + default Response jsonSetLegacy(String key, Object pojo) { + return jsonSet(key, Path.ROOT_PATH, pojo); + } + + @Deprecated + default Response jsonSetLegacy(String key, Object pojo, JsonSetParams params) { + return jsonSet(key, Path.ROOT_PATH, pojo, params); + } + + @Deprecated + Response jsonSet(String key, Path path, Object pojo); + + @Deprecated + Response jsonSet(String key, Path path, Object pojo, JsonSetParams params); + + @Deprecated + Response jsonMerge(String key, Path path, Object pojo); + + Response jsonGet(String key); // both ver + + @Deprecated + Response jsonGet(String key, Class clazz); + + @Deprecated + Response jsonGet(String key, Path... paths); + + @Deprecated + Response jsonGet(String key, Class clazz, Path... paths); + + @Deprecated + default Response> jsonMGet(Class clazz, String... keys) { + return jsonMGet(Path.ROOT_PATH, clazz, keys); + } + + @Deprecated + Response> jsonMGet(Path path, Class clazz, String... keys); + + Response jsonDel(String key); // both ver + + @Deprecated + Response jsonDel(String key, Path path); + + @Deprecated + Response jsonClear(String key); // no test + + @Deprecated + Response jsonClear(String key, Path path); + + @Deprecated + Response jsonToggle(String key, Path path); + + @Deprecated + Response> jsonType(String key); + + @Deprecated + Response> jsonType(String key, Path path); + + @Deprecated + Response jsonStrAppend(String key, Object string); + + @Deprecated + Response jsonStrAppend(String key, Path path, Object string); + + @Deprecated + Response jsonStrLen(String key); + + @Deprecated + Response jsonStrLen(String key, Path path); + + @Deprecated + Response jsonNumIncrBy(String key, Path path, double value); + + @Deprecated + Response jsonArrAppend(String key, Path path, Object... pojos); + + @Deprecated + Response jsonArrIndex(String key, Path path, Object scalar); + + @Deprecated + Response jsonArrInsert(String key, Path path, int index, Object... pojos); + + @Deprecated + Response jsonArrPop(String key); + + @Deprecated + Response jsonArrPop(String key, Class clazz); + + @Deprecated + Response jsonArrPop(String key, Path path); + + @Deprecated + Response jsonArrPop(String key, Class clazz, Path path); + + @Deprecated + Response jsonArrPop(String key, Path path, int index); + + @Deprecated + Response jsonArrPop(String key, Class clazz, Path path, int index); + + @Deprecated + Response jsonArrLen(String key); + + @Deprecated + Response jsonArrLen(String key, Path path); + + @Deprecated + Response jsonArrTrim(String key, Path path, int start, int stop); +} diff --git a/src/main/java/redis/clients/jedis/json/commands/RedisJsonV2Commands.java b/src/main/java/redis/clients/jedis/json/commands/RedisJsonV2Commands.java new file mode 100644 index 0000000000..2e5f400650 --- /dev/null +++ b/src/main/java/redis/clients/jedis/json/commands/RedisJsonV2Commands.java @@ -0,0 +1,89 @@ +package redis.clients.jedis.json.commands; + +import java.util.List; +import org.json.JSONArray; +import redis.clients.jedis.json.JsonSetParams; +import redis.clients.jedis.json.Path2; + +public interface RedisJsonV2Commands { + + default String jsonSet(String key, Object object) { + return jsonSet(key, Path2.ROOT_PATH, object); + } + + default String jsonSetWithEscape(String key, Object object) { + return jsonSetWithEscape(key, Path2.ROOT_PATH, object); + } + + default String jsonSet(String key, Object object, JsonSetParams params) { + return jsonSet(key, Path2.ROOT_PATH, object, params); + } + + default String jsonSetWithEscape(String key, Object object, JsonSetParams params) { + return jsonSetWithEscape(key, Path2.ROOT_PATH, object, params); + } + + String jsonSet(String key, Path2 path, Object object); + + String jsonSetWithEscape(String key, Path2 path, Object object); + + String jsonSet(String key, Path2 path, Object object, JsonSetParams params); + + String jsonSetWithEscape(String key, Path2 path, Object object, JsonSetParams params); + + String jsonMerge(String key, Path2 path, Object object); + + Object jsonGet(String key); // both ver + + Object jsonGet(String key, Path2... paths); + + default List jsonMGet(String... keys) { + return jsonMGet(Path2.ROOT_PATH, keys); + } + + List jsonMGet(Path2 path, String... keys); + + long jsonDel(String key); // both ver + + long jsonDel(String key, Path2 path); + + long jsonClear(String key); // no test + + long jsonClear(String key, Path2 path); + + List jsonToggle(String key, Path2 path); + + List> jsonType(String key, Path2 path); + + List jsonStrAppend(String key, Path2 path, Object string); + + List jsonStrLen(String key, Path2 path); + + Object jsonNumIncrBy(String key, Path2 path, double value); + + List jsonArrAppend(String key, Path2 path, Object... objects); + + List jsonArrAppendWithEscape(String key, Path2 path, Object... objects); + + List jsonArrIndex(String key, Path2 path, Object scalar); + + List jsonArrIndexWithEscape(String key, Path2 path, Object scalar); + + List jsonArrInsert(String key, Path2 path, int index, Object... objects); + + List jsonArrInsertWithEscape(String key, Path2 path, int index, Object... objects); + + List jsonArrPop(String key, Path2 path); + + List jsonArrPop(String key, Path2 path, int index); + + List jsonArrLen(String key, Path2 path); + + List jsonArrTrim(String key, Path2 path, int start, int stop); + + List jsonObjLen(String key, Path2 path); + + List> jsonObjKeys(String key, Path2 path); + + List jsonDebugMemory(String key, Path2 path); +} diff --git a/src/main/java/redis/clients/jedis/json/commands/RedisJsonV2PipelineCommands.java b/src/main/java/redis/clients/jedis/json/commands/RedisJsonV2PipelineCommands.java new file mode 100644 index 0000000000..c6fbbac6b3 --- /dev/null +++ b/src/main/java/redis/clients/jedis/json/commands/RedisJsonV2PipelineCommands.java @@ -0,0 +1,84 @@ +package redis.clients.jedis.json.commands; + +import java.util.List; +import org.json.JSONArray; +import redis.clients.jedis.Response; +import redis.clients.jedis.json.JsonSetParams; +import redis.clients.jedis.json.Path2; + +public interface RedisJsonV2PipelineCommands { + + default Response jsonSet(String key, Object object) { + return jsonSet(key, Path2.ROOT_PATH, object); + } + + default Response jsonSetWithEscape(String key, Object object) { + return jsonSetWithEscape(key, Path2.ROOT_PATH, object); + } + + default Response jsonSet(String key, Object object, JsonSetParams params) { + return jsonSet(key, Path2.ROOT_PATH, object, params); + } + + default Response jsonSetWithEscape(String key, Object object, JsonSetParams params) { + return jsonSetWithEscape(key, Path2.ROOT_PATH, object, params); + } + + Response jsonSet(String key, Path2 path, Object object); + + Response jsonSetWithEscape(String key, Path2 path, Object object); + + Response jsonSet(String key, Path2 path, Object object, JsonSetParams params); + + Response jsonSetWithEscape(String key, Path2 path, Object object, JsonSetParams params); + + Response jsonMerge(String key, Path2 path, Object object); + + Response jsonGet(String key); // both ver + + Response jsonGet(String key, Path2... paths); + + default Response> jsonMGet(String... keys) { + return jsonMGet(Path2.ROOT_PATH, keys); + } + + Response> jsonMGet(Path2 path, String... keys); + + Response jsonDel(String key); // both ver + + Response jsonDel(String key, Path2 path); + + Response jsonClear(String key); // no test + + Response jsonClear(String key, Path2 path); + + Response> jsonToggle(String key, Path2 path); + + Response>> jsonType(String key, Path2 path); + + Response> jsonStrAppend(String key, Path2 path, Object string); + + Response> jsonStrLen(String key, Path2 path); + + Response jsonNumIncrBy(String key, Path2 path, double value); + + Response> jsonArrAppend(String key, Path2 path, Object... objects); + + Response> jsonArrAppendWithEscape(String key, Path2 path, Object... objects); + + Response> jsonArrIndex(String key, Path2 path, Object scalar); + + Response> jsonArrIndexWithEscape(String key, Path2 path, Object scalar); + + Response> jsonArrInsert(String key, Path2 path, int index, Object... objects); + + Response> jsonArrInsertWithEscape(String key, Path2 path, int index, Object... objects); + + Response> jsonArrPop(String key, Path2 path); + + Response> jsonArrPop(String key, Path2 path, int index); + + Response> jsonArrLen(String key, Path2 path); + + Response> jsonArrTrim(String key, Path2 path, int start, int stop); +} diff --git a/src/main/java/redis/clients/jedis/mcf/CircuitBreakerCommandExecutor.java b/src/main/java/redis/clients/jedis/mcf/CircuitBreakerCommandExecutor.java new file mode 100644 index 0000000000..7a857174cb --- /dev/null +++ b/src/main/java/redis/clients/jedis/mcf/CircuitBreakerCommandExecutor.java @@ -0,0 +1,61 @@ +package redis.clients.jedis.mcf; + +import io.github.resilience4j.circuitbreaker.CircuitBreaker; +import io.github.resilience4j.decorators.Decorators; +import io.github.resilience4j.decorators.Decorators.DecorateSupplier; + +import redis.clients.jedis.CommandObject; +import redis.clients.jedis.Connection; +import redis.clients.jedis.executors.CommandExecutor; +import redis.clients.jedis.providers.MultiClusterPooledConnectionProvider; +import redis.clients.jedis.providers.MultiClusterPooledConnectionProvider.Cluster; + +/** + * @author Allen Terleto (aterleto) + *

+ * CommandExecutor with built-in retry, circuit-breaker, and failover to another cluster/database endpoint. + * With this executor users can seamlessly failover to Disaster Recovery (DR), Backup, and Active-Active cluster(s) + * by using simple configuration which is passed through from Resilience4j - https://resilience4j.readme.io/docs + *

+ */ +public class CircuitBreakerCommandExecutor extends CircuitBreakerFailoverBase implements CommandExecutor { + + public CircuitBreakerCommandExecutor(MultiClusterPooledConnectionProvider provider) { + super(provider); + } + + @Override + public T executeCommand(CommandObject commandObject) { + Cluster cluster = provider.getCluster(); // Pass this by reference for thread safety + + DecorateSupplier supplier = Decorators.ofSupplier(() -> this.handleExecuteCommand(commandObject, cluster)); + + supplier.withRetry(cluster.getRetry()); + supplier.withCircuitBreaker(cluster.getCircuitBreaker()); + supplier.withFallback(defaultCircuitBreakerFallbackException, + e -> this.handleClusterFailover(commandObject, cluster.getCircuitBreaker())); + + return supplier.decorate().get(); + } + + /** + * Functional interface wrapped in retry and circuit breaker logic to handle happy path scenarios + */ + private T handleExecuteCommand(CommandObject commandObject, Cluster cluster) { + try (Connection connection = cluster.getConnection()) { + return connection.executeCommand(commandObject); + } + } + + /** + * Functional interface wrapped in retry and circuit breaker logic to handle open circuit breaker failure scenarios + */ + private T handleClusterFailover(CommandObject commandObject, CircuitBreaker circuitBreaker) { + + clusterFailover(circuitBreaker); + + // Recursive call to the initiating method so the operation can be retried on the next cluster connection + return executeCommand(commandObject); + } + +} \ No newline at end of file diff --git a/src/main/java/redis/clients/jedis/mcf/CircuitBreakerFailoverBase.java b/src/main/java/redis/clients/jedis/mcf/CircuitBreakerFailoverBase.java new file mode 100644 index 0000000000..2228233849 --- /dev/null +++ b/src/main/java/redis/clients/jedis/mcf/CircuitBreakerFailoverBase.java @@ -0,0 +1,66 @@ +package redis.clients.jedis.mcf; + +import io.github.resilience4j.circuitbreaker.CallNotPermittedException; +import io.github.resilience4j.circuitbreaker.CircuitBreaker; + +import java.util.Arrays; +import java.util.List; + +import redis.clients.jedis.exceptions.JedisConnectionException; +import redis.clients.jedis.providers.MultiClusterPooledConnectionProvider; +import redis.clients.jedis.util.IOUtils; + +/** + * @author Allen Terleto (aterleto) + *

+ * Base class for CommandExecutor with built-in retry, circuit-breaker, and failover to another cluster/database + * endpoint. With this executor users can seamlessly failover to Disaster Recovery (DR), Backup, and Active-Active + * cluster(s) by using simple configuration which is passed through from + * Resilience4j - https://resilience4j.readme.io/docs + *

+ */ +public class CircuitBreakerFailoverBase implements AutoCloseable { + + protected final static List> defaultCircuitBreakerFallbackException = + Arrays.asList(CallNotPermittedException.class); + + protected final MultiClusterPooledConnectionProvider provider; + + public CircuitBreakerFailoverBase(MultiClusterPooledConnectionProvider provider) { + this.provider = provider; + } + + @Override + public void close() { + IOUtils.closeQuietly(this.provider); + } + + /** + * Functional interface wrapped in retry and circuit breaker logic to handle open circuit breaker failure scenarios + */ + protected synchronized void clusterFailover(CircuitBreaker circuitBreaker) { + + // Check state to handle race conditions since incrementActiveMultiClusterIndex() is non-idempotent + if (!CircuitBreaker.State.FORCED_OPEN.equals(circuitBreaker.getState())) { + + // Transitions state machine to a FORCED_OPEN state, stopping state transition, metrics and event publishing. + // To recover/transition from this forced state the user will need to manually failback + circuitBreaker.transitionToForcedOpenState(); + + // Incrementing the activeMultiClusterIndex will allow subsequent calls to the executeCommand() + // to use the next cluster's connection pool - according to the configuration's prioritization/order + int activeMultiClusterIndex = provider.incrementActiveMultiClusterIndex(); + + // Implementation is optionally provided during configuration. Typically, used for activeMultiClusterIndex persistence or custom logging + provider.runClusterFailoverPostProcessor(activeMultiClusterIndex); + } + + // Once the priority list is exhausted only a manual failback can open the circuit breaker so all subsequent operations will fail + else if (provider.isLastClusterCircuitBreakerForcedOpen()) { + throw new JedisConnectionException("Cluster/database endpoint could not failover since the MultiClusterClientConfig was not " + + "provided with an additional cluster/database endpoint according to its prioritized sequence. " + + "If applicable, consider failing back OR restarting with an available cluster/database endpoint"); + } + } + +} \ No newline at end of file diff --git a/src/main/java/redis/clients/jedis/mcf/CircuitBreakerFailoverConnectionProvider.java b/src/main/java/redis/clients/jedis/mcf/CircuitBreakerFailoverConnectionProvider.java new file mode 100644 index 0000000000..dad2c751c8 --- /dev/null +++ b/src/main/java/redis/clients/jedis/mcf/CircuitBreakerFailoverConnectionProvider.java @@ -0,0 +1,55 @@ +package redis.clients.jedis.mcf; + +import io.github.resilience4j.circuitbreaker.CircuitBreaker; +import io.github.resilience4j.decorators.Decorators; +import io.github.resilience4j.decorators.Decorators.DecorateSupplier; + +import redis.clients.jedis.Connection; +import redis.clients.jedis.providers.MultiClusterPooledConnectionProvider; +import redis.clients.jedis.providers.MultiClusterPooledConnectionProvider.Cluster; + +/** + * ConnectionProvider with built-in retry, circuit-breaker, and failover to another cluster/database endpoint. + * With this executor users can seamlessly failover to Disaster Recovery (DR), Backup, and Active-Active cluster(s) + * by using simple configuration which is passed through from Resilience4j - https://resilience4j.readme.io/docs + */ +public class CircuitBreakerFailoverConnectionProvider extends CircuitBreakerFailoverBase { + + public CircuitBreakerFailoverConnectionProvider(MultiClusterPooledConnectionProvider provider) { + super(provider); + } + + public Connection getConnection() { + Cluster cluster = provider.getCluster(); // Pass this by reference for thread safety + + DecorateSupplier supplier = Decorators.ofSupplier(() -> this.handleGetConnection(cluster)); + + supplier.withRetry(cluster.getRetry()); + supplier.withCircuitBreaker(cluster.getCircuitBreaker()); + supplier.withFallback(defaultCircuitBreakerFallbackException, + e -> this.handleClusterFailover(cluster.getCircuitBreaker())); + + return supplier.decorate().get(); + } + + /** + * Functional interface wrapped in retry and circuit breaker logic to handle happy path scenarios + */ + private Connection handleGetConnection(Cluster cluster) { + Connection connection = cluster.getConnection(); + connection.ping(); + return connection; + } + + /** + * Functional interface wrapped in retry and circuit breaker logic to handle open circuit breaker failure scenarios + */ + private Connection handleClusterFailover(CircuitBreaker circuitBreaker) { + + clusterFailover(circuitBreaker); + + // Recursive call to the initiating method so the operation can be retried on the next cluster connection + return getConnection(); + } + +} \ No newline at end of file diff --git a/src/main/java/redis/clients/jedis/mcf/MultiClusterPipeline.java b/src/main/java/redis/clients/jedis/mcf/MultiClusterPipeline.java new file mode 100644 index 0000000000..94f686c2d7 --- /dev/null +++ b/src/main/java/redis/clients/jedis/mcf/MultiClusterPipeline.java @@ -0,0 +1,124 @@ +package redis.clients.jedis.mcf; + +import java.io.Closeable; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; + +import redis.clients.jedis.*; +import redis.clients.jedis.graph.ResultSet; +import redis.clients.jedis.providers.MultiClusterPooledConnectionProvider; +import redis.clients.jedis.util.KeyValue; + +/** + * This is high memory dependent solution as all the appending commands will be hold in memory until + * {@link MultiClusterPipeline#sync() SYNC} (or {@link MultiClusterPipeline#close() CLOSE}) gets called. + */ +public class MultiClusterPipeline extends PipelineBase implements Closeable { + + private final CircuitBreakerFailoverConnectionProvider failoverProvider; + private final Queue>> commands = new LinkedList<>(); + + public MultiClusterPipeline(MultiClusterPooledConnectionProvider pooledProvider) { + super(new CommandObjects()); + try (Connection connection = pooledProvider.getConnection()) { // we don't need a healthy connection now + RedisProtocol proto = connection.getRedisProtocol(); + if (proto != null) this.commandObjects.setProtocol(proto); + } + + this.failoverProvider = new CircuitBreakerFailoverConnectionProvider(pooledProvider); + } + + @Override + protected final Response appendCommand(CommandObject commandObject) { + CommandArguments args = commandObject.getArguments(); + Response response = new Response<>(commandObject.getBuilder()); + commands.add(KeyValue.of(args, response)); + return response; + } + + @Override + public void close() { + sync(); + // connection prepared and closed (in try-with-resources) in sync() + } + + /** + * Synchronize pipeline by reading all responses. This operation close the pipeline. In order to get return values + * from pipelined commands, capture the different Response<?> of the commands you execute. + */ + @Override + public void sync() { + if (commands.isEmpty()) return; + + try (Connection connection = failoverProvider.getConnection()) { + + commands.forEach((command) -> connection.sendCommand(command.getKey())); + // following connection.getMany(int) flushes anyway, so no flush here. + + List unformatted = connection.getMany(commands.size()); + unformatted.forEach((rawReply) -> commands.poll().getValue().set(rawReply)); + } + } + + public Response waitReplicas(int replicas, long timeout) { + return appendCommand(commandObjects.waitReplicas(replicas, timeout)); + } + + public Response> waitAOF(long numLocal, long numReplicas, long timeout) { + return appendCommand(commandObjects.waitAOF(numLocal, numReplicas, timeout)); + } + + // RedisGraph commands + @Override + public Response graphQuery(String name, String query) { + throw new UnsupportedOperationException("Graph commands are not supported."); + } + + @Override + public Response graphReadonlyQuery(String name, String query) { + throw new UnsupportedOperationException("Graph commands are not supported."); + } + + @Override + public Response graphQuery(String name, String query, long timeout) { + throw new UnsupportedOperationException("Graph commands are not supported."); + } + + @Override + public Response graphReadonlyQuery(String name, String query, long timeout) { + throw new UnsupportedOperationException("Graph commands are not supported."); + } + + @Override + public Response graphQuery(String name, String query, Map params) { + throw new UnsupportedOperationException("Graph commands are not supported."); + } + + @Override + public Response graphReadonlyQuery(String name, String query, Map params) { + throw new UnsupportedOperationException("Graph commands are not supported."); + } + + @Override + public Response graphQuery(String name, String query, Map params, long timeout) { + throw new UnsupportedOperationException("Graph commands are not supported."); + } + + @Override + public Response graphReadonlyQuery(String name, String query, Map params, long timeout) { + throw new UnsupportedOperationException("Graph commands are not supported."); + } + + @Override + public Response graphDelete(String name) { + throw new UnsupportedOperationException("Graph commands are not supported."); + } + + @Override + public Response> graphProfile(String graphName, String query) { + throw new UnsupportedOperationException("Graph commands are not supported."); + } + // RedisGraph commands +} diff --git a/src/main/java/redis/clients/jedis/mcf/MultiClusterTransaction.java b/src/main/java/redis/clients/jedis/mcf/MultiClusterTransaction.java new file mode 100644 index 0000000000..5ce9ecd9b5 --- /dev/null +++ b/src/main/java/redis/clients/jedis/mcf/MultiClusterTransaction.java @@ -0,0 +1,245 @@ +package redis.clients.jedis.mcf; + +import static redis.clients.jedis.Protocol.Command.DISCARD; +import static redis.clients.jedis.Protocol.Command.EXEC; +import static redis.clients.jedis.Protocol.Command.MULTI; +import static redis.clients.jedis.Protocol.Command.UNWATCH; +import static redis.clients.jedis.Protocol.Command.WATCH; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.concurrent.atomic.AtomicInteger; + +import redis.clients.jedis.*; +import redis.clients.jedis.exceptions.JedisDataException; +import redis.clients.jedis.graph.ResultSet; +import redis.clients.jedis.providers.MultiClusterPooledConnectionProvider; +import redis.clients.jedis.util.KeyValue; + +/** + * This is high memory dependent solution as all the appending commands will be hold in memory. + */ +public class MultiClusterTransaction extends TransactionBase { + + private static final Builder NO_OP_BUILDER = BuilderFactory.RAW_OBJECT; + + private final CircuitBreakerFailoverConnectionProvider provider; + private final AtomicInteger extraCommandCount = new AtomicInteger(); + private final Queue>> commands = new LinkedList<>(); + + private boolean inWatch = false; + private boolean inMulti = false; + + /** + * A MULTI command will be added to be sent to server. WATCH/UNWATCH/MULTI commands must not be + * called with this object. + * @param provider + */ + public MultiClusterTransaction(MultiClusterPooledConnectionProvider provider) { + this(provider, true); + } + + /** + * A user wanting to WATCH/UNWATCH keys followed by a call to MULTI ({@link #multi()}) it should + * be {@code doMulti=false}. + * + * @param provider + * @param doMulti {@code false} should be set to enable manual WATCH, UNWATCH and MULTI + */ + public MultiClusterTransaction(MultiClusterPooledConnectionProvider provider, boolean doMulti) { + try (Connection connection = provider.getConnection()) { // we don't need a healthy connection now + RedisProtocol proto = connection.getRedisProtocol(); + if (proto != null) this.commandObjects.setProtocol(proto); + } + + this.provider = new CircuitBreakerFailoverConnectionProvider(provider); + + if (doMulti) multi(); + } + + @Override + public final void multi() { + appendCommand(new CommandObject<>(new CommandArguments(MULTI), NO_OP_BUILDER)); + extraCommandCount.incrementAndGet(); + inMulti = true; + } + + /** + * @param keys + * @return {@code null} + */ + @Override + public final String watch(String... keys) { + appendCommand(new CommandObject<>(new CommandArguments(WATCH).addObjects((Object[]) keys), NO_OP_BUILDER)); + extraCommandCount.incrementAndGet(); + inWatch = true; + return null; + } + + /** + * @param keys + * @return {@code null} + */ + @Override + public final String watch(byte[]... keys) { + appendCommand(new CommandObject<>(new CommandArguments(WATCH).addObjects((Object[]) keys), NO_OP_BUILDER)); + extraCommandCount.incrementAndGet(); + inWatch = true; + return null; + } + + /** + * @return {@code null} + */ + @Override + public final String unwatch() { + appendCommand(new CommandObject<>(new CommandArguments(UNWATCH), NO_OP_BUILDER)); + extraCommandCount.incrementAndGet(); + inWatch = false; + return null; + } + + @Override + protected final Response appendCommand(CommandObject commandObject) { + CommandArguments args = commandObject.getArguments(); + Response response = new Response<>(commandObject.getBuilder()); + commands.add(KeyValue.of(args, response)); + return response; + } + + @Override + public void close() { + clear(); + } + + private void clear() { + if (inMulti) { + discard(); + } else if (inWatch) { + unwatch(); + } + } + + @Override + public final List exec() { + if (!inMulti) { + throw new IllegalStateException("EXEC without MULTI"); + } + + try (Connection connection = provider.getConnection()) { + + commands.forEach((command) -> connection.sendCommand(command.getKey())); + // following connection.getMany(int) flushes anyway, so no flush here. + + // ignore QUEUED (or ERROR) + connection.getMany(commands.size()); + + // remove extra response builders + for (int idx = 0; idx < extraCommandCount.get(); ++idx) { + commands.poll(); + } + + connection.sendCommand(EXEC); + + List unformatted = connection.getObjectMultiBulkReply(); + if (unformatted == null) { + commands.clear(); + return null; + } + + List formatted = new ArrayList<>(unformatted.size() - extraCommandCount.get()); + for (Object rawReply: unformatted) { + try { + Response response = commands.poll().getValue(); + response.set(rawReply); + formatted.add(response.get()); + } catch (JedisDataException e) { + formatted.add(e); + } + } + return formatted; + + } finally { + inMulti = false; + inWatch = false; + } + } + + @Override + public final String discard() { + if (!inMulti) { + throw new IllegalStateException("DISCARD without MULTI"); + } + + try (Connection connection = provider.getConnection()) { + + commands.forEach((command) -> connection.sendCommand(command.getKey())); + // following connection.getMany(int) flushes anyway, so no flush here. + + // ignore QUEUED (or ERROR) + connection.getMany(commands.size()); + + connection.sendCommand(DISCARD); + + return connection.getStatusCodeReply(); + } finally { + inMulti = false; + inWatch = false; + } + } + + // RedisGraph commands + @Override + public Response graphQuery(String name, String query) { + throw new UnsupportedOperationException("Graph commands are not supported."); + } + + @Override + public Response graphReadonlyQuery(String name, String query) { + throw new UnsupportedOperationException("Graph commands are not supported."); + } + + @Override + public Response graphQuery(String name, String query, long timeout) { + throw new UnsupportedOperationException("Graph commands are not supported."); + } + + @Override + public Response graphReadonlyQuery(String name, String query, long timeout) { + throw new UnsupportedOperationException("Graph commands are not supported."); + } + + @Override + public Response graphQuery(String name, String query, Map params) { + throw new UnsupportedOperationException("Graph commands are not supported."); + } + + @Override + public Response graphReadonlyQuery(String name, String query, Map params) { + throw new UnsupportedOperationException("Graph commands are not supported."); + } + + @Override + public Response graphQuery(String name, String query, Map params, long timeout) { + throw new UnsupportedOperationException("Graph commands are not supported."); + } + + @Override + public Response graphReadonlyQuery(String name, String query, Map params, long timeout) { + throw new UnsupportedOperationException("Graph commands are not supported."); + } + + @Override + public Response graphDelete(String name) { + throw new UnsupportedOperationException("Graph commands are not supported."); + } + + @Override + public Response> graphProfile(String graphName, String query) { + throw new UnsupportedOperationException("Graph commands are not supported."); + } + // RedisGraph commands +} diff --git a/src/main/java/redis/clients/jedis/mcf/package-info.java b/src/main/java/redis/clients/jedis/mcf/package-info.java new file mode 100644 index 0000000000..6b89d9c77b --- /dev/null +++ b/src/main/java/redis/clients/jedis/mcf/package-info.java @@ -0,0 +1,4 @@ +/** + * This package contains the classes that are related to Active-Active cluster(s) and Multi-Cluster failover. + */ +package redis.clients.jedis.mcf; diff --git a/src/main/java/redis/clients/jedis/params/BitPosParams.java b/src/main/java/redis/clients/jedis/params/BitPosParams.java index 6771626925..dc9d3ceea1 100644 --- a/src/main/java/redis/clients/jedis/params/BitPosParams.java +++ b/src/main/java/redis/clients/jedis/params/BitPosParams.java @@ -33,11 +33,18 @@ public BitPosParams start(long start) { return this; } + /** + * {@link BitPosParams#start(long) START} must be set for END option. + */ public BitPosParams end(long end) { this.end = end; return this; } + /** + * Both {@link BitPosParams#start(long) START} and {@link BitPosParams#end(long) END} both must be + * set for MODIFIER option. + */ public BitPosParams modifier(BitCountOption modifier) { this.modifier = modifier; return this; diff --git a/src/main/java/redis/clients/jedis/params/ClientKillParams.java b/src/main/java/redis/clients/jedis/params/ClientKillParams.java index 6ffbdd6977..12c65be882 100644 --- a/src/main/java/redis/clients/jedis/params/ClientKillParams.java +++ b/src/main/java/redis/clients/jedis/params/ClientKillParams.java @@ -1,20 +1,20 @@ package redis.clients.jedis.params; -import redis.clients.jedis.args.ClientType; +import java.util.ArrayList; -public class ClientKillParams extends Params { +import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.Protocol.Keyword; +import redis.clients.jedis.args.ClientType; +import redis.clients.jedis.util.KeyValue; - private static final String ID = "ID"; - private static final String TYPE = "TYPE"; - private static final String ADDR = "ADDR"; - private static final String SKIPME = "SKIPME"; - private static final String USER = "USER"; - private static final String LADDR = "LADDR"; +public class ClientKillParams implements IParams { public static enum SkipMe { YES, NO; } + private final ArrayList> params = new ArrayList<>(); + public ClientKillParams() { } @@ -22,53 +22,53 @@ public static ClientKillParams clientKillParams() { return new ClientKillParams(); } - public ClientKillParams id(String clientId) { - addParam(ID, clientId); + private ClientKillParams addParam(Keyword key, Object value) { + params.add(KeyValue.of(key, value)); return this; } + public ClientKillParams id(String clientId) { + return addParam(Keyword.ID, clientId); + } + public ClientKillParams id(byte[] clientId) { - addParam(ID, clientId); - return this; + return addParam(Keyword.ID, clientId); } public ClientKillParams type(ClientType type) { - addParam(TYPE, type); - return this; + return addParam(Keyword.TYPE, type); } public ClientKillParams addr(String ipPort) { - addParam(ADDR, ipPort); - return this; + return addParam(Keyword.ADDR, ipPort); } public ClientKillParams addr(byte[] ipPort) { - addParam(ADDR, ipPort); - return this; + return addParam(Keyword.ADDR, ipPort); } public ClientKillParams addr(String ip, int port) { - addParam(ADDR, ip + ':' + port); - return this; + return addParam(Keyword.ADDR, ip + ':' + port); } public ClientKillParams skipMe(SkipMe skipMe) { - addParam(SKIPME, skipMe); - return this; + return addParam(Keyword.SKIPME, skipMe); } public ClientKillParams user(String username) { - addParam(USER, username); - return this; + return addParam(Keyword.USER, username); } public ClientKillParams laddr(String ipPort) { - addParam(LADDR, ipPort); - return this; + return addParam(Keyword.LADDR, ipPort); } public ClientKillParams laddr(String ip, int port) { - addParam(LADDR, ip + ':' + port); - return this; + return addParam(Keyword.LADDR, ip + ':' + port); + } + + @Override + public void addParams(CommandArguments args) { + params.forEach(kv -> args.add(kv.getKey()).add(kv.getValue())); } } diff --git a/src/main/java/redis/clients/jedis/params/CommandListFilterByParams.java b/src/main/java/redis/clients/jedis/params/CommandListFilterByParams.java index 2cdee1799a..cce880fada 100644 --- a/src/main/java/redis/clients/jedis/params/CommandListFilterByParams.java +++ b/src/main/java/redis/clients/jedis/params/CommandListFilterByParams.java @@ -1,14 +1,10 @@ package redis.clients.jedis.params; import redis.clients.jedis.CommandArguments; -import redis.clients.jedis.exceptions.JedisDataException; - -import static redis.clients.jedis.Protocol.Keyword.FILTERBY; -import static redis.clients.jedis.Protocol.Keyword.MODULE; -import static redis.clients.jedis.Protocol.Keyword.ACLCAT; -import static redis.clients.jedis.Protocol.Keyword.PATTERN; +import redis.clients.jedis.Protocol.Keyword; public class CommandListFilterByParams implements IParams { + private String moduleName; private String category; private String pattern; @@ -34,19 +30,20 @@ public CommandListFilterByParams filterByPattern(String pattern) { @Override public void addParams(CommandArguments args) { - args.add(FILTERBY); + args.add(Keyword.FILTERBY); if (moduleName != null && category == null && pattern == null) { - args.add(MODULE); + args.add(Keyword.MODULE); args.add(moduleName); } else if (moduleName == null && category != null && pattern == null) { - args.add(ACLCAT); + args.add(Keyword.ACLCAT); args.add(category); } else if (moduleName == null && category == null && pattern != null) { - args.add(PATTERN); + args.add(Keyword.PATTERN); args.add(pattern); } else { - throw new JedisDataException("Must choose exactly one filter"); + throw new IllegalArgumentException("Must choose exactly one filter in " + + getClass().getSimpleName()); } } } diff --git a/src/main/java/redis/clients/jedis/params/FailoverParams.java b/src/main/java/redis/clients/jedis/params/FailoverParams.java index 266fd1da3f..d1afbe368c 100644 --- a/src/main/java/redis/clients/jedis/params/FailoverParams.java +++ b/src/main/java/redis/clients/jedis/params/FailoverParams.java @@ -1,12 +1,8 @@ package redis.clients.jedis.params; -import static redis.clients.jedis.Protocol.Keyword.FORCE; -import static redis.clients.jedis.Protocol.Keyword.TIMEOUT; -import static redis.clients.jedis.Protocol.Keyword.TO; -import static redis.clients.jedis.Protocol.toByteArray; - import redis.clients.jedis.CommandArguments; import redis.clients.jedis.HostAndPort; +import redis.clients.jedis.Protocol.Keyword; public class FailoverParams implements IParams { @@ -30,7 +26,9 @@ public FailoverParams to(HostAndPort to) { } /** - * WARNING: FORCE option can be used only if both TO and TIMEOUT options are specified. + * Both TO ({@link FailoverParams#to(redis.clients.jedis.HostAndPort)} or + * {@link FailoverParams#to(java.lang.String, int)}) and + * {@link FailoverParams#timeout(long) TIMEOUT} must be set in order for FORCE option. */ public FailoverParams force() { this.force = true; @@ -46,19 +44,18 @@ public FailoverParams timeout(long timeout) { public void addParams(CommandArguments args) { if (to != null) { - args.add(TO); - args.add(to.getHost()).add(toByteArray(to.getPort())); + args.add(Keyword.TO).add(to.getHost()).add(to.getPort()); } if (force) { if (to == null || timeout == null) { - throw new IllegalStateException("ERR FAILOVER with force option requires both a timeout and target HOST and IP."); + throw new IllegalArgumentException("FAILOVER with force option requires both a timeout and target HOST and IP."); } - args.add(FORCE); + args.add(Keyword.FORCE); } if (timeout != null) { - args.add(TIMEOUT).add(toByteArray(timeout)); + args.add(Keyword.TIMEOUT).add(timeout); } } diff --git a/src/main/java/redis/clients/jedis/params/GeoAddParams.java b/src/main/java/redis/clients/jedis/params/GeoAddParams.java index 920d986d26..6dbcf99b94 100644 --- a/src/main/java/redis/clients/jedis/params/GeoAddParams.java +++ b/src/main/java/redis/clients/jedis/params/GeoAddParams.java @@ -1,10 +1,7 @@ package redis.clients.jedis.params; -import static redis.clients.jedis.Protocol.Keyword.CH; -import static redis.clients.jedis.Protocol.Keyword.NX; -import static redis.clients.jedis.Protocol.Keyword.XX; - import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.Protocol.Keyword; public class GeoAddParams implements IParams { @@ -50,13 +47,13 @@ public GeoAddParams ch() { @Override public void addParams(CommandArguments args) { if (nx) { - args.add(NX); + args.add(Keyword.NX); } else if (xx) { - args.add(XX); + args.add(Keyword.XX); } if (ch) { - args.add(CH); + args.add(Keyword.CH); } } diff --git a/src/main/java/redis/clients/jedis/params/GeoRadiusParam.java b/src/main/java/redis/clients/jedis/params/GeoRadiusParam.java index 7d484f07e8..113624af93 100644 --- a/src/main/java/redis/clients/jedis/params/GeoRadiusParam.java +++ b/src/main/java/redis/clients/jedis/params/GeoRadiusParam.java @@ -1,12 +1,7 @@ package redis.clients.jedis.params; -import static redis.clients.jedis.Protocol.Keyword.COUNT; -import static redis.clients.jedis.Protocol.Keyword.WITHCOORD; -import static redis.clients.jedis.Protocol.Keyword.WITHDIST; -import static redis.clients.jedis.Protocol.Keyword.WITHHASH; -import static redis.clients.jedis.Protocol.Keyword.ANY; - import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.Protocol.Keyword; import redis.clients.jedis.args.SortingOrder; public class GeoRadiusParam implements IParams { @@ -55,20 +50,21 @@ public GeoRadiusParam sortingOrder(SortingOrder order) { } public GeoRadiusParam count(int count) { - if (count > 0) { - this.count = count; - } + this.count = count; return this; } public GeoRadiusParam count(int count, boolean any) { - if (count > 0) { - this.count = count; + this.count = count; + this.any = any; + return this; + } - if (any) { - this.any = true; - } + public GeoRadiusParam any() { + if (this.count == null) { + throw new IllegalArgumentException("COUNT must be set before ANY to be set"); } + this.any = true; return this; } @@ -76,19 +72,19 @@ public GeoRadiusParam count(int count, boolean any) { public void addParams(CommandArguments args) { if (withCoord) { - args.add(WITHCOORD); + args.add(Keyword.WITHCOORD); } if (withDist) { - args.add(WITHDIST); + args.add(Keyword.WITHDIST); } if (withHash) { - args.add(WITHHASH); + args.add(Keyword.WITHHASH); } if (count != null) { - args.add(COUNT).add(count); + args.add(Keyword.COUNT).add(count); if (any) { - args.add(ANY); + args.add(Keyword.ANY); } } diff --git a/src/main/java/redis/clients/jedis/params/GeoRadiusStoreParam.java b/src/main/java/redis/clients/jedis/params/GeoRadiusStoreParam.java index fd1cec0681..6711fa9461 100644 --- a/src/main/java/redis/clients/jedis/params/GeoRadiusStoreParam.java +++ b/src/main/java/redis/clients/jedis/params/GeoRadiusStoreParam.java @@ -1,8 +1,7 @@ package redis.clients.jedis.params; import redis.clients.jedis.CommandArguments; -import static redis.clients.jedis.Protocol.Keyword.STORE; -import static redis.clients.jedis.Protocol.Keyword.STOREDIST; +import redis.clients.jedis.Protocol.Keyword; public class GeoRadiusStoreParam implements IParams { @@ -17,6 +16,11 @@ public static GeoRadiusStoreParam geoRadiusStoreParam() { return new GeoRadiusStoreParam(); } + /** + * WARNING: In Redis, if STOREDIST exists, store will be ignored. + *

+ * Refer: https://github.com/antirez/redis/blob/6.0/src/geo.c#L649 + */ public GeoRadiusStoreParam store(String key) { if (key != null) { this.store = true; @@ -33,19 +37,12 @@ public GeoRadiusStoreParam storeDist(String key) { return this; } - /** - * WARNING: In Redis, if STOREDIST exists, store will be ignored. - *

- * Refer: https://github.com/antirez/redis/blob/6.0/src/geo.c#L649 - * - * @param args - */ @Override public void addParams(CommandArguments args) { if (storeDist) { - args.add(STOREDIST).key(key); + args.add(Keyword.STOREDIST).key(key); } else if (store) { - args.add(STORE).key(key); + args.add(Keyword.STORE).key(key); } else { throw new IllegalArgumentException(this.getClass().getSimpleName() + " must has store or storedist option"); diff --git a/src/main/java/redis/clients/jedis/params/GeoSearchParam.java b/src/main/java/redis/clients/jedis/params/GeoSearchParam.java index c7dd9263fc..9c12269c6b 100644 --- a/src/main/java/redis/clients/jedis/params/GeoSearchParam.java +++ b/src/main/java/redis/clients/jedis/params/GeoSearchParam.java @@ -1,17 +1,8 @@ package redis.clients.jedis.params; -import static redis.clients.jedis.Protocol.Keyword.ANY; -import static redis.clients.jedis.Protocol.Keyword.BYBOX; -import static redis.clients.jedis.Protocol.Keyword.BYRADIUS; -import static redis.clients.jedis.Protocol.Keyword.COUNT; -import static redis.clients.jedis.Protocol.Keyword.WITHCOORD; -import static redis.clients.jedis.Protocol.Keyword.WITHDIST; -import static redis.clients.jedis.Protocol.Keyword.WITHHASH; -import static redis.clients.jedis.Protocol.Keyword.FROMMEMBER; -import static redis.clients.jedis.Protocol.Keyword.FROMLONLAT; - -import redis.clients.jedis.GeoCoordinate; import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.GeoCoordinate; +import redis.clients.jedis.Protocol.Keyword; import redis.clients.jedis.args.GeoUnit; import redis.clients.jedis.args.SortingOrder; @@ -104,55 +95,53 @@ public GeoSearchParam sortingOrder(SortingOrder order) { } public GeoSearchParam count(int count) { - return this.count(count, false); + this.count = count; + return this; } public GeoSearchParam count(int count, boolean any) { - if (count > 0) { - this.count = count; + this.count = count; + this.any = true; + return this; + } - if (any) { - this.any = true; - } + public GeoSearchParam any() { + if (this.count == null) { + throw new IllegalArgumentException("COUNT must be set before ANY to be set"); } + this.any = true; return this; } @Override public void addParams(CommandArguments args) { if (this.fromMember) { - args.add(FROMMEMBER); - args.add(this.member); + args.add(Keyword.FROMMEMBER).add(this.member); } else if (this.fromLonLat) { - args.add(FROMLONLAT); - args.add(coord.getLongitude()); - args.add(coord.getLatitude()); + args.add(Keyword.FROMLONLAT).add(coord.getLongitude()).add(coord.getLatitude()); } if (this.byRadius) { - args.add(BYRADIUS); - args.add(this.radius); + args.add(Keyword.BYRADIUS).add(this.radius); } else if (this.byBox) { - args.add(BYBOX); - args.add(this.width); - args.add(this.height); + args.add(Keyword.BYBOX).add(this.width).add(this.height); } args.add(this.unit); if (withCoord) { - args.add(WITHCOORD); + args.add(Keyword.WITHCOORD); } if (withDist) { - args.add(WITHDIST); + args.add(Keyword.WITHDIST); } if (withHash) { - args.add(WITHHASH); + args.add(Keyword.WITHHASH); } if (count != null) { - args.add(COUNT).add(count); + args.add(Keyword.COUNT).add(count); if (any) { - args.add(ANY); + args.add(Keyword.ANY); } } diff --git a/src/main/java/redis/clients/jedis/params/GetExParams.java b/src/main/java/redis/clients/jedis/params/GetExParams.java index c985ff0a54..27c875e83a 100644 --- a/src/main/java/redis/clients/jedis/params/GetExParams.java +++ b/src/main/java/redis/clients/jedis/params/GetExParams.java @@ -1,16 +1,14 @@ package redis.clients.jedis.params; import redis.clients.jedis.CommandArguments; -import redis.clients.jedis.Protocol; -import redis.clients.jedis.util.SafeEncoder; +import redis.clients.jedis.Protocol.Keyword; -public class GetExParams extends Params implements IParams { +public class GetExParams implements IParams { - private static final String PX = "px"; - private static final String EX = "ex"; - private static final String EXAT = "exat"; - private static final String PXAT = "pxat"; - private static final String PERSIST = "persist"; + private Keyword expiration; + private Long expirationValue; + + private boolean persist; public GetExParams() { } @@ -19,13 +17,18 @@ public static GetExParams getExParams() { return new GetExParams(); } + private GetExParams expiration(Keyword type, Long value) { + this.expiration = type; + this.expirationValue = value; + return this; + } + /** * Set the specified expire time, in seconds. * @return GetExParams */ public GetExParams ex(long secondsToExpire) { - addParam(EX, secondsToExpire); - return this; + return expiration(Keyword.EX, secondsToExpire); } /** @@ -33,8 +36,7 @@ public GetExParams ex(long secondsToExpire) { * @return GetExParams */ public GetExParams px(long millisecondsToExpire) { - addParam(PX, millisecondsToExpire); - return this; + return expiration(Keyword.PX, millisecondsToExpire); } /** @@ -43,8 +45,7 @@ public GetExParams px(long millisecondsToExpire) { * @return GetExParams */ public GetExParams exAt(long seconds) { - addParam(EXAT, seconds); - return this; + return expiration(Keyword.EXAT, seconds); } /** @@ -53,8 +54,7 @@ public GetExParams exAt(long seconds) { * @return GetExParams */ public GetExParams pxAt(long milliseconds) { - addParam(PXAT, milliseconds); - return this; + return expiration(Keyword.PXAT, milliseconds); } /** @@ -62,27 +62,16 @@ public GetExParams pxAt(long milliseconds) { * @return GetExParams */ public GetExParams persist() { - addParam(PERSIST); - return this; + return expiration(Keyword.PERSIST, null); } @Override public void addParams(CommandArguments args) { - if (contains(EX)) { - args.add(SafeEncoder.encode(EX)); - args.add(Protocol.toByteArray((long) getParam(EX))); - } else if (contains(PX)) { - args.add(SafeEncoder.encode(PX)); - args.add(Protocol.toByteArray((long) getParam(PX))); - } else if (contains(EXAT)) { - args.add(SafeEncoder.encode(EXAT)); - args.add(Protocol.toByteArray((long) getParam(EXAT))); - } else if (contains(PXAT)) { - args.add(SafeEncoder.encode(PXAT)); - args.add(Protocol.toByteArray((long) getParam(PXAT))); - } else if (contains(PERSIST)) { - args.add(SafeEncoder.encode(PERSIST)); + if (expiration != null) { + args.add(expiration); + if (expirationValue != null) { + args.add(expirationValue); + } } } - } diff --git a/src/main/java/redis/clients/jedis/params/LCSParams.java b/src/main/java/redis/clients/jedis/params/LCSParams.java index d6b8cc3acb..be3152aefc 100644 --- a/src/main/java/redis/clients/jedis/params/LCSParams.java +++ b/src/main/java/redis/clients/jedis/params/LCSParams.java @@ -1,11 +1,7 @@ package redis.clients.jedis.params; import redis.clients.jedis.CommandArguments; - -import static redis.clients.jedis.Protocol.Keyword.IDX; -import static redis.clients.jedis.Protocol.Keyword.LEN; -import static redis.clients.jedis.Protocol.Keyword.MINMATCHLEN; -import static redis.clients.jedis.Protocol.Keyword.WITHMATCHLEN; +import redis.clients.jedis.Protocol.Keyword; public class LCSParams implements IParams { @@ -57,16 +53,16 @@ public LCSParams withMatchLen() { @Override public void addParams(CommandArguments args) { if (len) { - args.add(LEN); + args.add(Keyword.LEN); } if (idx) { - args.add(IDX); + args.add(Keyword.IDX); } if (minMatchLen != null) { - args.add(MINMATCHLEN).add(minMatchLen); + args.add(Keyword.MINMATCHLEN).add(minMatchLen); } if (withMatchLen) { - args.add(WITHMATCHLEN); + args.add(Keyword.WITHMATCHLEN); } } } diff --git a/src/main/java/redis/clients/jedis/params/LPosParams.java b/src/main/java/redis/clients/jedis/params/LPosParams.java index f1291a5781..257e97d1ba 100644 --- a/src/main/java/redis/clients/jedis/params/LPosParams.java +++ b/src/main/java/redis/clients/jedis/params/LPosParams.java @@ -1,37 +1,35 @@ package redis.clients.jedis.params; import redis.clients.jedis.CommandArguments; -import redis.clients.jedis.Protocol; +import redis.clients.jedis.Protocol.Keyword; -public class LPosParams extends Params implements IParams { - - private static final String RANK = "RANK"; - private static final String MAXLEN = "MAXLEN"; +public class LPosParams implements IParams { + private Integer rank; + private Integer maxlen; + public static LPosParams lPosParams() { return new LPosParams(); } public LPosParams rank(int rank) { - addParam(RANK, rank); + this.rank = rank; return this; } public LPosParams maxlen(int maxLen) { - addParam(MAXLEN, maxLen); + this.maxlen = maxLen; return this; } @Override public void addParams(CommandArguments args) { - if (contains(RANK)) { - args.add(RANK); - args.add(Protocol.toByteArray((int) getParam(RANK))); + if (rank != null) { + args.add(Keyword.RANK).add(rank); } - if (contains(MAXLEN)) { - args.add(MAXLEN); - args.add(Protocol.toByteArray((int) getParam(MAXLEN))); + if (maxlen != null) { + args.add(Keyword.MAXLEN).add(maxlen); } } diff --git a/src/main/java/redis/clients/jedis/params/LolwutParams.java b/src/main/java/redis/clients/jedis/params/LolwutParams.java index 375ea2e770..9b8c996793 100644 --- a/src/main/java/redis/clients/jedis/params/LolwutParams.java +++ b/src/main/java/redis/clients/jedis/params/LolwutParams.java @@ -1,31 +1,36 @@ package redis.clients.jedis.params; import redis.clients.jedis.CommandArguments; - +import redis.clients.jedis.Protocol.Keyword; public class LolwutParams implements IParams { - private int version; - private String[] args; + private Integer version; + private String[] opargs; public LolwutParams version(int version) { this.version = version; return this; } + @Deprecated public LolwutParams args(String... args) { - this.args = args; + return optionalArguments(args); + } + + public LolwutParams optionalArguments(String... args) { + this.opargs = args; return this; } @Override public void addParams(CommandArguments args) { - if (this.version != 0) { - args.add(this.version); - } + if (version != null) { + args.add(Keyword.VERSION).add(version); - if (this.args != null) { - args.add(this.args); + if (opargs != null && opargs.length > 0) { + args.addObjects((Object[]) opargs); + } } } } diff --git a/src/main/java/redis/clients/jedis/params/MigrateParams.java b/src/main/java/redis/clients/jedis/params/MigrateParams.java index b2f872c1f9..a75251e0e4 100644 --- a/src/main/java/redis/clients/jedis/params/MigrateParams.java +++ b/src/main/java/redis/clients/jedis/params/MigrateParams.java @@ -1,18 +1,14 @@ package redis.clients.jedis.params; -import static redis.clients.jedis.Protocol.Keyword.AUTH; -import static redis.clients.jedis.Protocol.Keyword.AUTH2; -import static redis.clients.jedis.Protocol.Keyword.COPY; -import static redis.clients.jedis.Protocol.Keyword.REPLACE; - import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.Protocol.Keyword; public class MigrateParams implements IParams { private boolean copy = false; private boolean replace = false; private String username = null; - private String passowrd = null; + private String password = null; public MigrateParams() { } @@ -32,28 +28,28 @@ public MigrateParams replace() { } public MigrateParams auth(String password) { - this.passowrd = password; + this.password = password; return this; } public MigrateParams auth2(String username, String password) { this.username = username; - this.passowrd = password; + this.password = password; return this; } @Override public void addParams(CommandArguments args) { if (copy) { - args.add(COPY); + args.add(Keyword.COPY); } if (replace) { - args.add(REPLACE); + args.add(Keyword.REPLACE); } if (username != null) { - args.add(AUTH2).add(username).add(passowrd); - } else if (passowrd != null) { - args.add(AUTH).add(passowrd); + args.add(Keyword.AUTH2).add(username).add(password); + } else if (password != null) { + args.add(Keyword.AUTH).add(password); } } } diff --git a/src/main/java/redis/clients/jedis/params/ModuleLoadExParams.java b/src/main/java/redis/clients/jedis/params/ModuleLoadExParams.java index a0d159eff1..9866d8f4dc 100644 --- a/src/main/java/redis/clients/jedis/params/ModuleLoadExParams.java +++ b/src/main/java/redis/clients/jedis/params/ModuleLoadExParams.java @@ -1,12 +1,10 @@ package redis.clients.jedis.params; -import static redis.clients.jedis.Protocol.Keyword.ARGS; -import static redis.clients.jedis.Protocol.Keyword.CONFIG; - import java.util.ArrayList; import java.util.List; import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.Protocol.Keyword; import redis.clients.jedis.util.KeyValue; public class ModuleLoadExParams implements IParams { @@ -34,10 +32,10 @@ public ModuleLoadExParams arg(String arg) { @Override public void addParams(CommandArguments args) { - this.configs.forEach(kv -> args.add(CONFIG).add(kv.getKey()).add(kv.getValue())); + this.configs.forEach(kv -> args.add(Keyword.CONFIG).add(kv.getKey()).add(kv.getValue())); if (!this.args.isEmpty()) { - args.add(ARGS).addObjects(this.args); + args.add(Keyword.ARGS).addObjects(this.args); } } } diff --git a/src/main/java/redis/clients/jedis/params/Params.java b/src/main/java/redis/clients/jedis/params/Params.java deleted file mode 100644 index d051bf0ea2..0000000000 --- a/src/main/java/redis/clients/jedis/params/Params.java +++ /dev/null @@ -1,87 +0,0 @@ -package redis.clients.jedis.params; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; - -import redis.clients.jedis.Protocol; -import redis.clients.jedis.args.Rawable; -import redis.clients.jedis.util.SafeEncoder; - -public abstract class Params { - - private Map params; - - @SuppressWarnings("unchecked") - public T getParam(String name) { - if (params == null) return null; - - return (T) params.get(name); - } - - public byte[][] getByteParams() { - if (params == null) return new byte[0][]; - ArrayList byteParams = new ArrayList<>(); - - for (Entry param : params.entrySet()) { - byteParams.add(SafeEncoder.encode(param.getKey())); - - Object value = param.getValue(); - if (value != null) { - if (value instanceof byte[]) { - byteParams.add((byte[]) value); - } else if (value instanceof Rawable) { - byteParams.add(((Rawable) value).getRaw()); - } else if (value instanceof Boolean) { - byteParams.add(Protocol.toByteArray((boolean) value)); - } else if (value instanceof Integer) { - byteParams.add(Protocol.toByteArray((int) value)); - } else if (value instanceof Long) { - byteParams.add(Protocol.toByteArray((long) value)); - } else if (value instanceof Double) { - byteParams.add(Protocol.toByteArray((double) value)); - } else { - byteParams.add(SafeEncoder.encode(String.valueOf(value))); - } - } - } - - return byteParams.toArray(new byte[byteParams.size()][]); - } - - protected boolean contains(String name) { - if (params == null) return false; - - return params.containsKey(name); - } - - protected void addParam(String name, Object value) { - if (params == null) { - params = new HashMap<>(); - } - params.put(name, value); - } - - protected void addParam(String name) { - if (params == null) { - params = new HashMap<>(); - } - params.put(name, null); - } - - @Override - public String toString() { - ArrayList paramsFlatList = new ArrayList<>(); - if (params != null) { - for (Entry param : params.entrySet()) { - paramsFlatList.add(param.getKey()); - Object value = param.getValue(); - if (value != null) { - paramsFlatList.add(SafeEncoder.encodeObject(value)); - } - } - } - return paramsFlatList.toString(); - } -} diff --git a/src/main/java/redis/clients/jedis/params/RestoreParams.java b/src/main/java/redis/clients/jedis/params/RestoreParams.java index 1acfc185d8..499bad7302 100644 --- a/src/main/java/redis/clients/jedis/params/RestoreParams.java +++ b/src/main/java/redis/clients/jedis/params/RestoreParams.java @@ -1,12 +1,7 @@ package redis.clients.jedis.params; -import static redis.clients.jedis.Protocol.Keyword.ABSTTL; -import static redis.clients.jedis.Protocol.Keyword.FREQ; -import static redis.clients.jedis.Protocol.Keyword.IDLETIME; -import static redis.clients.jedis.Protocol.Keyword.REPLACE; - import redis.clients.jedis.CommandArguments; -import redis.clients.jedis.Protocol; +import redis.clients.jedis.Protocol.Keyword; public class RestoreParams implements IParams { @@ -45,21 +40,19 @@ public RestoreParams frequency(long frequency) { @Override public void addParams(CommandArguments args) { if (replace) { - args.add(REPLACE.getRaw()); + args.add(Keyword.REPLACE); } if (absTtl) { - args.add(ABSTTL.getRaw()); + args.add(Keyword.ABSTTL); } if (idleTime != null) { - args.add(IDLETIME.getRaw()); - args.add(Protocol.toByteArray(idleTime)); + args.add(Keyword.IDLETIME).add(idleTime); } if (frequency != null) { - args.add(FREQ.getRaw()); - args.add(Protocol.toByteArray(frequency)); + args.add(Keyword.FREQ).add(frequency); } } } diff --git a/src/main/java/redis/clients/jedis/params/ScanParams.java b/src/main/java/redis/clients/jedis/params/ScanParams.java index 73c2b7e4e6..ad22a5778c 100644 --- a/src/main/java/redis/clients/jedis/params/ScanParams.java +++ b/src/main/java/redis/clients/jedis/params/ScanParams.java @@ -1,6 +1,5 @@ package redis.clients.jedis.params; -import static redis.clients.jedis.Protocol.Keyword.COUNT; import static redis.clients.jedis.Protocol.Keyword.MATCH; import java.nio.ByteBuffer; @@ -37,7 +36,7 @@ public ScanParams match(final String pattern) { * @see COUNT option in Redis documentation */ public ScanParams count(final Integer count) { - params.put(COUNT, ByteBuffer.wrap(Protocol.toByteArray(count))); + params.put(Keyword.COUNT, ByteBuffer.wrap(Protocol.toByteArray(count))); return this; } diff --git a/src/main/java/redis/clients/jedis/params/SetParams.java b/src/main/java/redis/clients/jedis/params/SetParams.java index 080c47f019..b0e4310327 100644 --- a/src/main/java/redis/clients/jedis/params/SetParams.java +++ b/src/main/java/redis/clients/jedis/params/SetParams.java @@ -1,19 +1,13 @@ package redis.clients.jedis.params; import redis.clients.jedis.CommandArguments; -import redis.clients.jedis.Protocol; import redis.clients.jedis.Protocol.Keyword; -public class SetParams extends Params implements IParams { +public class SetParams implements IParams { - private static final String XX = "xx"; - private static final String NX = "nx"; - private static final String PX = "px"; - private static final String EX = "ex"; - private static final String EXAT = "exat"; - private static final String PXAT = "pxat"; - private static final String KEEPTTL = "keepttl"; - private static final String GET = "get"; + private Keyword existance; + private Keyword expiration; + private Long expirationValue; public SetParams() { } @@ -23,115 +17,93 @@ public static SetParams setParams() { } /** - * Set the specified expire time, in seconds. - * @param secondsToExpire + * Only set the key if it does not already exist. * @return SetParams */ - public SetParams ex(long secondsToExpire) { - addParam(EX, secondsToExpire); + public SetParams nx() { + this.existance = Keyword.NX; return this; } /** - * Set the specified expire time, in milliseconds. - * @param millisecondsToExpire + * Only set the key if it already exist. * @return SetParams */ - public SetParams px(long millisecondsToExpire) { - addParam(PX, millisecondsToExpire); + public SetParams xx() { + this.existance = Keyword.XX; + return this; + } + + private SetParams expiration(Keyword type, Long value) { + this.expiration = type; + this.expirationValue = value; return this; } /** - * Only set the key if it does not already exist. + * Set the specified expire time, in seconds. + * @param remainingSeconds * @return SetParams */ - public SetParams nx() { - addParam(NX); - return this; + public SetParams ex(long remainingSeconds) { + return expiration(Keyword.EX, remainingSeconds); } /** - * Only set the key if it already exist. + * Set the specified expire time, in milliseconds. + * @param remainingMilliseconds * @return SetParams */ - public SetParams xx() { - addParam(XX); - return this; + public SetParams px(long remainingMilliseconds) { + return expiration(Keyword.PX, remainingMilliseconds); } /** * Set the specified Unix time at which the key will expire, in seconds. - * @param seconds + * @param timestampSeconds * @return SetParams */ - public SetParams exAt(long seconds) { - addParam(EXAT, seconds); - return this; + public SetParams exAt(long timestampSeconds) { + return expiration(Keyword.EXAT, timestampSeconds); } /** * Set the specified Unix time at which the key will expire, in milliseconds. - * @param milliseconds + * @param timestampMilliseconds * @return SetParams */ - public SetParams pxAt(long milliseconds) { - addParam(PXAT, milliseconds); - return this; + public SetParams pxAt(long timestampMilliseconds) { + return expiration(Keyword.PXAT, timestampMilliseconds); } /** * Retain the time to live associated with the key. * @return SetParams */ + // TODO: deprecate? public SetParams keepttl() { - addParam(KEEPTTL); - return this; + return keepTtl(); } /** - * Return the old value stored at key, or nil when key did not exist. + * Retain the time to live associated with the key. * @return SetParams - * @deprecated Use {@code setGet} method (without setting {@link SetParams#get()}. */ - @Deprecated - public SetParams get() { - addParam(GET); - return this; + public SetParams keepTtl() { + return expiration(Keyword.KEEPTTL, null); } @Override public void addParams(CommandArguments args) { - if (contains(NX)) { - args.add(Keyword.NX); - } - if (contains(XX)) { - args.add(Keyword.XX); + if (existance != null) { + args.add(existance); } - if (contains(EX)) { - args.add(Keyword.EX); - args.add(Protocol.toByteArray((long) getParam(EX))); - } - if (contains(PX)) { - args.add(Keyword.PX); - args.add(Protocol.toByteArray((long) getParam(PX))); - } - if (contains(EXAT)) { - args.add(Keyword.EXAT); - args.add(Protocol.toByteArray((long) getParam(EXAT))); - } - if (contains(PXAT)) { - args.add(Keyword.PXAT); - args.add(Protocol.toByteArray((long) getParam(PXAT))); - } - if (contains(KEEPTTL)) { - args.add(Keyword.KEEPTTL); - } - - if (contains(GET)) { - args.add(Keyword.GET); + if (expiration != null) { + args.add(expiration); + if (expirationValue != null) { + args.add(expirationValue); + } } } - } diff --git a/src/main/java/redis/clients/jedis/params/ShutdownParams.java b/src/main/java/redis/clients/jedis/params/ShutdownParams.java index 8072a033da..0c35943abe 100644 --- a/src/main/java/redis/clients/jedis/params/ShutdownParams.java +++ b/src/main/java/redis/clients/jedis/params/ShutdownParams.java @@ -1,9 +1,8 @@ package redis.clients.jedis.params; import redis.clients.jedis.CommandArguments; -import redis.clients.jedis.Protocol; +import redis.clients.jedis.Protocol.Keyword; import redis.clients.jedis.args.SaveMode; -import redis.clients.jedis.util.SafeEncoder; public class ShutdownParams implements IParams { @@ -40,17 +39,14 @@ public ShutdownParams force() { @Override public void addParams(CommandArguments args) { - if (this.saveMode != null) { - args.add(SafeEncoder.encode(saveMode.getRaw())); + args.add(saveMode); } - if (this.now) { - args.add(Protocol.Keyword.NOW.getRaw()); + args.add(Keyword.NOW); } - if (this.force) { - args.add(Protocol.Keyword.FORCE.getRaw()); + args.add(Keyword.FORCE); } } } diff --git a/src/main/java/redis/clients/jedis/params/SortingParams.java b/src/main/java/redis/clients/jedis/params/SortingParams.java index 07130f578b..6762acf301 100644 --- a/src/main/java/redis/clients/jedis/params/SortingParams.java +++ b/src/main/java/redis/clients/jedis/params/SortingParams.java @@ -1,11 +1,5 @@ package redis.clients.jedis.params; -import static redis.clients.jedis.Protocol.Keyword.ALPHA; -import static redis.clients.jedis.Protocol.Keyword.BY; -import static redis.clients.jedis.Protocol.Keyword.GET; -import static redis.clients.jedis.Protocol.Keyword.LIMIT; -import static redis.clients.jedis.Protocol.Keyword.NOSORT; - import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -13,15 +7,17 @@ import redis.clients.jedis.CommandArguments; import redis.clients.jedis.Protocol; +import redis.clients.jedis.Protocol.Keyword; import redis.clients.jedis.args.SortingOrder; import redis.clients.jedis.util.SafeEncoder; /** * Builder Class for {@code SORT} command parameters. */ +// TODO: public class SortingParams implements IParams { - private final List params = new ArrayList<>(); + private final List params = new ArrayList<>(); /** * Sort by weight in keys. @@ -52,7 +48,7 @@ public SortingParams by(final String pattern) { * @return the SortingParams Object */ public SortingParams by(final byte[] pattern) { - params.add(BY.getRaw()); + params.add(Keyword.BY); params.add(pattern); return this; } @@ -65,15 +61,11 @@ public SortingParams by(final byte[] pattern) { * @return the SortingParams Object */ public SortingParams nosort() { - params.add(BY.getRaw()); - params.add(NOSORT.getRaw()); + params.add(Keyword.BY); + params.add(Keyword.NOSORT); return this; } - public Collection getParams() { - return Collections.unmodifiableCollection(params); - } - /** * Get the Sorting in Descending Order. * @return the sortingParams Object @@ -107,9 +99,9 @@ public SortingParams sortingOrder(SortingOrder order) { * @return the SortingParams Object */ public SortingParams limit(final int start, final int count) { - params.add(LIMIT.getRaw()); - params.add(Protocol.toByteArray(start)); - params.add(Protocol.toByteArray(count)); + params.add(Keyword.LIMIT); + params.add(start); + params.add(count); return this; } @@ -119,7 +111,7 @@ public SortingParams limit(final int start, final int count) { * @return the SortingParams Object */ public SortingParams alpha() { - params.add(ALPHA.getRaw()); + params.add(Keyword.ALPHA); return this; } @@ -139,8 +131,8 @@ public SortingParams alpha() { */ public SortingParams get(String... patterns) { for (final String pattern : patterns) { - params.add(GET.getRaw()); - params.add(SafeEncoder.encode(pattern)); + params.add(Keyword.GET); + params.add(pattern); } return this; } @@ -161,7 +153,7 @@ public SortingParams get(String... patterns) { */ public SortingParams get(byte[]... patterns) { for (final byte[] pattern : patterns) { - params.add(GET.getRaw()); + params.add(Keyword.GET); params.add(pattern); } return this; @@ -169,8 +161,6 @@ public SortingParams get(byte[]... patterns) { @Override public void addParams(CommandArguments args) { - for (byte[] param : params) { - args.add(param); - } + args.addObjects(params); } } diff --git a/src/main/java/redis/clients/jedis/params/StrAlgoLCSParams.java b/src/main/java/redis/clients/jedis/params/StrAlgoLCSParams.java deleted file mode 100644 index ad24a87bd3..0000000000 --- a/src/main/java/redis/clients/jedis/params/StrAlgoLCSParams.java +++ /dev/null @@ -1,75 +0,0 @@ -package redis.clients.jedis.params; - -import redis.clients.jedis.CommandArguments; -import redis.clients.jedis.Protocol; - -public class StrAlgoLCSParams extends Params implements IParams { - - private static final String IDX = "idx"; - private static final String LEN = "len"; - private static final String WITHMATCHLEN = "withmatchlen"; - private static final String MINMATCHLEN = "minmatchlen"; - - public StrAlgoLCSParams() { - } - - public static StrAlgoLCSParams StrAlgoLCSParams() { - return new StrAlgoLCSParams(); - } - - /** - * When IDX is given the command returns an array with the LCS length - * and all the ranges in both the strings, start and end offset for - * each string, where there are matches. - * @return StrAlgoParams - */ - public StrAlgoLCSParams idx() { - addParam(IDX); - return this; - } - - /** - * When LEN is given the command returns the length of the longest common substring. - * @return StrAlgoParams - */ - public StrAlgoLCSParams len() { - addParam(LEN); - return this; - } - - /** - * When WITHMATCHLEN is given each array representing a match will also have the length of the match. - * @return StrAlgoParams - */ - public StrAlgoLCSParams withMatchLen() { - addParam(WITHMATCHLEN); - return this; - } - - /** - * Specify the minimum match length. - * @return StrAlgoParams - */ - public StrAlgoLCSParams minMatchLen(long minMatchLen) { - addParam(MINMATCHLEN, minMatchLen); - return this; - } - - @Override - public void addParams(CommandArguments args) { - if (contains(IDX)) { - args.add(IDX); - } - if (contains(LEN)) { - args.add(LEN); - } - if (contains(WITHMATCHLEN)) { - args.add(WITHMATCHLEN); - } - - if (contains(MINMATCHLEN)) { - args.add(MINMATCHLEN); - args.add(Protocol.toByteArray((long) getParam(MINMATCHLEN))); - } - } -} diff --git a/src/main/java/redis/clients/jedis/params/XAddParams.java b/src/main/java/redis/clients/jedis/params/XAddParams.java index 310510ea34..8c8d09141d 100644 --- a/src/main/java/redis/clients/jedis/params/XAddParams.java +++ b/src/main/java/redis/clients/jedis/params/XAddParams.java @@ -1,21 +1,15 @@ package redis.clients.jedis.params; -import static redis.clients.jedis.Protocol.Keyword.LIMIT; -import static redis.clients.jedis.Protocol.Keyword.MAXLEN; -import static redis.clients.jedis.Protocol.Keyword.MINID; -import static redis.clients.jedis.Protocol.Keyword.NOMKSTREAM; -import static redis.clients.jedis.util.SafeEncoder.encode; - -import java.util.Arrays; import redis.clients.jedis.CommandArguments; import redis.clients.jedis.Protocol; +import redis.clients.jedis.Protocol.Keyword; import redis.clients.jedis.StreamEntryID; +import redis.clients.jedis.args.Rawable; +import redis.clients.jedis.args.RawableFactory; public class XAddParams implements IParams { - private static final byte[] NEW_ENTRY = encode(StreamEntryID.NEW_ENTRY.toString()); - - private byte[] id; + private Rawable id; private Long maxLen; @@ -39,12 +33,12 @@ public XAddParams noMkStream() { } public XAddParams id(byte[] id) { - this.id = Arrays.copyOf(id, id.length); + this.id = RawableFactory.from(id); return this; } public XAddParams id(String id) { - this.id = encode(id); + this.id = RawableFactory.from(id); return this; } @@ -89,11 +83,11 @@ public XAddParams limit(long limit) { public void addParams(CommandArguments args) { if (nomkstream) { - args.add(NOMKSTREAM.getRaw()); + args.add(Keyword.NOMKSTREAM); } if (maxLen != null) { - args.add(MAXLEN.getRaw()); + args.add(Keyword.MAXLEN); if (approximateTrimming) { args.add(Protocol.BYTES_TILDE); @@ -101,9 +95,9 @@ public void addParams(CommandArguments args) { args.add(Protocol.BYTES_EQUAL); } - args.add(Protocol.toByteArray(maxLen)); + args.add(maxLen); } else if (minId != null) { - args.add(MINID.getRaw()); + args.add(Keyword.MINID); if (approximateTrimming) { args.add(Protocol.BYTES_TILDE); @@ -111,14 +105,13 @@ public void addParams(CommandArguments args) { args.add(Protocol.BYTES_EQUAL); } - args.add(encode(minId)); + args.add(minId); } if (limit != null) { - args.add(LIMIT.getRaw()); - args.add(Protocol.toByteArray(limit)); + args.add(Keyword.LIMIT).add(limit); } - args.add(id != null ? id : NEW_ENTRY); + args.add(id != null ? id : StreamEntryID.NEW_ENTRY); } } diff --git a/src/main/java/redis/clients/jedis/params/XAutoClaimParams.java b/src/main/java/redis/clients/jedis/params/XAutoClaimParams.java index 6317cddb6d..ce20d8652d 100644 --- a/src/main/java/redis/clients/jedis/params/XAutoClaimParams.java +++ b/src/main/java/redis/clients/jedis/params/XAutoClaimParams.java @@ -1,8 +1,7 @@ package redis.clients.jedis.params; -import static redis.clients.jedis.Protocol.Keyword.COUNT; - import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.Protocol.Keyword; public class XAutoClaimParams implements IParams { @@ -28,7 +27,7 @@ public XAutoClaimParams count(int count) { @Override public void addParams(CommandArguments args) { if (count != null) { - args.add(COUNT.getRaw()).add(count); + args.add(Keyword.COUNT.getRaw()).add(count); } } diff --git a/src/main/java/redis/clients/jedis/params/XClaimParams.java b/src/main/java/redis/clients/jedis/params/XClaimParams.java index fb3e68f0f8..977e825ff2 100644 --- a/src/main/java/redis/clients/jedis/params/XClaimParams.java +++ b/src/main/java/redis/clients/jedis/params/XClaimParams.java @@ -1,11 +1,7 @@ package redis.clients.jedis.params; -import static redis.clients.jedis.Protocol.Keyword.IDLE; -import static redis.clients.jedis.Protocol.Keyword.TIME; -import static redis.clients.jedis.Protocol.Keyword.RETRYCOUNT; -import static redis.clients.jedis.Protocol.Keyword.FORCE; - import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.Protocol.Keyword; public class XClaimParams implements IParams { @@ -64,16 +60,16 @@ public XClaimParams force() { @Override public void addParams(CommandArguments args) { if (idleTime != null) { - args.add(IDLE).add(idleTime); + args.add(Keyword.IDLE).add(idleTime); } if (idleUnixTime != null) { - args.add(TIME).add(idleUnixTime); + args.add(Keyword.TIME).add(idleUnixTime); } if (retryCount != null) { - args.add(RETRYCOUNT).add(retryCount); + args.add(Keyword.RETRYCOUNT).add(retryCount); } if (force) { - args.add(FORCE); + args.add(Keyword.FORCE); } } } diff --git a/src/main/java/redis/clients/jedis/params/XPendingParams.java b/src/main/java/redis/clients/jedis/params/XPendingParams.java index 7ce3e687fd..5985ed3f7e 100644 --- a/src/main/java/redis/clients/jedis/params/XPendingParams.java +++ b/src/main/java/redis/clients/jedis/params/XPendingParams.java @@ -1,37 +1,20 @@ package redis.clients.jedis.params; -import static redis.clients.jedis.Protocol.Keyword.IDLE; -import static redis.clients.jedis.Protocol.toByteArray; import static redis.clients.jedis.args.RawableFactory.from; import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.Protocol.Keyword; import redis.clients.jedis.StreamEntryID; import redis.clients.jedis.args.Rawable; public class XPendingParams implements IParams { - private boolean legacy = true; private Long idle; - private Rawable start; // TODO: final - private Rawable end; // TODO: final - private int count = Integer.MIN_VALUE; // TODO: final + private Rawable start; + private Rawable end; + private Integer count; private Rawable consumer; - /** - * @deprecated Use {@link XPendingParams#XPendingParams(redis.clients.jedis.StreamEntryID, redis.clients.jedis.StreamEntryID, int)}. - */ - @Deprecated - public XPendingParams() { - } - - /** - * @deprecated Use {@link XPendingParams#xPendingParams(redis.clients.jedis.StreamEntryID, redis.clients.jedis.StreamEntryID, int)}. - */ - @Deprecated - public static XPendingParams xPendingParams() { - return new XPendingParams(); - } - public XPendingParams(StreamEntryID start, StreamEntryID end, int count) { this(start.toString(), end.toString(), count); } @@ -44,13 +27,18 @@ public XPendingParams(byte[] start, byte[] end, int count) { this(from(start), from(end), count); } - private XPendingParams(Rawable start, Rawable end, int count) { - this.legacy = false; + private XPendingParams(Rawable start, Rawable end, Integer count) { this.start = start; this.end = end; this.count = count; } + public XPendingParams() { + this.start = null; + this.end = null; + this.count = null; + } + public static XPendingParams xPendingParams(StreamEntryID start, StreamEntryID end, int count) { return new XPendingParams(start, end, count); } @@ -63,18 +51,20 @@ public static XPendingParams xPendingParams(byte[] start, byte[] end, int count) return new XPendingParams(start, end, count); } + public static XPendingParams xPendingParams() { + return new XPendingParams(); + } + public XPendingParams idle(long idle) { this.idle = idle; return this; } - @Deprecated public XPendingParams start(StreamEntryID start) { this.start = from(start.toString()); return this; } - @Deprecated public XPendingParams end(StreamEntryID end) { this.end = from(end.toString()); return this; @@ -97,30 +87,17 @@ public XPendingParams consumer(byte[] consumer) { @Override public void addParams(CommandArguments args) { + if (count == null) { + throw new IllegalArgumentException("start, end and count must be set."); + } + if (start == null) start = from("-"); + if (end == null) end = from("+"); if (idle != null) { - args.add(IDLE).add(toByteArray(idle)); + args.add(Keyword.IDLE).add(idle); } - if (legacy) { - if (start == null) { - args.add("-"); - } else { - args.add(start); - } - - if (end == null) { - args.add("+"); - } else { - args.add(end); - } - - if (count != Integer.MIN_VALUE) { - args.add(toByteArray(count)); - } - } else { - args.add(start).add(end).add(toByteArray(count)); - } + args.add(start).add(end).add(count); if (consumer != null) { args.add(consumer); diff --git a/src/main/java/redis/clients/jedis/params/XReadGroupParams.java b/src/main/java/redis/clients/jedis/params/XReadGroupParams.java index b53caa585b..07f878fb99 100644 --- a/src/main/java/redis/clients/jedis/params/XReadGroupParams.java +++ b/src/main/java/redis/clients/jedis/params/XReadGroupParams.java @@ -1,11 +1,7 @@ package redis.clients.jedis.params; -import static redis.clients.jedis.Protocol.Keyword.BLOCK; -import static redis.clients.jedis.Protocol.Keyword.COUNT; -import static redis.clients.jedis.Protocol.Keyword.NOACK; -import static redis.clients.jedis.Protocol.toByteArray; - import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.Protocol.Keyword; public class XReadGroupParams implements IParams { @@ -35,16 +31,13 @@ public XReadGroupParams noAck() { @Override public void addParams(CommandArguments args) { if (count != null) { - args.add(COUNT); - args.add(toByteArray(count)); + args.add(Keyword.COUNT).add(count); } if (block != null) { - args.add(BLOCK); - args.add(toByteArray(block)); - args.blocking(); + args.add(Keyword.BLOCK).add(block).blocking(); } if (noack) { - args.add(NOACK); + args.add(Keyword.NOACK); } } } diff --git a/src/main/java/redis/clients/jedis/params/XReadParams.java b/src/main/java/redis/clients/jedis/params/XReadParams.java index 9f587005b5..a64d3c1afa 100644 --- a/src/main/java/redis/clients/jedis/params/XReadParams.java +++ b/src/main/java/redis/clients/jedis/params/XReadParams.java @@ -1,10 +1,7 @@ package redis.clients.jedis.params; -import static redis.clients.jedis.Protocol.Keyword.BLOCK; -import static redis.clients.jedis.Protocol.Keyword.COUNT; -import static redis.clients.jedis.Protocol.toByteArray; - import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.Protocol.Keyword; public class XReadParams implements IParams { @@ -28,13 +25,10 @@ public XReadParams block(int block) { @Override public void addParams(CommandArguments args) { if (count != null) { - args.add(COUNT); - args.add(toByteArray(count)); + args.add(Keyword.COUNT).add(count); } if (block != null) { - args.add(BLOCK); - args.add(toByteArray(block)); - args.blocking(); + args.add(Keyword.BLOCK).add(block).blocking(); } } } diff --git a/src/main/java/redis/clients/jedis/params/XTrimParams.java b/src/main/java/redis/clients/jedis/params/XTrimParams.java index 27eb3c5b08..a7c7a05562 100644 --- a/src/main/java/redis/clients/jedis/params/XTrimParams.java +++ b/src/main/java/redis/clients/jedis/params/XTrimParams.java @@ -1,12 +1,8 @@ package redis.clients.jedis.params; -import static redis.clients.jedis.Protocol.Keyword.LIMIT; -import static redis.clients.jedis.Protocol.Keyword.MAXLEN; -import static redis.clients.jedis.Protocol.Keyword.MINID; - import redis.clients.jedis.CommandArguments; import redis.clients.jedis.Protocol; -import redis.clients.jedis.util.SafeEncoder; +import redis.clients.jedis.Protocol.Keyword; public class XTrimParams implements IParams { @@ -53,7 +49,7 @@ public XTrimParams limit(long limit) { @Override public void addParams(CommandArguments args) { if (maxLen != null) { - args.add(MAXLEN.getRaw()); + args.add(Keyword.MAXLEN); if (approximateTrimming) { args.add(Protocol.BYTES_TILDE); @@ -63,7 +59,7 @@ public void addParams(CommandArguments args) { args.add(Protocol.toByteArray(maxLen)); } else if (minId != null) { - args.add(MINID.getRaw()); + args.add(Keyword.MINID); if (approximateTrimming) { args.add(Protocol.BYTES_TILDE); @@ -71,12 +67,11 @@ public void addParams(CommandArguments args) { args.add(Protocol.BYTES_EQUAL); } - args.add(SafeEncoder.encode(minId)); + args.add(minId); } if (limit != null) { - args.add(LIMIT.getRaw()); - args.add(Protocol.toByteArray(limit)); + args.add(Keyword.LIMIT).add(limit); } } } diff --git a/src/main/java/redis/clients/jedis/params/ZAddParams.java b/src/main/java/redis/clients/jedis/params/ZAddParams.java index 2862c81e57..8194c041a6 100644 --- a/src/main/java/redis/clients/jedis/params/ZAddParams.java +++ b/src/main/java/redis/clients/jedis/params/ZAddParams.java @@ -1,14 +1,13 @@ package redis.clients.jedis.params; import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.Protocol.Keyword; -public class ZAddParams extends Params implements IParams { +public class ZAddParams implements IParams { - private static final String XX = "xx"; - private static final String NX = "nx"; - private static final String CH = "ch"; - private static final String LT = "lt"; - private static final String GT = "gt"; + private Keyword existence; + private Keyword comparison; + private boolean change; public ZAddParams() { } @@ -22,63 +21,57 @@ public static ZAddParams zAddParams() { * @return ZAddParams */ public ZAddParams nx() { - addParam(NX); + this.existence = Keyword.NX; return this; } /** - * Only set the key if it already exist. + * Only set the key if it already exists. * @return ZAddParams */ public ZAddParams xx() { - addParam(XX); + this.existence = Keyword.XX; return this; } /** - * Modify the return value from the number of new elements added to the total number of elements - * changed + * Only update existing elements if the new score is greater than the current score. * @return ZAddParams */ - public ZAddParams ch() { - addParam(CH); + public ZAddParams gt() { + this.comparison = Keyword.GT; return this; } /** - * Only update existing elements if the new score is greater than the current score. + * Only update existing elements if the new score is less than the current score. * @return ZAddParams */ - public ZAddParams gt() { - addParam(GT); + public ZAddParams lt() { + this.comparison = Keyword.LT; return this; } /** - * Only update existing elements if the new score is less than the current score. + * Modify the return value from the number of new elements added to the total number of elements + * changed * @return ZAddParams */ - public ZAddParams lt() { - addParam(LT); + public ZAddParams ch() { + this.change = true; return this; } @Override public void addParams(CommandArguments args) { - if (contains(NX)) { - args.add(NX); - } - if (contains(XX)) { - args.add(XX); - } - if (contains(CH)) { - args.add(CH); + if (existence != null) { + args.add(existence); } - if (contains(LT)) { - args.add(LT); + if (comparison != null) { + args.add(comparison); } - if (contains(GT)) { - args.add(GT); + if (change) { + args.add(Keyword.CH); } } diff --git a/src/main/java/redis/clients/jedis/params/ZIncrByParams.java b/src/main/java/redis/clients/jedis/params/ZIncrByParams.java index a2652063b7..6d5b5a411d 100644 --- a/src/main/java/redis/clients/jedis/params/ZIncrByParams.java +++ b/src/main/java/redis/clients/jedis/params/ZIncrByParams.java @@ -1,6 +1,7 @@ package redis.clients.jedis.params; import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.Protocol.Keyword; /** * Parameters for ZINCRBY commands. In fact, Redis doesn't have parameters for ZINCRBY. Instead @@ -12,11 +13,9 @@ *

* Works with Redis 3.0.2 and onwards. */ -public class ZIncrByParams extends Params implements IParams { +public class ZIncrByParams implements IParams { - private static final String XX = "xx"; - private static final String NX = "nx"; - private static final String INCR = "incr"; + private Keyword existance; public ZIncrByParams() { } @@ -30,7 +29,7 @@ public static ZIncrByParams zIncrByParams() { * @return ZIncrByParams */ public ZIncrByParams nx() { - addParam(NX); + this.existance = Keyword.NX; return this; } @@ -39,20 +38,17 @@ public ZIncrByParams nx() { * @return ZIncrByParams */ public ZIncrByParams xx() { - addParam(XX); + this.existance = Keyword.XX; return this; } @Override public void addParams(CommandArguments args) { - if (contains(NX)) { - args.add(NX); - } - if (contains(XX)) { - args.add(XX); + if (existance != null) { + args.add(existance); } - args.add(INCR); + args.add(Keyword.INCR); } } diff --git a/src/main/java/redis/clients/jedis/params/ZParams.java b/src/main/java/redis/clients/jedis/params/ZParams.java index b4edc3b808..ea45cc9327 100644 --- a/src/main/java/redis/clients/jedis/params/ZParams.java +++ b/src/main/java/redis/clients/jedis/params/ZParams.java @@ -1,12 +1,10 @@ package redis.clients.jedis.params; -import static redis.clients.jedis.Protocol.Keyword.AGGREGATE; -import static redis.clients.jedis.Protocol.Keyword.WEIGHTS; - import java.util.ArrayList; import java.util.List; import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.Protocol.Keyword; import redis.clients.jedis.args.Rawable; import redis.clients.jedis.util.SafeEncoder; @@ -31,22 +29,21 @@ public byte[] getRaw() { private final List params = new ArrayList<>(); public ZParams weights(final double... weights) { - params.add(WEIGHTS); + params.add(Keyword.WEIGHTS); for (final double weight : weights) { params.add(weight); } - return this; } public ZParams aggregate(final Aggregate aggregate) { - params.add(AGGREGATE); + params.add(Keyword.AGGREGATE); params.add(aggregate); return this; } @Override public void addParams(CommandArguments args) { - params.forEach(param -> args.add(param)); + args.addObjects(params); } } diff --git a/src/main/java/redis/clients/jedis/params/ZRangeParams.java b/src/main/java/redis/clients/jedis/params/ZRangeParams.java index 0f4a284a77..7d990c6198 100644 --- a/src/main/java/redis/clients/jedis/params/ZRangeParams.java +++ b/src/main/java/redis/clients/jedis/params/ZRangeParams.java @@ -2,8 +2,6 @@ import static redis.clients.jedis.Protocol.Keyword.BYLEX; import static redis.clients.jedis.Protocol.Keyword.BYSCORE; -import static redis.clients.jedis.Protocol.Keyword.LIMIT; -import static redis.clients.jedis.Protocol.Keyword.REV; import static redis.clients.jedis.args.RawableFactory.from; import redis.clients.jedis.CommandArguments; @@ -89,20 +87,15 @@ public void addParams(CommandArguments args) { args.add(min).add(max); if (by != null) { -// if (by == BYSCORE || by == BYLEX) { -// args.add(by); -// } else { -// throw new IllegalArgumentException(by.name() + " is not a valid ZRANGE type argument."); -// } args.add(by); } if (rev) { - args.add(REV); + args.add(Keyword.REV); } - if (this.limit) { - args.add(LIMIT).add(offset).add(count); + if (limit) { + args.add(Keyword.LIMIT).add(offset).add(count); } } } diff --git a/src/main/java/redis/clients/jedis/providers/ClusterConnectionProvider.java b/src/main/java/redis/clients/jedis/providers/ClusterConnectionProvider.java index 57cf18bbc1..c21640713d 100644 --- a/src/main/java/redis/clients/jedis/providers/ClusterConnectionProvider.java +++ b/src/main/java/redis/clients/jedis/providers/ClusterConnectionProvider.java @@ -1,5 +1,6 @@ package redis.clients.jedis.providers; +import java.time.Duration; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -17,6 +18,8 @@ import redis.clients.jedis.exceptions.JedisClusterOperationException; import redis.clients.jedis.exceptions.JedisException; +import static redis.clients.jedis.JedisCluster.INIT_NO_ERROR_PROPERTY; + public class ClusterConnectionProvider implements ConnectionProvider { protected final JedisClusterInfoCache cache; @@ -32,6 +35,12 @@ public ClusterConnectionProvider(Set clusterNodes, JedisClientConfi initializeSlotsCache(clusterNodes, clientConfig); } + public ClusterConnectionProvider(Set clusterNodes, JedisClientConfig clientConfig, + GenericObjectPoolConfig poolConfig, Duration topologyRefreshPeriod) { + this.cache = new JedisClusterInfoCache(clientConfig, poolConfig, clusterNodes, topologyRefreshPeriod); + initializeSlotsCache(clusterNodes, clientConfig); + } + private void initializeSlotsCache(Set startNodes, JedisClientConfig clientConfig) { if (startNodes.isEmpty()) { throw new JedisClusterOperationException("No nodes to initialize cluster slots cache."); @@ -53,6 +62,9 @@ private void initializeSlotsCache(Set startNodes, JedisClientConfig } } + if (System.getProperty(INIT_NO_ERROR_PROPERTY) != null) { + return; + } JedisClusterOperationException uninitializedException = new JedisClusterOperationException("Could not initialize cluster slots cache."); uninitializedException.addSuppressed(firstException); @@ -61,7 +73,7 @@ private void initializeSlotsCache(Set startNodes, JedisClientConfig @Override public void close() { - cache.reset(); + cache.close(); } public void renewSlotCache() { diff --git a/src/main/java/redis/clients/jedis/providers/MultiClusterPooledConnectionProvider.java b/src/main/java/redis/clients/jedis/providers/MultiClusterPooledConnectionProvider.java new file mode 100644 index 0000000000..abe5515b97 --- /dev/null +++ b/src/main/java/redis/clients/jedis/providers/MultiClusterPooledConnectionProvider.java @@ -0,0 +1,321 @@ +package redis.clients.jedis.providers; + +import io.github.resilience4j.circuitbreaker.CircuitBreaker; +import io.github.resilience4j.circuitbreaker.CircuitBreaker.State; +import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig; +import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry; +import io.github.resilience4j.core.IntervalFunction; +import io.github.resilience4j.retry.Retry; +import io.github.resilience4j.retry.RetryConfig; +import io.github.resilience4j.retry.RetryRegistry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import redis.clients.jedis.*; +import redis.clients.jedis.MultiClusterClientConfig.ClusterConfig; +import redis.clients.jedis.exceptions.JedisConnectionException; +import redis.clients.jedis.exceptions.JedisValidationException; +import redis.clients.jedis.util.Pool; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; + + +/** + * @author Allen Terleto (aterleto) + *

+ * ConnectionProvider which supports multiple cluster/database endpoints each with their own isolated connection pool. + * With this ConnectionProvider users can seamlessly failover to Disaster Recovery (DR), Backup, and Active-Active cluster(s) + * by using simple configuration which is passed through from Resilience4j - https://resilience4j.readme.io/docs + *

+ * Support for manual failback is provided by way of {@link #setActiveMultiClusterIndex(int)} + *

+ */ +public class MultiClusterPooledConnectionProvider implements ConnectionProvider { + + private final Logger log = LoggerFactory.getLogger(getClass()); + + /** + * Ordered map of cluster/database endpoints which were provided at startup via the MultiClusterClientConfig. + * Users can move down (failover) or (up) failback the map depending on their availability and order. + */ + private final Map multiClusterMap = new ConcurrentHashMap<>(); + + /** + * Indicates the actively used cluster/database endpoint (connection pool) amongst the pre-configured list which were + * provided at startup via the MultiClusterClientConfig. All traffic will be routed according to this index. + */ + private volatile Integer activeMultiClusterIndex = 1; + + /** + * Indicates the final cluster/database endpoint (connection pool), according to the pre-configured list + * provided at startup via the MultiClusterClientConfig, is unavailable and therefore no further failover is possible. + * Users can manually failback to an available cluster which would reset this flag via {@link #setActiveMultiClusterIndex(int)} + */ + private volatile boolean lastClusterCircuitBreakerForcedOpen = false; + + /** + * Functional interface typically used for activeMultiClusterIndex persistence or custom logging after a successful + * failover of a cluster/database endpoint (connection pool). Cluster/database endpoint info is passed as the sole parameter + * + * Example: cluster:2:redis-smart-cache.demo.com:12000 + */ + private Consumer clusterFailoverPostProcessor; + + + public MultiClusterPooledConnectionProvider(MultiClusterClientConfig multiClusterClientConfig) { + + if (multiClusterClientConfig == null) + throw new JedisValidationException("MultiClusterClientConfig must not be NULL for MultiClusterPooledConnectionProvider"); + + ////////////// Configure Retry //////////////////// + + RetryConfig.Builder retryConfigBuilder = RetryConfig.custom(); + retryConfigBuilder.maxAttempts(multiClusterClientConfig.getRetryMaxAttempts()); + retryConfigBuilder.intervalFunction(IntervalFunction.ofExponentialBackoff(multiClusterClientConfig.getRetryWaitDuration(), + multiClusterClientConfig.getRetryWaitDurationExponentialBackoffMultiplier())); + retryConfigBuilder.failAfterMaxAttempts(false); // JedisConnectionException will be thrown + retryConfigBuilder.retryExceptions(multiClusterClientConfig.getRetryIncludedExceptionList().stream().toArray(Class[]::new)); + + List retryIgnoreExceptionList = multiClusterClientConfig.getRetryIgnoreExceptionList(); + if (retryIgnoreExceptionList != null && !retryIgnoreExceptionList.isEmpty()) + retryConfigBuilder.ignoreExceptions(retryIgnoreExceptionList.stream().toArray(Class[]::new)); + + RetryConfig retryConfig = retryConfigBuilder.build(); + + ////////////// Configure Circuit Breaker //////////////////// + + CircuitBreakerConfig.Builder circuitBreakerConfigBuilder = CircuitBreakerConfig.custom(); + circuitBreakerConfigBuilder.failureRateThreshold(multiClusterClientConfig.getCircuitBreakerFailureRateThreshold()); + circuitBreakerConfigBuilder.slowCallRateThreshold(multiClusterClientConfig.getCircuitBreakerSlowCallRateThreshold()); + circuitBreakerConfigBuilder.slowCallDurationThreshold(multiClusterClientConfig.getCircuitBreakerSlowCallDurationThreshold()); + circuitBreakerConfigBuilder.minimumNumberOfCalls(multiClusterClientConfig.getCircuitBreakerSlidingWindowMinCalls()); + circuitBreakerConfigBuilder.slidingWindowType(multiClusterClientConfig.getCircuitBreakerSlidingWindowType()); + circuitBreakerConfigBuilder.slidingWindowSize(multiClusterClientConfig.getCircuitBreakerSlidingWindowSize()); + circuitBreakerConfigBuilder.recordExceptions(multiClusterClientConfig.getCircuitBreakerIncludedExceptionList().stream().toArray(Class[]::new)); + circuitBreakerConfigBuilder.automaticTransitionFromOpenToHalfOpenEnabled(false); // State transitions are forced. No half open states are used + + List circuitBreakerIgnoreExceptionList = multiClusterClientConfig.getCircuitBreakerIgnoreExceptionList(); + if (circuitBreakerIgnoreExceptionList != null && !circuitBreakerIgnoreExceptionList.isEmpty()) + circuitBreakerConfigBuilder.ignoreExceptions(circuitBreakerIgnoreExceptionList.stream().toArray(Class[]::new)); + + CircuitBreakerConfig circuitBreakerConfig = circuitBreakerConfigBuilder.build(); + + ////////////// Configure Cluster Map //////////////////// + + ClusterConfig[] clusterConfigs = multiClusterClientConfig.getClusterConfigs(); + for (ClusterConfig config : clusterConfigs) { + + String clusterId = "cluster:" + config.getPriority() + ":" + config.getHostAndPort(); + + Retry retry = RetryRegistry.of(retryConfig).retry(clusterId); + + Retry.EventPublisher retryPublisher = retry.getEventPublisher(); + retryPublisher.onRetry(event -> log.warn(String.valueOf(event))); + retryPublisher.onError(event -> log.error(String.valueOf(event))); + + CircuitBreaker circuitBreaker = CircuitBreakerRegistry.of(circuitBreakerConfig).circuitBreaker(clusterId); + + CircuitBreaker.EventPublisher circuitBreakerEventPublisher = circuitBreaker.getEventPublisher(); + circuitBreakerEventPublisher.onCallNotPermitted(event -> log.error(String.valueOf(event))); + circuitBreakerEventPublisher.onError(event -> log.error(String.valueOf(event))); + circuitBreakerEventPublisher.onFailureRateExceeded(event -> log.error(String.valueOf(event))); + circuitBreakerEventPublisher.onSlowCallRateExceeded(event -> log.error(String.valueOf(event))); + circuitBreakerEventPublisher.onStateTransition(event -> log.warn(String.valueOf(event))); + + multiClusterMap.put(config.getPriority(), new Cluster(new ConnectionPool(config.getHostAndPort(), + config.getJedisClientConfig()), + retry, circuitBreaker)); + } + } + + /** + * Increments the actively used cluster/database endpoint (connection pool) amongst the pre-configured list which were + * provided at startup via the MultiClusterClientConfig. All traffic will be routed according to this index. + * + * Only indexes within the pre-configured range (static) are supported otherwise an exception will be thrown. + * + * In the event that the next prioritized connection has a forced open state, + * the method will recursively increment the index in order to avoid a failed command. + */ + public int incrementActiveMultiClusterIndex() { + + // Field-level synchronization is used to avoid the edge case in which + // setActiveMultiClusterIndex(int multiClusterIndex) is called at the same time + synchronized (activeMultiClusterIndex) { + + String originalClusterName = getClusterCircuitBreaker().getName(); + + // Only increment if it can pass this validation otherwise we will need to check for NULL in the data path + if (activeMultiClusterIndex + 1 > multiClusterMap.size()) { + + lastClusterCircuitBreakerForcedOpen = true; + + throw new JedisConnectionException("Cluster/database endpoint could not failover since the MultiClusterClientConfig was not " + + "provided with an additional cluster/database endpoint according to its prioritized sequence. " + + "If applicable, consider failing back OR restarting with an available cluster/database endpoint"); + } + else activeMultiClusterIndex++; + + CircuitBreaker circuitBreaker = getClusterCircuitBreaker(); + + // Handles edge-case in which the user resets the activeMultiClusterIndex to a higher priority prematurely + // which forces a failover to the next prioritized cluster that has potentially not yet recovered + if (CircuitBreaker.State.FORCED_OPEN.equals(circuitBreaker.getState())) + incrementActiveMultiClusterIndex(); + + else log.warn("Cluster/database endpoint successfully updated from '{}' to '{}'", originalClusterName, circuitBreaker.getName()); + } + + return activeMultiClusterIndex; + } + + /** + * Design decision was made to defer responsibility for cross-replication validation to the user. + * + * Alternatively there was discussion to handle cross-cluster replication validation by + * setting a key/value pair per hashslot in the active connection (with a TTL) and + * subsequently reading it from the target connection. + */ + public void validateTargetConnection(int multiClusterIndex) { + + CircuitBreaker circuitBreaker = getClusterCircuitBreaker(multiClusterIndex); + + State originalState = circuitBreaker.getState(); + try { + // Transitions the state machine to a CLOSED state, allowing state transition, metrics and event publishing + // Safe since the activeMultiClusterIndex has not yet been changed and therefore no traffic will be routed yet + circuitBreaker.transitionToClosedState(); + + try (Connection targetConnection = getConnection(multiClusterIndex)) { + targetConnection.ping(); + } + } + catch (Exception e) { + + // If the original state was FORCED_OPEN, then transition it back which stops state transition, metrics and event publishing + if (CircuitBreaker.State.FORCED_OPEN.equals(originalState)) + circuitBreaker.transitionToForcedOpenState(); + + throw new JedisValidationException(circuitBreaker.getName() + " failed to connect. Please check configuration and try again.", e); + } + } + + /** + * Manually overrides the actively used cluster/database endpoint (connection pool) amongst the + * pre-configured list which were provided at startup via the MultiClusterClientConfig. + * All traffic will be routed according to the provided new index. + * + * Special care should be taken to confirm cluster/database availability AND + * potentially cross-cluster replication BEFORE using this capability. + */ + public synchronized void setActiveMultiClusterIndex(int multiClusterIndex) { + + // Field-level synchronization is used to avoid the edge case in which + // incrementActiveMultiClusterIndex() is called at the same time + synchronized (activeMultiClusterIndex) { + + // Allows an attempt to reset the current cluster from a FORCED_OPEN to CLOSED state in the event that no failover is possible + if (activeMultiClusterIndex == multiClusterIndex && + !CircuitBreaker.State.FORCED_OPEN.equals(getClusterCircuitBreaker(multiClusterIndex).getState())) + return; + + if (multiClusterIndex < 1 || multiClusterIndex > multiClusterMap.size()) + throw new JedisValidationException("MultiClusterIndex: " + multiClusterIndex + " is not within " + + "the configured range. Please choose an index between 1 and " + multiClusterMap.size()); + + validateTargetConnection(multiClusterIndex); + + String originalClusterName = getClusterCircuitBreaker().getName(); + + if (activeMultiClusterIndex == multiClusterIndex) + log.warn("Cluster/database endpoint '{}' successfully closed its circuit breaker", originalClusterName); + else + log.warn("Cluster/database endpoint successfully updated from '{}' to '{}'", + originalClusterName, getClusterCircuitBreaker(multiClusterIndex).getName()); + + activeMultiClusterIndex = multiClusterIndex; + lastClusterCircuitBreakerForcedOpen = false; + } + } + + @Override + public void close() { + multiClusterMap.get(activeMultiClusterIndex).getConnectionPool().close(); + } + + @Override + public Connection getConnection() { + return multiClusterMap.get(activeMultiClusterIndex).getConnection(); + } + + public Connection getConnection(int multiClusterIndex) { + return multiClusterMap.get(multiClusterIndex).getConnection(); + } + + @Override + public Connection getConnection(CommandArguments args) { + return multiClusterMap.get(activeMultiClusterIndex).getConnection(); + } + + @Override + public Map> getConnectionMap() { + ConnectionPool connectionPool = multiClusterMap.get(activeMultiClusterIndex).getConnectionPool(); + return Collections.singletonMap(connectionPool.getFactory(), connectionPool); + } + + public Cluster getCluster() { + return multiClusterMap.get(activeMultiClusterIndex); + } + + public CircuitBreaker getClusterCircuitBreaker() { + return multiClusterMap.get(activeMultiClusterIndex).getCircuitBreaker(); + } + + public CircuitBreaker getClusterCircuitBreaker(int multiClusterIndex) { + return multiClusterMap.get(multiClusterIndex).getCircuitBreaker(); + } + + public boolean isLastClusterCircuitBreakerForcedOpen() { + return lastClusterCircuitBreakerForcedOpen; + } + + public void runClusterFailoverPostProcessor(Integer multiClusterIndex) { + if (clusterFailoverPostProcessor != null) + clusterFailoverPostProcessor.accept(getClusterCircuitBreaker(multiClusterIndex).getName()); + } + + public void setClusterFailoverPostProcessor(Consumer clusterFailoverPostProcessor) { + this.clusterFailoverPostProcessor = clusterFailoverPostProcessor; + } + + public static class Cluster { + + private final ConnectionPool connectionPool; + private final Retry retry; + private final CircuitBreaker circuitBreaker; + + public Cluster(ConnectionPool connectionPool, Retry retry, CircuitBreaker circuitBreaker) { + this.connectionPool = connectionPool; + this.retry = retry; + this.circuitBreaker = circuitBreaker; + } + + public Connection getConnection() { + return connectionPool.getResource(); + } + + public ConnectionPool getConnectionPool() { + return connectionPool; + } + + public Retry getRetry() { + return retry; + } + + public CircuitBreaker getCircuitBreaker() { + return circuitBreaker; + } + } + +} \ No newline at end of file diff --git a/src/main/java/redis/clients/jedis/providers/ShardedConnectionProvider.java b/src/main/java/redis/clients/jedis/providers/ShardedConnectionProvider.java index 63d6c7946f..da5a377f34 100644 --- a/src/main/java/redis/clients/jedis/providers/ShardedConnectionProvider.java +++ b/src/main/java/redis/clients/jedis/providers/ShardedConnectionProvider.java @@ -19,6 +19,10 @@ import redis.clients.jedis.exceptions.JedisException; import redis.clients.jedis.util.Hashing; +/** + * @deprecated Sharding/Sharded feature will be removed in next major release. + */ +@Deprecated public class ShardedConnectionProvider implements ConnectionProvider { private final TreeMap nodes = new TreeMap<>(); diff --git a/src/main/java/redis/clients/jedis/resps/AccessControlLogEntry.java b/src/main/java/redis/clients/jedis/resps/AccessControlLogEntry.java index d60359edeb..930c9b064d 100644 --- a/src/main/java/redis/clients/jedis/resps/AccessControlLogEntry.java +++ b/src/main/java/redis/clients/jedis/resps/AccessControlLogEntry.java @@ -1,13 +1,15 @@ package redis.clients.jedis.resps; import java.io.Serializable; -import java.util.*; +import java.util.LinkedHashMap; +import java.util.Map; /** * This class holds information about an Access Control Log entry (returned by ACL LOG command) They - * can be access via getters. For future purpose there is also {@link #getlogEntry} method that + * can be accessed via getters. For future purpose there is also {@link #getlogEntry} method that * returns a generic {@code Map} - in case where more info is returned from a server */ +// TODO: remove public class AccessControlLogEntry implements Serializable { private static final long serialVersionUID = 1L; @@ -19,15 +21,22 @@ public class AccessControlLogEntry implements Serializable { public static final String USERNAME = "username"; public static final String AGE_SECONDS = "age-seconds"; public static final String CLIENT_INFO = "client-info"; + // Redis 7.2 + public static final String ENTRY_ID = "entry-id"; + public static final String TIMESTAMP_CREATED = "timestamp-created"; + public static final String TIMESTAMP_LAST_UPDATED = "timestamp-last-updated"; - private long count; + private final long count; private final String reason; private final String context; private final String object; private final String username; - private final String ageSeconds; + private final Double ageSeconds; private final Map clientInfo; private final Map logEntry; + private final long entryId; + private final long timestampCreated; + private final long timestampLastUpdated; public AccessControlLogEntry(Map map) { count = (long) map.get(COUNT); @@ -35,9 +44,12 @@ public AccessControlLogEntry(Map map) { context = (String) map.get(CONTEXT); object = (String) map.get(OBJECT); username = (String) map.get(USERNAME); - ageSeconds = (String) map.get(AGE_SECONDS); + ageSeconds = (Double) map.get(AGE_SECONDS); clientInfo = getMapFromRawClientInfo((String) map.get(CLIENT_INFO)); logEntry = map; + entryId = (long) map.get(ENTRY_ID); + timestampCreated = (long) map.get(TIMESTAMP_CREATED); + timestampLastUpdated = (long) map.get(TIMESTAMP_LAST_UPDATED); } public long getCount() { @@ -60,7 +72,7 @@ public String getUsername() { return username; } - public String getAgeSeconds() { + public Double getAgeSeconds() { return ageSeconds; } @@ -75,6 +87,18 @@ public Map getlogEntry() { return logEntry; } + public long getEntryId() { + return entryId; + } + + public long getTimestampCreated() { + return timestampCreated; + } + + public long getTimestampLastUpdated() { + return timestampLastUpdated; + } + /** * Convert the client-info string into a Map of String. When the value is empty, the value in the * map is set to an empty string The key order is maintained to reflect the string return by Redis @@ -95,6 +119,8 @@ private Map getMapFromRawClientInfo(String clientInfo) { public String toString() { return "AccessControlLogEntry{" + "count=" + count + ", reason='" + reason + '\'' + ", context='" + context + '\'' + ", object='" + object + '\'' + ", username='" + username - + '\'' + ", ageSeconds='" + ageSeconds + '\'' + ", clientInfo=" + clientInfo + '}'; + + '\'' + ", ageSeconds='" + ageSeconds + '\'' + ", clientInfo=" + clientInfo + + ", entryId=" + entryId + ", timestampCreated=" + timestampCreated + + ", timestampLastUpdated=" + timestampLastUpdated + '}'; } } diff --git a/src/main/java/redis/clients/jedis/resps/AccessControlUser.java b/src/main/java/redis/clients/jedis/resps/AccessControlUser.java index 6013a8f760..2c9d0f9e78 100644 --- a/src/main/java/redis/clients/jedis/resps/AccessControlUser.java +++ b/src/main/java/redis/clients/jedis/resps/AccessControlUser.java @@ -1,75 +1,116 @@ package redis.clients.jedis.resps; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; +import java.util.StringJoiner; +// TODO: remove public class AccessControlUser { - private final List flags = new ArrayList<>(); - private final List keys = new ArrayList<>(); - private final List passwords = new ArrayList<>(); - private final List channels = new ArrayList<>(); - private String commands; + private final Map userInfo; + private final List flags; + private final List passwords; + private final String commands; + private final List keysList; + private final String keys; + private final List channelsList; + private final String channels; + private final List selectors; + + public AccessControlUser(Map map) { + this.userInfo = map; + + this.flags = (List) map.get("flags"); + + this.passwords = (List) map.get("passwords"); + + this.commands = (String) map.get("commands"); + + Object localKeys = map.get("keys"); + if (localKeys == null) { + this.keys = null; + this.keysList = null; + } else if (localKeys instanceof List) { + this.keysList = (List) localKeys; + this.keys = joinStrings(this.keysList); + } else { + this.keys = (String) localKeys; + this.keysList = Arrays.asList(this.keys.split(" ")); + } + + Object localChannels = map.get("channels"); + if (localChannels == null) { + this.channels = null; + this.channelsList = null; + } else if (localChannels instanceof List) { + this.channelsList = (List) localChannels; + this.channels = joinStrings(this.channelsList); + } else { + this.channels = (String) localChannels; + this.channelsList = Arrays.asList(this.channels.split(" ")); + } - public AccessControlUser() { + this.selectors = (List) map.get("selectors"); } - public void addFlag(String flag) { - flags.add(flag); + private static String joinStrings(List list) { + StringJoiner joiner = new StringJoiner(" "); + list.forEach(s -> joiner.add(s)); + return joiner.toString(); } public List getFlags() { return flags; } - public void addKey(String key) { - keys.add(key); - } - - public List getKeys() { - return keys; + /** + * @deprecated Use {@link AccessControlUser#getPasswords()}. + */ + @Deprecated + public List getPassword() { + return passwords; } - public void addKeys(String keys) { - if (!keys.isEmpty()) { - this.keys.addAll(Arrays.asList(keys.split(" "))); - } + public List getPasswords() { + return passwords; } - public void addPassword(String password) { - passwords.add(password); + public String getCommands() { + return commands; } - public List getPassword() { - return passwords; + /** + * @return Generic map containing all key-value pairs returned by the server + */ + public Map getUserInfo() { + return userInfo; } - public void addChannel(String channel) { - channels.add(channel); + public String getKeys() { + return keys; } - public List getChannels() { - return channels; + public List getKeysList() { + return keysList; } - public void addChannels(String channels) { - if (!channels.isEmpty()) { - this.channels.addAll(Arrays.asList(channels.split(" "))); - } + public List getChannelsList() { + return channelsList; } - public String getCommands() { - return commands; + public String getChannels() { + return channels; } - public void setCommands(String commands) { - this.commands = commands; + public List getSelectors() { + return selectors; } @Override public String toString() { return "AccessControlUser{" + "flags=" + flags + ", passwords=" + passwords - + ", commands='" + commands + "', keys='" + keys + "', channels='" + channels + "'}"; + + ", commands='" + commands + "', keys='" + keys + "', channels='" + channels + + "', selectors=" + selectors + "}"; } } diff --git a/src/main/java/redis/clients/jedis/resps/ClusterShardInfo.java b/src/main/java/redis/clients/jedis/resps/ClusterShardInfo.java new file mode 100644 index 0000000000..8e7394bccc --- /dev/null +++ b/src/main/java/redis/clients/jedis/resps/ClusterShardInfo.java @@ -0,0 +1,44 @@ +package redis.clients.jedis.resps; + +import java.util.List; +import java.util.Map; + +/** + * This class holds information about a shard of the cluster with command {@code CLUSTER SHARDS}. + * They can be accessed via getters. There is also {@link ClusterShardInfo#getClusterShardInfo()} + * method that returns a generic {@link Map} in case more info are returned from the server. + */ +public class ClusterShardInfo { + + public static final String SLOTS = "slots"; + public static final String NODES = "nodes"; + + private final List> slots; + private final List nodes; + + private final Map clusterShardInfo; + + /** + * @param map contains key-value pairs with cluster shard info + */ + @SuppressWarnings("unchecked") + public ClusterShardInfo(Map map) { + slots = (List>) map.get(SLOTS); + nodes = (List) map.get(NODES); + + clusterShardInfo = map; + } + + public List> getSlots() { + return slots; + } + + public List getNodes() { + return nodes; + } + + public Map getClusterShardInfo() { + return clusterShardInfo; + } + +} diff --git a/src/main/java/redis/clients/jedis/resps/ClusterShardNodeInfo.java b/src/main/java/redis/clients/jedis/resps/ClusterShardNodeInfo.java new file mode 100644 index 0000000000..6e245de4d2 --- /dev/null +++ b/src/main/java/redis/clients/jedis/resps/ClusterShardNodeInfo.java @@ -0,0 +1,94 @@ +package redis.clients.jedis.resps; + +import java.util.Map; + +/** + * This class holds information about a node of the cluster with command {@code CLUSTER SHARDS}. + * They can be accessed via getters. There is also {@link ClusterShardNodeInfo#getClusterShardNodeInfo()} + * method that returns a generic {@link Map} in case more info are returned from the server. + */ +public class ClusterShardNodeInfo { + + public static final String ID = "id"; + public static final String ENDPOINT = "endpoint"; + public static final String IP = "ip"; + public static final String HOSTNAME = "hostname"; + public static final String PORT = "port"; + public static final String TLS_PORT = "tls-port"; + public static final String ROLE = "role"; + public static final String REPLICATION_OFFSET = "replication-offset"; + public static final String HEALTH = "health"; + + private final String id; + private final String endpoint; + private final String ip; + private final String hostname; + private final Long port; + private final Long tlsPort; + private final String role; + private final Long replicationOffset; + private final String health; + + private final Map clusterShardNodeInfo; + + /** + * @param map contains key-value pairs with node info + */ + public ClusterShardNodeInfo(Map map) { + id = (String) map.get(ID); + endpoint = (String) map.get(ENDPOINT); + ip = (String) map.get(IP); + hostname = (String) map.get(HOSTNAME); + port = (Long) map.get(PORT); + tlsPort = (Long) map.get(TLS_PORT); + role = (String) map.get(ROLE); + replicationOffset = (Long) map.get(REPLICATION_OFFSET); + health = (String) map.get(HEALTH); + + clusterShardNodeInfo = map; + } + + public String getId() { + return id; + } + + public String getEndpoint() { + return endpoint; + } + + public String getIp() { + return ip; + } + + public String getHostname() { + return hostname; + } + + public Long getPort() { + return port; + } + + public Long getTlsPort() { + return tlsPort; + } + + public String getRole() { + return role; + } + + public Long getReplicationOffset() { + return replicationOffset; + } + + public String getHealth() { + return health; + } + + public Map getClusterShardNodeInfo() { + return clusterShardNodeInfo; + } + + public boolean isSsl() { + return tlsPort != null; + } +} diff --git a/src/main/java/redis/clients/jedis/resps/CommandDocument.java b/src/main/java/redis/clients/jedis/resps/CommandDocument.java index 219397811e..3e320d8dec 100644 --- a/src/main/java/redis/clients/jedis/resps/CommandDocument.java +++ b/src/main/java/redis/clients/jedis/resps/CommandDocument.java @@ -5,21 +5,55 @@ import static redis.clients.jedis.BuilderFactory.STRING; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import redis.clients.jedis.util.KeyValue; public class CommandDocument { + + private static final String SUMMARY_STR = "summary"; + private static final String SINCE_STR = "since"; + private static final String GROUP_STR = "group"; + private static final String COMPLEXITY_STR = "complexity"; + private static final String HISTORY_STR = "history"; + private final String summary; private final String since; private final String group; private final String complexity; private final List history; + @Deprecated public CommandDocument(String summary, String since, String group, String complexity, List history) { this.summary = summary; this.since = since; this.group = group; this.complexity = complexity; - this.history = history; + this.history = (List) history; + } + + public CommandDocument(Map map) { + this.summary = (String) map.get(SUMMARY_STR); + this.since = (String) map.get(SINCE_STR); + this.group = (String) map.get(GROUP_STR); + this.complexity = (String) map.get(COMPLEXITY_STR); + + List historyObject = (List) map.get(HISTORY_STR); + if (historyObject == null) { + this.history = null; + } else if (historyObject.isEmpty()) { + this.history = Collections.emptyList(); + } else if (historyObject.get(0) instanceof KeyValue) { + this.history = historyObject.stream().map(o -> (KeyValue) o) + .map(kv -> (String) kv.getKey() + ": " + (String) kv.getValue()) + .collect(Collectors.toList()); + } else { + this.history = historyObject.stream().map(o -> (List) o) + .map(l -> (String) l.get(0) + ": " + (String) l.get(1)) + .collect(Collectors.toList()); + } } public String getSummary() { @@ -42,6 +76,7 @@ public List getHistory() { return history; } + @Deprecated public static final Builder COMMAND_DOCUMENT_BUILDER = new Builder() { @Override public CommandDocument build(Object data) { diff --git a/src/main/java/redis/clients/jedis/resps/FunctionStats.java b/src/main/java/redis/clients/jedis/resps/FunctionStats.java index 917af0ce68..b8d55c181f 100644 --- a/src/main/java/redis/clients/jedis/resps/FunctionStats.java +++ b/src/main/java/redis/clients/jedis/resps/FunctionStats.java @@ -5,6 +5,7 @@ import java.util.Map; import redis.clients.jedis.Builder; import redis.clients.jedis.BuilderFactory; +import redis.clients.jedis.util.KeyValue; public class FunctionStats { @@ -28,12 +29,38 @@ public Map> getEngines() { @Override public FunctionStats build(Object data) { - List superMapList = (List) data; + if (data == null) return null; + List list = (List) data; + if (list.isEmpty()) return null; - Map runningScriptMap = superMapList.get(1) == null ? null - : BuilderFactory.ENCODED_OBJECT_MAP.build(superMapList.get(1)); + if (list.get(0) instanceof KeyValue) { - List enginesList = (List) superMapList.get(3); + Map runningScriptMap = null; + Map> enginesMap = null; + + for (KeyValue kv : (List) list) { + switch (BuilderFactory.STRING.build(kv.getKey())) { + case "running_script": + runningScriptMap = BuilderFactory.ENCODED_OBJECT_MAP.build(kv.getValue()); + break; + case "engines": + List ilist = (List) kv.getValue(); + enginesMap = new LinkedHashMap<>(ilist.size()); + for (KeyValue ikv : (List) kv.getValue()) { + enginesMap.put(BuilderFactory.STRING.build(ikv.getKey()), + BuilderFactory.ENCODED_OBJECT_MAP.build(ikv.getValue())); + } + break; + } + } + + return new FunctionStats(runningScriptMap, enginesMap); + } + + Map runningScriptMap = list.get(1) == null ? null + : BuilderFactory.ENCODED_OBJECT_MAP.build(list.get(1)); + + List enginesList = (List) list.get(3); Map> enginesMap = new LinkedHashMap<>(enginesList.size() / 2); for (int i = 0; i < enginesList.size(); i += 2) { diff --git a/src/main/java/redis/clients/jedis/resps/GeoRadiusResponse.java b/src/main/java/redis/clients/jedis/resps/GeoRadiusResponse.java index 03a51b2525..d4442bd725 100644 --- a/src/main/java/redis/clients/jedis/resps/GeoRadiusResponse.java +++ b/src/main/java/redis/clients/jedis/resps/GeoRadiusResponse.java @@ -4,8 +4,10 @@ import redis.clients.jedis.util.SafeEncoder; import java.util.Arrays; +import java.util.Objects; public class GeoRadiusResponse { + private byte[] member; private double distance; private GeoCoordinate coordinate; @@ -23,6 +25,10 @@ public void setCoordinate(GeoCoordinate coordinate) { this.coordinate = coordinate; } + public void setRawScore(long rawScore) { + this.rawScore = rawScore; + } + public byte[] getMember() { return member; } @@ -31,22 +37,30 @@ public String getMemberByString() { return SafeEncoder.encode(member); } + /** + * @return The distance of the returned item from the specified center. The distance is returned + * in the same unit as the unit specified as the radius argument of the command. + */ public double getDistance() { return distance; } + /** + * @return The longitude,latitude coordinates of the matching item. + */ public GeoCoordinate getCoordinate() { return coordinate; } + /** + * @return The raw geohash-encoded sorted set score of the item, in the form of a 52 bit unsigned + * integer. This is only useful for low level hacks or debugging and is otherwise of little + * interest for the general user. + */ public long getRawScore() { return rawScore; } - public void setRawScore(long rawScore) { - this.rawScore = rawScore; - } - @Override public boolean equals(Object obj) { if (obj == this) { @@ -62,4 +76,14 @@ public boolean equals(Object obj) { && rawScore == response.getRawScore() && coordinate.equals(response.coordinate) && Arrays.equals(member, response.getMember()); } + + @Override + public int hashCode() { + int hash = 7; + hash = 67 * hash + Arrays.hashCode(this.member); + hash = 67 * hash + (int) (Double.doubleToLongBits(this.distance) ^ (Double.doubleToLongBits(this.distance) >>> 32)); + hash = 67 * hash + Objects.hashCode(this.coordinate); + hash = 67 * hash + (int) (this.rawScore ^ (this.rawScore >>> 32)); + return hash; + } } diff --git a/src/main/java/redis/clients/jedis/resps/KeyedListElement.java b/src/main/java/redis/clients/jedis/resps/KeyedListElement.java deleted file mode 100644 index c3195c7a26..0000000000 --- a/src/main/java/redis/clients/jedis/resps/KeyedListElement.java +++ /dev/null @@ -1,28 +0,0 @@ -package redis.clients.jedis.resps; - -import redis.clients.jedis.util.KeyValue; -import redis.clients.jedis.util.SafeEncoder; - -/** - * This class is used to represent a List element when it is returned with respective key name. - * @deprecated Use {@link KeyValue}. - */ -@Deprecated -public class KeyedListElement extends KeyValue { - - public KeyedListElement(byte[] key, byte[] element) { - this(SafeEncoder.encode(key), SafeEncoder.encode(element)); - } - - public KeyedListElement(String key, String element) { - super(key, element); - } - - /** - * @deprecated Use {@link java.util.Map.Entry#getValue()}. - */ - @Deprecated - public String getElement() { - return getValue(); - } -} diff --git a/src/main/java/redis/clients/jedis/resps/KeyedZSetElement.java b/src/main/java/redis/clients/jedis/resps/KeyedZSetElement.java deleted file mode 100644 index d1639937f1..0000000000 --- a/src/main/java/redis/clients/jedis/resps/KeyedZSetElement.java +++ /dev/null @@ -1,45 +0,0 @@ -package redis.clients.jedis.resps; - -import redis.clients.jedis.util.SafeEncoder; - -/** - * This class is used to represent a SortedSet element when it is returned with respective key name. - */ -public class KeyedZSetElement extends Tuple { - - private final String key; - - public KeyedZSetElement(byte[] key, byte[] element, Double score) { - super(element, score); - this.key = SafeEncoder.encode(key); - } - - public KeyedZSetElement(String key, String element, Double score) { - super(element, score); - this.key = key; - } - - public String getKey() { - return key; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof KeyedZSetElement)) return false; - - if (!key.equals(((KeyedZSetElement) o).key)) return false; - return super.equals(o); - } - - @Override - public int hashCode() { - return 31 * key.hashCode() + super.hashCode(); - } - - @Override - public String toString() { - return "KeyedZSetElement{" + "key=" + key + ", element='" + getElement() + "'" - + ", score=" + getScore() + "} "; - } -} diff --git a/src/main/java/redis/clients/jedis/resps/LibraryInfo.java b/src/main/java/redis/clients/jedis/resps/LibraryInfo.java index 7934ce7080..41cbd49dd3 100644 --- a/src/main/java/redis/clients/jedis/resps/LibraryInfo.java +++ b/src/main/java/redis/clients/jedis/resps/LibraryInfo.java @@ -8,7 +8,11 @@ import java.util.stream.Collectors; import redis.clients.jedis.Builder; +import redis.clients.jedis.BuilderFactory; +import redis.clients.jedis.util.KeyValue; +//[library_name=mylib, engine=LUA, functions=[[name=myfunc, description=null, flags=[]]], library_code=#!LUA name=mylib +// redis.register_function('myfunc', function(keys, args) return args[1] end)] public class LibraryInfo { private final String libraryName; @@ -43,20 +47,59 @@ public String getLibraryCode() { return libraryCode; } - public static final Builder LIBRARY_BUILDER = new Builder() { + public static final Builder LIBRARY_INFO = new Builder() { @Override public LibraryInfo build(Object data) { - List objectList = (List) data; - String libname = STRING.build(objectList.get(1)); - String engine = STRING.build(objectList.get(3)); - List rawFunctions = (List) objectList.get(5); + if (data == null) return null; + List list = (List) data; + if (list.isEmpty()) return null; + + if (list.get(0) instanceof KeyValue) { + String libname = null, enginename = null, librarycode = null; + List> functions = null; + for (KeyValue kv : (List) list) { + switch (BuilderFactory.STRING.build(kv.getKey())) { + case "library_name": + libname = BuilderFactory.STRING.build(kv.getValue()); + break; + case "engine": + enginename = BuilderFactory.STRING.build(kv.getValue()); + break; + case "functions": + functions = ((List) kv.getValue()).stream().map(o -> ENCODED_OBJECT_MAP.build(o)).collect(Collectors.toList()); + break; + case "library_code": + librarycode = BuilderFactory.STRING.build(kv.getValue()); + break; + } + } + return new LibraryInfo(libname, enginename, functions, librarycode); + } + + String libname = STRING.build(list.get(1)); + String engine = STRING.build(list.get(3)); + List rawFunctions = (List) list.get(5); List> functions = rawFunctions.stream().map(o -> ENCODED_OBJECT_MAP.build(o)).collect(Collectors.toList()); - if (objectList.size() <= 6) { + if (list.size() <= 6) { return new LibraryInfo(libname, engine, functions); } - String code = STRING.build(objectList.get(7)); + String code = STRING.build(list.get(7)); return new LibraryInfo(libname, engine, functions, code); } }; + /** + * @deprecated Use {@link LibraryInfo#LIBRARY_INFO}. + */ + @Deprecated + public static final Builder LIBRARY_BUILDER = LIBRARY_INFO; + + public static final Builder> LIBRARY_INFO_LIST = new Builder>() { + @Override + public List build(Object data) { + List list = (List) data; + return list.stream().map(o -> LibraryInfo.LIBRARY_INFO.build(o)).collect(Collectors.toList()); + } + }; + } diff --git a/src/main/java/redis/clients/jedis/resps/Slowlog.java b/src/main/java/redis/clients/jedis/resps/Slowlog.java index 13898af98d..58ccf53e21 100644 --- a/src/main/java/redis/clients/jedis/resps/Slowlog.java +++ b/src/main/java/redis/clients/jedis/resps/Slowlog.java @@ -2,7 +2,7 @@ import java.util.ArrayList; import java.util.List; - +import redis.clients.jedis.BuilderFactory; import redis.clients.jedis.HostAndPort; import redis.clients.jedis.util.SafeEncoder; @@ -19,17 +19,11 @@ public class Slowlog { @SuppressWarnings("unchecked") private Slowlog(List properties) { - super(); this.id = (Long) properties.get(0); this.timeStamp = (Long) properties.get(1); this.executionTime = (Long) properties.get(2); - List bargs = (List) properties.get(3); - this.args = new ArrayList<>(bargs.size()); - - for (byte[] barg : bargs) { - this.args.add(SafeEncoder.encode(barg)); - } + this.args = BuilderFactory.STRING_LIST.build(properties.get(3)); if (properties.size() == 4) return; this.clientIpPort = HostAndPort.from(SafeEncoder.encode((byte[]) properties.get(4))); @@ -43,7 +37,6 @@ public static List from(List nestedMultiBulkReply) { List properties = (List) obj; logs.add(new Slowlog(properties)); } - return logs; } diff --git a/src/main/java/redis/clients/jedis/resps/StreamConsumerFullInfo.java b/src/main/java/redis/clients/jedis/resps/StreamConsumerFullInfo.java index 134e570284..2f57329415 100644 --- a/src/main/java/redis/clients/jedis/resps/StreamConsumerFullInfo.java +++ b/src/main/java/redis/clients/jedis/resps/StreamConsumerFullInfo.java @@ -6,19 +6,22 @@ import redis.clients.jedis.StreamEntryID; /** - * This class holds information about a stream consumer with command {@code xinfo stream mystream full}. - * They can be access via getters. For future purpose there is also {@link #getConsumerInfo()} method that - * returns a generic {@link Map} - in case where more info is returned from the server. + * This class holds information about a stream consumer with command + * {@code xinfo stream mystream full}. They can be accessed via getters. There is also + * {@link StreamConsumerFullInfo#getConsumerInfo()} method that returns a generic {@link Map} in + * case more info are returned from the server. */ public class StreamConsumerFullInfo implements Serializable { public static final String NAME = "name"; public static final String SEEN_TIME = "seen-time"; + public static final String ACTIVE_TIME = "active-time"; public static final String PEL_COUNT = "pel-count"; public static final String PENDING = "pending"; private final String name; private final Long seenTime; + private final Long activeTime; // since Redis 7.2 private final Long pelCount; private final List> pending; private final Map consumerInfo; @@ -28,20 +31,28 @@ public StreamConsumerFullInfo(Map map) { consumerInfo = map; name = (String) map.get(NAME); seenTime = (Long) map.get(SEEN_TIME); + activeTime = (Long) map.get(ACTIVE_TIME); pending = (List>) map.get(PENDING); pelCount = (Long) map.get(PEL_COUNT); - pending.stream().forEach(entry -> entry.set(0, new StreamEntryID((String) entry.get(0)))); + pending.forEach(entry -> entry.set(0, new StreamEntryID((String) entry.get(0)))); } public String getName() { return name; } - public long getSeenTime() { + public Long getSeenTime() { return seenTime; } + /** + * Since Redis 7.2. + */ + public Long getActiveTime() { + return activeTime; + } + public Long getPelCount() { return pelCount; } @@ -50,6 +61,9 @@ public List> getPending() { return pending; } + /** + * All data. + */ public Map getConsumerInfo() { return consumerInfo; } diff --git a/src/main/java/redis/clients/jedis/resps/StreamConsumerInfo.java b/src/main/java/redis/clients/jedis/resps/StreamConsumerInfo.java new file mode 100644 index 0000000000..0bf5a46250 --- /dev/null +++ b/src/main/java/redis/clients/jedis/resps/StreamConsumerInfo.java @@ -0,0 +1,60 @@ +package redis.clients.jedis.resps; + +import java.util.Map; + +/** + * This class holds information about a consumer. They can be accessed via getters. There is also + * {@link StreamConsumersInfo#getConsumerInfo()}} method that returns a generic {@code Map} in case + * more info are returned from the server. + */ +public class StreamConsumerInfo { + + public static final String NAME = "name"; + public static final String IDLE = "idle"; + public static final String PENDING = "pending"; + public static final String INACTIVE = "inactive"; + + private final String name; + private final long idle; + private final long pending; + private final Long inactive; + private final Map consumerInfo; + + /** + * @param map contains key-value pairs with consumer info + */ + public StreamConsumerInfo(Map map) { + consumerInfo = map; + name = (String) map.get(NAME); + idle = (Long) map.get(IDLE); + pending = (Long) map.get(PENDING); + inactive = (Long) map.get(INACTIVE); + } + + public String getName() { + return name; + } + + public long getIdle() { + return idle; + } + + public long getPending() { + return pending; + } + + /** + * Since Redis 7.2. + */ + public Long getInactive() { + return inactive; + } + + /** + * All data. + * @return Generic map containing all key-value pairs returned by the server + */ + public Map getConsumerInfo() { + return consumerInfo; + } +} diff --git a/src/main/java/redis/clients/jedis/resps/StreamConsumersInfo.java b/src/main/java/redis/clients/jedis/resps/StreamConsumersInfo.java index e493cc4bcc..4b12a95006 100644 --- a/src/main/java/redis/clients/jedis/resps/StreamConsumersInfo.java +++ b/src/main/java/redis/clients/jedis/resps/StreamConsumersInfo.java @@ -3,51 +3,19 @@ import java.util.Map; /** - * This class holds information about a consumer. They can be access via getters. For future purpose - * there is also {@link #getConsumerInfo()}} method that returns a generic {@code Map} - in case - * where more info is returned from the server. + * This class holds information about a consumer. They can be accessed via getters. There is also + * {@link StreamConsumersInfo#getConsumerInfo()}} method that returns a generic {@code Map} in case + * more info are returned from the server. + * @deprecated Use {@link StreamConsumerInfo}. */ -// TODO: Rename to StreamConsumerInfo -public class StreamConsumersInfo { - - public static final String NAME = "name"; - public static final String IDLE = "idle"; - public static final String PENDING = "pending"; - - private final String name; - private final long idle; - private final long pending; - private final Map consumerInfo; +// TODO: rename to StreamConsumerInfo ? +@Deprecated +public class StreamConsumersInfo extends StreamConsumerInfo { /** * @param map contains key-value pairs with consumer info */ public StreamConsumersInfo(Map map) { - - consumerInfo = map; - name = (String) map.get(NAME); - idle = (long) map.get(IDLE); - pending = (long) map.get(PENDING); - - } - - public String getName() { - return name; - } - - public long getIdle() { - return idle; + super(map); } - - public long getPending() { - return pending; - } - - /** - * @return Generic map containing all key-value pairs returned by the server - */ - public Map getConsumerInfo() { - return consumerInfo; - } - } diff --git a/src/main/java/redis/clients/jedis/resps/StreamFullInfo.java b/src/main/java/redis/clients/jedis/resps/StreamFullInfo.java index 6d40791163..e768b536b8 100644 --- a/src/main/java/redis/clients/jedis/resps/StreamFullInfo.java +++ b/src/main/java/redis/clients/jedis/resps/StreamFullInfo.java @@ -8,8 +8,8 @@ /** * This class holds information about a stream info with command {@code xinfo stream mystream full}. - * They can be access via getters. For future purpose there is also {@link #getStreamFullInfo()} method - * that returns a generic {@link Map} - in case where more info is returned from the server. + * They can be accessed via getters. There is also {@link StreamFullInfo#getStreamFullInfo()} method + * that returns a generic {@link Map} in case where more info are returned from the server. */ public class StreamFullInfo implements Serializable { diff --git a/src/main/java/redis/clients/jedis/resps/StreamGroupFullInfo.java b/src/main/java/redis/clients/jedis/resps/StreamGroupFullInfo.java index c2e0c6642d..8354c86815 100644 --- a/src/main/java/redis/clients/jedis/resps/StreamGroupFullInfo.java +++ b/src/main/java/redis/clients/jedis/resps/StreamGroupFullInfo.java @@ -8,8 +8,8 @@ /** * This class holds information about a stream group with command {@code xinfo stream mystream full}. - * They can be access via getters. For future purpose there is also {@link #getGroupFullInfo()} method - * that returns a generic {@link Map} - in case where more info is returned from the server. + * They can be accessed via getters. There is also {@link StreamGroupFullInfo#getGroupFullInfo()} + * method that returns a generic {@link Map} in case more info are returned from the server. */ public class StreamGroupFullInfo implements Serializable { diff --git a/src/main/java/redis/clients/jedis/resps/StreamGroupInfo.java b/src/main/java/redis/clients/jedis/resps/StreamGroupInfo.java index 1aaaf38f1e..0531bb8fb5 100644 --- a/src/main/java/redis/clients/jedis/resps/StreamGroupInfo.java +++ b/src/main/java/redis/clients/jedis/resps/StreamGroupInfo.java @@ -5,9 +5,9 @@ import redis.clients.jedis.StreamEntryID; /** - * This class holds information about a stream group. They can be access via getters. For future - * purpose there is also {@link #getGroupInfo()} method that returns a generic {@code Map} - in case - * where more info is returned from the server. + * This class holds information about a stream group. They can be accessed via getters. There is also + * {@link StreamGroupInfo#getGroupInfo()} method that returns a generic {@code Map} in case more + * info are returned from the server. */ public class StreamGroupInfo implements Serializable { diff --git a/src/main/java/redis/clients/jedis/resps/StreamInfo.java b/src/main/java/redis/clients/jedis/resps/StreamInfo.java index 8d217b7d19..a866f41e4c 100644 --- a/src/main/java/redis/clients/jedis/resps/StreamInfo.java +++ b/src/main/java/redis/clients/jedis/resps/StreamInfo.java @@ -5,11 +5,10 @@ import redis.clients.jedis.StreamEntryID; /** - * This class holds information about stream. They can be access via getters. For future purpose - * there is also {@link #getStreamInfo} method that returns a generic {@code Map} - in case where - * more info is returned from the server. + * This class holds information about stream. They can be accessed via getters. There is also + * {@link StreamInfo#getStreamInfo} method that returns a generic {@code Map} in case more info are + * returned from the server. */ - public class StreamInfo implements Serializable { public static final String LENGTH = "length"; diff --git a/src/main/java/redis/clients/jedis/resps/Tuple.java b/src/main/java/redis/clients/jedis/resps/Tuple.java index 63e63554c0..fd91454e4c 100644 --- a/src/main/java/redis/clients/jedis/resps/Tuple.java +++ b/src/main/java/redis/clients/jedis/resps/Tuple.java @@ -75,6 +75,7 @@ public double getScore() { } @Override + // TODO: element=score public String toString() { return '[' + SafeEncoder.encode(element) + ',' + score + ']'; } diff --git a/src/main/java/redis/clients/jedis/search/Document.java b/src/main/java/redis/clients/jedis/search/Document.java index b9a8904348..20149e581a 100644 --- a/src/main/java/redis/clients/jedis/search/Document.java +++ b/src/main/java/redis/clients/jedis/search/Document.java @@ -3,9 +3,13 @@ import redis.clients.jedis.util.SafeEncoder; import java.io.Serializable; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import redis.clients.jedis.Builder; +import redis.clients.jedis.BuilderFactory; +import redis.clients.jedis.util.KeyValue; /** * Document represents a single indexed document or entity in the engine @@ -15,44 +19,43 @@ public class Document implements Serializable { private static final long serialVersionUID = 4884173545291367373L; private final String id; - private double score; - private byte[] payload; - private final Map properties; - - public Document(String id, double score) { - this(id, new HashMap<>(), score); - } + private Double score; + private final Map fields; public Document(String id) { this(id, 1.0); } + public Document(String id, double score) { + this(id, new HashMap<>(), score); + } + public Document(String id, Map fields) { this(id, fields, 1.0f); } public Document(String id, Map fields, double score) { - this(id, fields, score, null); + this.id = id; + this.fields = fields; + this.score = score; } - public Document(String id, Map fields, double score, byte[] payload) { + private Document(String id, Double score, Map fields) { this.id = id; - this.properties = new HashMap<>(fields); this.score = score; - this.payload = payload; + this.fields = fields; } public Iterable> getProperties() { - return properties.entrySet(); + return fields.entrySet(); } public static Document load(String id, double score, byte[] payload, List fields) { - return Document.load(id, score, payload, fields, true); + return Document.load(id, score, fields, true); } - public static Document load(String id, double score, byte[] payload, List fields, boolean decode) { + public static Document load(String id, double score, List fields, boolean decode) { Document ret = new Document(id, score); - ret.payload = payload; if (fields != null) { for (int i = 0; i < fields.size(); i += 2) { byte[] rawKey = fields.get(i); @@ -65,9 +68,18 @@ public static Document load(String id, double score, byte[] payload, List SEARCH_DOCUMENT = new Builder() { + + private static final String ID_STR = "id"; + private static final String SCORE_STR = "score"; + // private static final String FIELDS_STR = "fields"; + private static final String FIELDS_STR = "extra_attributes"; + + @Override + public Document build(Object data) { + List list = (List) data; + String id = null; + Double score = null; + Map fields = null; + for (KeyValue kv : list) { + String key = BuilderFactory.STRING.build(kv.getKey()); + switch (key) { + case ID_STR: + id = BuilderFactory.STRING.build(kv.getValue()); + break; + case SCORE_STR: + score = BuilderFactory.DOUBLE.build(kv.getValue()); + break; + case FIELDS_STR: + fields = BuilderFactory.ENCODED_OBJECT_MAP.build(kv.getValue()); + break; + } + } +// assert id != null; +// if (fields == null) fields = Collections.emptyMap(); + return new Document(id, score, fields); + } + }; } diff --git a/src/main/java/redis/clients/jedis/search/FTSearchParams.java b/src/main/java/redis/clients/jedis/search/FTSearchParams.java index e88926e1da..1bb5597085 100644 --- a/src/main/java/redis/clients/jedis/search/FTSearchParams.java +++ b/src/main/java/redis/clients/jedis/search/FTSearchParams.java @@ -9,6 +9,7 @@ import redis.clients.jedis.args.GeoUnit; import redis.clients.jedis.args.SortingOrder; import redis.clients.jedis.params.IParams; +import redis.clients.jedis.util.LazyRawable; /** * Query represents query parameters and filters to load results from the engine @@ -421,6 +422,18 @@ public FTSearchParams dialect(int dialect) { return this; } + /** + * This method will not replace the dialect if it has been already set. + * @param dialect dialect + * @return this + */ + public FTSearchParams dialectOptional(int dialect) { + if (dialect != 0 && this.dialect == null) { + this.dialect = dialect; + } + return this; + } + public boolean getNoContent() { return noContent; } diff --git a/src/main/java/redis/clients/jedis/search/FTSpellCheckParams.java b/src/main/java/redis/clients/jedis/search/FTSpellCheckParams.java index c3cde42cfb..439885a2a1 100644 --- a/src/main/java/redis/clients/jedis/search/FTSpellCheckParams.java +++ b/src/main/java/redis/clients/jedis/search/FTSpellCheckParams.java @@ -69,6 +69,18 @@ public FTSpellCheckParams dialect(int dialect) { return this; } + /** + * This method will not replace the dialect if it has been already set. + * @param dialect dialect + * @return this + */ + public FTSpellCheckParams dialectOptional(int dialect) { + if (dialect != 0 && this.dialect == null) { + this.dialect = dialect; + } + return this; + } + @Override public void addParams(CommandArguments args) { diff --git a/src/main/java/redis/clients/jedis/search/FieldName.java b/src/main/java/redis/clients/jedis/search/FieldName.java index 3e83faa8b4..9a0a9329db 100644 --- a/src/main/java/redis/clients/jedis/search/FieldName.java +++ b/src/main/java/redis/clients/jedis/search/FieldName.java @@ -3,15 +3,10 @@ import java.util.List; import redis.clients.jedis.CommandArguments; import redis.clients.jedis.params.IParams; - -import redis.clients.jedis.util.SafeEncoder; +import redis.clients.jedis.search.SearchProtocol.SearchKeyword; public class FieldName implements IParams { - private static final String AS_ENCODED = "AS"; - private static final byte[] AS_BINARY = SafeEncoder.encode(AS_ENCODED); - private static final byte[] AS = SafeEncoder.encode("AS"); - private final String name; private String attribute; @@ -35,36 +30,33 @@ public FieldName as(String attribute) { return this; } - public int addCommandEncodedArguments(List args) { - args.add(name); - if (attribute == null) { - return 1; - } + public final String getName() { + return name; + } - args.add(AS_ENCODED); - args.add(attribute); - return 3; + public final String getAttribute() { + return attribute; } - public int addCommandBinaryArguments(List args) { - args.add(SafeEncoder.encode(name)); + public int addCommandArguments(List args) { + args.add(name); if (attribute == null) { return 1; } - args.add(AS_BINARY); - args.add(SafeEncoder.encode(attribute)); + args.add(SearchKeyword.AS); + args.add(attribute); return 3; } public int addCommandArguments(CommandArguments args) { - args.add(SafeEncoder.encode(name)); + args.add(name); if (attribute == null) { return 1; } - args.add(AS); - args.add(SafeEncoder.encode(attribute)); + args.add(SearchKeyword.AS); + args.add(attribute); return 3; } @@ -73,11 +65,6 @@ public void addParams(CommandArguments args) { addCommandArguments(args); } - @Deprecated // TODO: remove? - String getName() { - return name; - } - @Override public String toString() { return attribute == null ? name : (name + " AS " + attribute); diff --git a/src/main/java/redis/clients/jedis/search/FtSearchIteration.java b/src/main/java/redis/clients/jedis/search/FtSearchIteration.java new file mode 100644 index 0000000000..c856e5d780 --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/FtSearchIteration.java @@ -0,0 +1,75 @@ +package redis.clients.jedis.search; + +import java.util.Collection; +import java.util.function.IntFunction; + +import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.RedisProtocol; +import redis.clients.jedis.providers.ConnectionProvider; +import redis.clients.jedis.search.SearchResult.SearchResultBuilder; +import redis.clients.jedis.util.JedisCommandIterationBase; + +public class FtSearchIteration extends JedisCommandIterationBase { + + private int batchStart; + private final int batchSize; + private final IntFunction args; + + /** + * {@link FTSearchParams#limit(int, int)} will be ignored. + */ + public FtSearchIteration(ConnectionProvider connectionProvider, int batchSize, String indexName, String query, FTSearchParams params) { + this(connectionProvider, null, batchSize, indexName, query, params); + } + + /** + * {@link Query#limit(java.lang.Integer, java.lang.Integer)} will be ignored. + */ + public FtSearchIteration(ConnectionProvider connectionProvider, int batchSize, String indexName, Query query) { + this(connectionProvider, null, batchSize, indexName, query); + } + + /** + * {@link FTSearchParams#limit(int, int)} will be ignored. + */ + public FtSearchIteration(ConnectionProvider connectionProvider, RedisProtocol protocol, int batchSize, String indexName, String query, FTSearchParams params) { + super(connectionProvider, protocol == RedisProtocol.RESP3 ? SearchResult.SEARCH_RESULT_BUILDER + : new SearchResultBuilder(!params.getNoContent(), params.getWithScores(), true)); + this.batchSize = batchSize; + this.args = (limitFirst) -> new CommandArguments(SearchProtocol.SearchCommand.SEARCH) + .add(indexName).add(query).addParams(params.limit(limitFirst, this.batchSize)); + } + + /** + * {@link Query#limit(java.lang.Integer, java.lang.Integer)} will be ignored. + */ + public FtSearchIteration(ConnectionProvider connectionProvider, RedisProtocol protocol, int batchSize, String indexName, Query query) { + super(connectionProvider, protocol == RedisProtocol.RESP3 ? SearchResult.SEARCH_RESULT_BUILDER + : new SearchResultBuilder(!query.getNoContent(), query.getWithScores(), true)); + this.batchSize = batchSize; + this.args = (limitFirst) -> new CommandArguments(SearchProtocol.SearchCommand.SEARCH) + .add(indexName).addParams(query.limit(limitFirst, this.batchSize)); + } + + @Override + protected boolean isNodeCompleted(SearchResult reply) { + return batchStart >= reply.getTotalResults() - batchSize; + } + + @Override + protected CommandArguments initCommandArguments() { + batchStart = 0; + return args.apply(batchStart); + } + + @Override + protected CommandArguments nextCommandArguments(SearchResult lastReply) { + batchStart += batchSize; + return args.apply(batchStart); + } + + @Override + protected Collection convertBatchToData(SearchResult batch) { + return batch.getDocuments(); + } +} diff --git a/src/main/java/redis/clients/jedis/search/IndexDefinition.java b/src/main/java/redis/clients/jedis/search/IndexDefinition.java index c652453da5..924863e387 100644 --- a/src/main/java/redis/clients/jedis/search/IndexDefinition.java +++ b/src/main/java/redis/clients/jedis/search/IndexDefinition.java @@ -16,14 +16,12 @@ public enum Type { } private final Type type; - private boolean async = false; private String[] prefixes; private String filter; private String languageField; private String language; private String scoreFiled; private double score = 1.0; // Default score when score isn't defined - private String payloadField; public IndexDefinition() { this(null); @@ -37,15 +35,6 @@ public Type getType() { return type; } - public boolean isAsync() { - return async; - } - - public IndexDefinition setAsync(boolean async) { - this.async = async; - return this; - } - public String[] getPrefixes() { return prefixes; } @@ -100,19 +89,6 @@ public IndexDefinition setScore(double score) { return this; } - public String getPayloadField() { - return payloadField; - } - - /** - * @deprecated Since RediSearch 2.0.0, PAYLOAD_FIELD option is deprecated. - */ - @Deprecated - public IndexDefinition setPayloadField(String payloadField) { - this.payloadField = payloadField; - return this; - } - @Override public void addParams(CommandArguments args) { @@ -121,10 +97,6 @@ public void addParams(CommandArguments args) { args.add(type.name()); } - if (async) { - args.add(SearchKeyword.ASYNC.name()); - } - if (prefixes != null && prefixes.length > 0) { args.add(SearchKeyword.PREFIX.name()); args.add(Integer.toString(prefixes.length)); @@ -155,10 +127,5 @@ public void addParams(CommandArguments args) { args.add(SearchKeyword.SCORE.name()); args.add(Double.toString(score)); } - - if (payloadField != null) { - args.add(SearchKeyword.PAYLOAD_FIELD.name()); - args.add(payloadField); - } } } diff --git a/src/main/java/redis/clients/jedis/search/Query.java b/src/main/java/redis/clients/jedis/search/Query.java index 06b2339523..66cba96acf 100644 --- a/src/main/java/redis/clients/jedis/search/Query.java +++ b/src/main/java/redis/clients/jedis/search/Query.java @@ -9,6 +9,7 @@ import redis.clients.jedis.Protocol; import redis.clients.jedis.params.IParams; import redis.clients.jedis.search.SearchProtocol.SearchKeyword; +import redis.clients.jedis.util.LazyRawable; import redis.clients.jedis.util.SafeEncoder; /** @@ -138,7 +139,6 @@ public HighlightTags(String open, String close) { private boolean _noContent = false; private boolean _noStopwords = false; private boolean _withScores = false; - private boolean _withPayloads = false; private String _language = null; private String[] _fields = null; private String[] _keys = null; @@ -150,14 +150,13 @@ public HighlightTags(String open, String close) { private String summarizeSeparator = null; private int summarizeNumFragments = -1; private int summarizeFragmentLen = -1; - private byte[] _payload = null; private String _sortBy = null; private boolean _sortAsc = true; private boolean wantsHighlight = false; private boolean wantsSummarize = false; private String _scorer = null; private Map _params = null; - private int _dialect = 0; + private Integer _dialect; private int _slop = -1; private long _timeout = -1; private boolean _inOrder = false; @@ -192,9 +191,6 @@ public void addParams(CommandArguments args) { if (_withScores) { args.add(SearchKeyword.WITHSCORES.getRaw()); } - if (_withPayloads) { - args.add(SearchKeyword.WITHPAYLOADS.getRaw()); - } if (_language != null) { args.add(SearchKeyword.LANGUAGE.getRaw()); args.add(SafeEncoder.encode(_language)); @@ -219,11 +215,6 @@ public void addParams(CommandArguments args) { args.add((_sortAsc ? SearchKeyword.ASC : SearchKeyword.DESC).getRaw()); } - if (_payload != null) { - args.add(SearchKeyword.PAYLOAD.getRaw()); - args.add(_payload); - } - if (_paging.offset != 0 || _paging.num != 10) { args.add(SearchKeyword.LIMIT.getRaw()).add(Protocol.toByteArray(_paging.offset)).add(Protocol.toByteArray(_paging.num)); } @@ -308,7 +299,7 @@ public void addParams(CommandArguments args) { } } - if (_dialect != 0) { + if (_dialect != null) { args.add(SearchKeyword.DIALECT.getRaw()); args.add(_dialect); } @@ -357,18 +348,6 @@ public Query addFilter(Filter f) { return this; } - /** - * Set the query payload to be evaluated by the scoring function - * - * @return the query object itself - * @deprecated Since RediSearch 2.0.0, PAYLOAD option is deprecated. - */ - @Deprecated - public Query setPayload(byte[] payload) { - _payload = payload; - return this; - } - /** * Set the query to verbatim mode, disabling stemming and query expansion * @@ -418,22 +397,6 @@ public Query setWithScores() { return this; } - public boolean getWithPayloads() { - return _withPayloads; - } - - /** - * Set the query to return object payloads, if any were given - * - * @return the query object itself - * @deprecated Since RediSearch 2.0.0, WITHPAYLOADS option is deprecated. - */ - @Deprecated - public Query setWithPayload() { - this._withPayloads = true; - return this; - } - /** * Set the query language, for stemming purposes *

@@ -581,6 +544,18 @@ public Query dialect(int dialect) { return this; } + /** + * This method will not replace the dialect if it has been already set. + * @param dialect dialect + * @return this + */ + public Query dialectOptional(int dialect) { + if (dialect != 0 && this._dialect == null) { + this._dialect = dialect; + } + return this; + } + /** * Set the slop to execute the query accordingly * diff --git a/src/main/java/redis/clients/jedis/search/RediSearchCommands.java b/src/main/java/redis/clients/jedis/search/RediSearchCommands.java index d128babf83..f361689aea 100644 --- a/src/main/java/redis/clients/jedis/search/RediSearchCommands.java +++ b/src/main/java/redis/clients/jedis/search/RediSearchCommands.java @@ -40,6 +40,16 @@ default String ftAlter(String indexName, SchemaField... schemaFields) { String ftAlter(String indexName, Iterable schemaFields); + String ftAliasAdd(String aliasName, String indexName); + + String ftAliasUpdate(String aliasName, String indexName); + + String ftAliasDel(String aliasName); + + String ftDropIndex(String indexName); + + String ftDropIndexDD(String indexName); + default SearchResult ftSearch(String indexName) { return ftSearch(indexName, "*"); } @@ -50,6 +60,7 @@ default SearchResult ftSearch(String indexName) { SearchResult ftSearch(String indexName, Query query); + @Deprecated SearchResult ftSearch(byte[] indexName, Query query); String ftExplain(String indexName, Query query); @@ -71,10 +82,6 @@ Map.Entry> ftProfileSearch(String indexName, Map.Entry> ftProfileSearch(String indexName, FTProfileParams profileParams, String query, FTSearchParams searchParams); - String ftDropIndex(String indexName); - - String ftDropIndexDD(String indexName); - String ftSynUpdate(String indexName, String synonymGroupId, String... terms); Map> ftSynDump(String indexName); @@ -100,15 +107,9 @@ Map> ftSpellCheck(String index, String query, Set ftTagVals(String indexName, String fieldName); - String ftAliasAdd(String aliasName, String indexName); - - String ftAliasUpdate(String aliasName, String indexName); - - String ftAliasDel(String aliasName); - - Map ftConfigGet(String option); + Map ftConfigGet(String option); - Map ftConfigGet(String indexName, String option); + Map ftConfigGet(String indexName, String option); String ftConfigSet(String option, String value); @@ -130,5 +131,5 @@ Map> ftSpellCheck(String index, String query, long ftSugLen(String key); - List ftList(); + Set ftList(); } diff --git a/src/main/java/redis/clients/jedis/search/RediSearchPipelineCommands.java b/src/main/java/redis/clients/jedis/search/RediSearchPipelineCommands.java index 5598a10dc1..c5765a6f31 100644 --- a/src/main/java/redis/clients/jedis/search/RediSearchPipelineCommands.java +++ b/src/main/java/redis/clients/jedis/search/RediSearchPipelineCommands.java @@ -41,6 +41,16 @@ default Response ftAlter(String indexName, SchemaField... schemaFields) Response ftAlter(String indexName, Iterable schemaFields); + Response ftAliasAdd(String aliasName, String indexName); + + Response ftAliasUpdate(String aliasName, String indexName); + + Response ftAliasDel(String aliasName); + + Response ftDropIndex(String indexName); + + Response ftDropIndexDD(String indexName); + default Response ftSearch(String indexName) { return ftSearch(indexName, "*"); } @@ -51,6 +61,7 @@ default Response ftSearch(String indexName) { Response ftSearch(String indexName, Query query); + @Deprecated Response ftSearch(byte[] indexName, Query query); Response ftExplain(String indexName, Query query); @@ -59,14 +70,6 @@ default Response ftSearch(String indexName) { Response ftAggregate(String indexName, AggregationBuilder aggr); - Response ftCursorRead(String indexName, long cursorId, int count); - - Response ftCursorDel(String indexName, long cursorId); - - Response ftDropIndex(String indexName); - - Response ftDropIndexDD(String indexName); - Response ftSynUpdate(String indexName, String synonymGroupId, String... terms); Response>> ftSynDump(String indexName); @@ -92,15 +95,9 @@ Response>> ftSpellCheck(String index, String que Response> ftTagVals(String indexName, String fieldName); - Response ftAliasAdd(String aliasName, String indexName); - - Response ftAliasUpdate(String aliasName, String indexName); - - Response ftAliasDel(String aliasName); - - Response> ftConfigGet(String option); + Response> ftConfigGet(String option); - Response> ftConfigGet(String indexName, String option); + Response> ftConfigGet(String indexName, String option); Response ftConfigSet(String option, String value); diff --git a/src/main/java/redis/clients/jedis/search/RediSearchUtil.java b/src/main/java/redis/clients/jedis/search/RediSearchUtil.java index 1200a5f253..14cb963bde 100644 --- a/src/main/java/redis/clients/jedis/search/RediSearchUtil.java +++ b/src/main/java/redis/clients/jedis/search/RediSearchUtil.java @@ -1,12 +1,38 @@ package redis.clients.jedis.search; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; + import redis.clients.jedis.util.SafeEncoder; public class RediSearchUtil { + /** + * Jedis' {@code hset} methods do not support {@link Object}s as values. This method eases process + * of converting a {@link Map} with Objects as values so that the returning Map can be set to a + * {@code hset} method. + * @param input map with object value + * @return map with string value + */ public static Map toStringMap(Map input) { + return toStringMap(input, false); + } + + /** + * Jedis' {@code hset} methods do not support {@link Object}s as values. This method eases process + * of converting a {@link Map} with Objects as values so that the returning Map can be set to a + * {@code hset} method. + * @param input map with object value + * @param stringEscape whether to escape the String objects + * @return map with string value + */ + public static Map toStringMap(Map input, boolean stringEscape) { Map output = new HashMap<>(input.size()); for (Map.Entry entry : input.entrySet()) { String key = entry.getKey(); @@ -21,15 +47,69 @@ public static Map toStringMap(Map input) { redis.clients.jedis.GeoCoordinate geo = (redis.clients.jedis.GeoCoordinate) obj; str = geo.getLongitude() + "," + geo.getLatitude(); } else if (obj instanceof String) { - str = (String) obj; + str = stringEscape ? escape((String) obj) : (String) obj; } else { - str = obj.toString(); + str = String.valueOf(obj); } output.put(key, str); } return output; } + /** + * x86 systems are little-endian and Java defaults to big-endian. This causes mismatching query + * results when RediSearch is running in a x86 system. This method helps to convert concerned + * arrays. + * @param input float array + * @return byte array + */ + public static byte[] toByteArray(float[] input) { + byte[] bytes = new byte[Float.BYTES * input.length]; + ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asFloatBuffer().put(input); + return bytes; + } + + /** + * @deprecated Use {@link RediSearchUtil#toByteArray(float[])}. + */ + @Deprecated + public static byte[] ToByteArray(float[] input) { + return toByteArray(input); + } + + private static final Set ESCAPE_CHARS = new HashSet<>(Arrays.asList(// + ',', '.', '<', '>', '{', '}', '[', // + ']', '"', '\'', ':', ';', '!', '@', // + '#', '$', '%', '^', '&', '*', '(', // + ')', '-', '+', '=', '~', '|' // + )); + + public static String escape(String text) { + return escape(text, false); + } + + public static String escapeQuery(String query) { + return escape(query, true); + } + + public static String escape(String text, boolean querying) { + char[] chars = text.toCharArray(); + + StringBuilder sb = new StringBuilder(); + for (char ch : chars) { + if (ESCAPE_CHARS.contains(ch) + || (querying && ch == ' ')) { + sb.append("\\"); + } + sb.append(ch); + } + return sb.toString(); + } + + public static String unescape(String text) { + return text.replace("\\", ""); + } + private RediSearchUtil() { throw new InstantiationError("Must not instantiate this class"); } diff --git a/src/main/java/redis/clients/jedis/search/Schema.java b/src/main/java/redis/clients/jedis/search/Schema.java index d9fa1c73e5..17f01cc9de 100644 --- a/src/main/java/redis/clients/jedis/search/Schema.java +++ b/src/main/java/redis/clients/jedis/search/Schema.java @@ -21,7 +21,7 @@ public enum FieldType { VECTOR } - @Deprecated // TODO: this should be private + // public for CommandObjects public final List fields; public Schema() { @@ -161,10 +161,9 @@ public String toString() { public static class Field implements IParams { protected final FieldName fieldName; - @Deprecated public final String name; - @Deprecated public final FieldType type; - @Deprecated public final boolean sortable; - @Deprecated public final boolean noIndex; + protected final FieldType type; + protected final boolean sortable; + protected final boolean noIndex; public Field(String name, FieldType type) { this(name, type, false, false); @@ -184,7 +183,6 @@ public Field(FieldName name, FieldType type) { public Field(FieldName name, FieldType type, boolean sortable, boolean noIndex) { this.fieldName = name; - this.name = this.fieldName.getName(); this.type = type; this.sortable = sortable; this.noIndex = noIndex; diff --git a/src/main/java/redis/clients/jedis/search/SearchBuilderFactory.java b/src/main/java/redis/clients/jedis/search/SearchBuilderFactory.java index 7083d9e4f3..8702b4a307 100644 --- a/src/main/java/redis/clients/jedis/search/SearchBuilderFactory.java +++ b/src/main/java/redis/clients/jedis/search/SearchBuilderFactory.java @@ -3,34 +3,21 @@ import static redis.clients.jedis.BuilderFactory.STRING; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import redis.clients.jedis.Builder; import redis.clients.jedis.BuilderFactory; -import redis.clients.jedis.search.aggr.AggregationResult; import redis.clients.jedis.util.DoublePrecision; +import redis.clients.jedis.util.KeyValue; import redis.clients.jedis.util.SafeEncoder; public final class SearchBuilderFactory { - public static final Builder SEARCH_AGGREGATION_RESULT = new Builder() { - @Override - public AggregationResult build(Object data) { - return new AggregationResult(data); - } - }; - - public static final Builder SEARCH_AGGREGATION_RESULT_WITH_CURSOR = new Builder() { - @Override - public AggregationResult build(Object data) { - List list = (List) data; - return new AggregationResult(list.get(0), (long) list.get(1)); - } - }; - public static final Builder> SEARCH_PROFILE_PROFILE = new Builder>() { private final String ITERATORS_PROFILE_STR = "Iterators profile"; @@ -53,7 +40,7 @@ public Map build(Object data) { if (attributeName.equals(ITERATORS_PROFILE_STR)) { attributeValue = parseIterators(value); } else if (attributeName.endsWith(" time")) { - attributeValue = DoublePrecision.parseFloatingPointNumber((String) value); + attributeValue = DoublePrecision.parseEncodedFloatingPointNumber(value); } else { attributeValue = value; } @@ -86,7 +73,7 @@ private Map parseResultProcessors(Object data) { String key = (String) list.get(i); Object value = list.get(i + 1); if (key.equals("Time")) { - value = DoublePrecision.parseFloatingPointNumber((String) value); + value = DoublePrecision.parseEncodedFloatingPointNumber(value); } map.put(key, value); } @@ -112,7 +99,7 @@ private Object parseIterators(Object data) { String key = (String) iteratorsAttributeList.get(i); Object value = iteratorsAttributeList.get(i + 1); if (key.equals("Time")) { - value = DoublePrecision.parseFloatingPointNumber((String) value); + value = DoublePrecision.parseEncodedFloatingPointNumber(value); } iteratorsProfile.put(key, value); } @@ -131,7 +118,14 @@ private Object parseIterators(Object data) { public static final Builder>> SEARCH_SYNONYM_GROUPS = new Builder>>() { @Override public Map> build(Object data) { - List list = (List) data; + List list = (List) data; + if (list.isEmpty()) return Collections.emptyMap(); + + if (list.get(0) instanceof KeyValue) { + return ((List) data).stream().collect(Collectors.toMap( + kv -> STRING.build(kv.getKey()), kv -> BuilderFactory.STRING_LIST.build(kv.getValue()))); + } + Map> dump = new HashMap<>(list.size() / 2, 1f); for (int i = 0; i < list.size(); i += 2) { dump.put(STRING.build(list.get(i)), BuilderFactory.STRING_LIST.build(list.get(i + 1))); @@ -143,15 +137,33 @@ public Map> build(Object data) { public static final Builder>> SEARCH_SPELLCHECK_RESPONSE = new Builder>>() { - private final String TERM = "TERM"; + private static final String TERM = "TERM"; + private static final String RESULTS = "results"; @Override public Map> build(Object data) { - List rawTerms = (List) data; - Map> returnTerms = new LinkedHashMap<>(rawTerms.size()); + List rawDataList = (List) data; + if (rawDataList.isEmpty()) return Collections.emptyMap(); + + if (rawDataList.get(0) instanceof KeyValue) { + KeyValue rawData = (KeyValue) rawDataList.get(0); + String header = STRING.build(rawData.getKey()); + if (!RESULTS.equals(header)) { + throw new IllegalStateException("Unrecognized header: " + header); + } + + return ((List) rawData.getValue()).stream().collect(Collectors.toMap( + rawTerm -> STRING.build(rawTerm.getKey()), + rawTerm -> ((List>) rawTerm.getValue()).stream() + .collect(Collectors.toMap(entry -> STRING.build(entry.get(0).getKey()), + entry -> BuilderFactory.DOUBLE.build(entry.get(0).getValue()))), + (x, y) -> x, LinkedHashMap::new)); + } + + Map> returnTerms = new LinkedHashMap<>(rawDataList.size()); - for (Object rawTerm : rawTerms) { - List rawElements = (List) rawTerm; + for (Object rawData : rawDataList) { + List rawElements = (List) rawData; String header = STRING.build(rawElements.get(0)); if (!TERM.equals(header)) { diff --git a/src/main/java/redis/clients/jedis/search/SearchProtocol.java b/src/main/java/redis/clients/jedis/search/SearchProtocol.java index 9812a203e2..7f2ad482fb 100644 --- a/src/main/java/redis/clients/jedis/search/SearchProtocol.java +++ b/src/main/java/redis/clients/jedis/search/SearchProtocol.java @@ -49,16 +49,14 @@ public byte[] getRaw() { public enum SearchKeyword implements Rawable { - SCHEMA, TEXT, TAG, NUMERIC, GEO, VECTOR, VERBATIM, NOCONTENT, NOSTOPWORDS, WITHSCORES, LANGUAGE, - INFIELDS, SORTBY, ASC, DESC, LIMIT, HIGHLIGHT, FIELDS, TAGS, SUMMARIZE, FRAGS, LEN, SEPARATOR, - INKEYS, RETURN, FILTER, GEOFILTER, ADD, INCR, MAX, FUZZY, READ, DEL, DD, TEMPORARY, STOPWORDS, - NOFREQS, NOFIELDS, NOOFFSETS, NOHL, SET, GET, ON, SORTABLE, UNF, PREFIX, LANGUAGE_FIELD, SCORE, - SCORE_FIELD, SCORER, PARAMS, AS, DIALECT, SLOP, TIMEOUT, INORDER, EXPANDER, MAXTEXTFIELDS, - SKIPINITIALSCAN, WITHSUFFIXTRIE, NOSTEM, NOINDEX, PHONETIC, WEIGHT, CASESENSITIVE, /*EXPLAINSCORE,*/ - LOAD, APPLY, GROUPBY, MAXIDLE, WITHCURSOR, DISTANCE, TERMS, INCLUDE, EXCLUDE, - SEARCH, AGGREGATE, QUERY, LIMITED, - @Deprecated ASYNC, @Deprecated PAYLOAD_FIELD, @Deprecated WITHPAYLOADS, @Deprecated PAYLOAD, - @Deprecated COUNT; + SCHEMA, TEXT, TAG, NUMERIC, GEO, GEOSHAPE, VECTOR, VERBATIM, NOCONTENT, NOSTOPWORDS, WITHSCORES, + LANGUAGE, INFIELDS, SORTBY, ASC, DESC, LIMIT, HIGHLIGHT, FIELDS, TAGS, SUMMARIZE, FRAGS, LEN, + SEPARATOR, INKEYS, RETURN, FILTER, GEOFILTER, ADD, INCR, MAX, FUZZY, READ, DEL, DD, TEMPORARY, + STOPWORDS, NOFREQS, NOFIELDS, NOOFFSETS, NOHL, SET, GET, ON, SORTABLE, UNF, PREFIX, + LANGUAGE_FIELD, SCORE, SCORE_FIELD, SCORER, PARAMS, AS, DIALECT, SLOP, TIMEOUT, INORDER, + EXPANDER, MAXTEXTFIELDS, SKIPINITIALSCAN, WITHSUFFIXTRIE, NOSTEM, NOINDEX, PHONETIC, WEIGHT, + CASESENSITIVE, LOAD, APPLY, GROUPBY, MAXIDLE, WITHCURSOR, DISTANCE, TERMS, INCLUDE, EXCLUDE, + SEARCH, AGGREGATE, QUERY, LIMITED, COUNT, REDUCE; private final byte[] raw; diff --git a/src/main/java/redis/clients/jedis/search/SearchResult.java b/src/main/java/redis/clients/jedis/search/SearchResult.java index 9d1bef2536..cc28cc942a 100644 --- a/src/main/java/redis/clients/jedis/search/SearchResult.java +++ b/src/main/java/redis/clients/jedis/search/SearchResult.java @@ -1,9 +1,12 @@ package redis.clients.jedis.search; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; import redis.clients.jedis.Builder; import redis.clients.jedis.BuilderFactory; +import redis.clients.jedis.util.KeyValue; /** * SearchResult encapsulates the returned result from a search query. It contains publicly @@ -25,20 +28,24 @@ public long getTotalResults() { } public List getDocuments() { - return documents; + return Collections.unmodifiableList(documents); + } + + @Override + public String toString() { + return getClass().getSimpleName() + "{Total results:" + totalResults + + ", Documents:" + documents + "}"; } public static class SearchResultBuilder extends Builder { private final boolean hasContent; private final boolean hasScores; - private final boolean hasPayloads; private final boolean decode; - public SearchResultBuilder(boolean hasContent, boolean hasScores, boolean hasPayloads, boolean decode) { + public SearchResultBuilder(boolean hasContent, boolean hasScores, boolean decode) { this.hasContent = hasContent; this.hasScores = hasScores; - this.hasPayloads = hasPayloads; this.decode = decode; } @@ -49,7 +56,6 @@ public SearchResult build(Object data) { int step = 1; int scoreOffset = 0; int contentOffset = 1; - int payloadOffset = 0; if (hasScores) { step += 1; scoreOffset = 1; @@ -57,11 +63,6 @@ public SearchResult build(Object data) { } if (hasContent) { step += 1; - if (hasPayloads) { - payloadOffset = scoreOffset + 1; - step += 1; - contentOffset += 1; - } } // the first element is always the number of results @@ -72,13 +73,39 @@ public SearchResult build(Object data) { String id = BuilderFactory.STRING.build(resp.get(i)); double score = hasScores ? BuilderFactory.DOUBLE.build(resp.get(i + scoreOffset)) : 1.0; - byte[] payload = hasPayloads ? (byte[]) resp.get(i + payloadOffset) : null; List fields = hasContent ? (List) resp.get(i + contentOffset) : null; - documents.add(Document.load(id, score, payload, fields, decode)); + documents.add(Document.load(id, score, fields, decode)); } return new SearchResult(totalResults, documents); } } + + public static Builder SEARCH_RESULT_BUILDER = new Builder() { + + private static final String TOTAL_RESULTS_STR = "total_results"; + private static final String RESULTS_STR = "results"; + + @Override + public SearchResult build(Object data) { + List list = (List) data; + long totalResults = -1; + List results = null; + for (KeyValue kv : list) { + String key = BuilderFactory.STRING.build(kv.getKey()); + switch (key) { + case TOTAL_RESULTS_STR: + totalResults = BuilderFactory.LONG.build(kv.getValue()); + break; + case RESULTS_STR: + results = ((List) kv.getValue()).stream() + .map(Document.SEARCH_DOCUMENT::build) + .collect(Collectors.toList()); + break; + } + } + return new SearchResult(totalResults, results); + } + }; } diff --git a/src/main/java/redis/clients/jedis/search/aggr/AggregationBuilder.java b/src/main/java/redis/clients/jedis/search/aggr/AggregationBuilder.java index c26f937b1f..eb8e039d02 100644 --- a/src/main/java/redis/clients/jedis/search/aggr/AggregationBuilder.java +++ b/src/main/java/redis/clients/jedis/search/aggr/AggregationBuilder.java @@ -1,19 +1,30 @@ package redis.clients.jedis.search.aggr; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.Protocol; +import redis.clients.jedis.params.IParams; import redis.clients.jedis.search.FieldName; -import redis.clients.jedis.util.SafeEncoder; +import redis.clients.jedis.search.SearchProtocol.SearchKeyword; +import redis.clients.jedis.util.LazyRawable; /** * @author Guy Korland */ -public class AggregationBuilder { +public class AggregationBuilder implements IParams { - private final List args = new ArrayList<>(); + private final List aggrArgs = new ArrayList<>(); + private Integer dialect; private boolean isWithCursor = false; public AggregationBuilder(String query) { - args.add(query); + aggrArgs.add(query); } public AggregationBuilder() { @@ -25,26 +36,27 @@ public AggregationBuilder load(String... fields) { } public AggregationBuilder load(FieldName... fields) { - args.add("LOAD"); - final int loadCountIndex = args.size(); - args.add(null); + aggrArgs.add(SearchKeyword.LOAD); + LazyRawable rawLoadCount = new LazyRawable(); + aggrArgs.add(rawLoadCount); int loadCount = 0; for (FieldName fn : fields) { - loadCount += fn.addCommandEncodedArguments(args); + loadCount += fn.addCommandArguments(aggrArgs); } - args.set(loadCountIndex, Integer.toString(loadCount)); + rawLoadCount.setRaw(Protocol.toByteArray(loadCount)); return this; } public AggregationBuilder loadAll() { - args.add("LOAD"); - args.add("*"); + aggrArgs.add(SearchKeyword.LOAD); + aggrArgs.add(Protocol.BYTES_ASTERISK); return this; } public AggregationBuilder limit(int offset, int count) { - Limit limit = new Limit(offset, count); - limit.addArgs(args); + aggrArgs.add(SearchKeyword.LIMIT); + aggrArgs.add(offset); + aggrArgs.add(count); return this; } @@ -53,21 +65,11 @@ public AggregationBuilder limit(int count) { } public AggregationBuilder sortBy(SortedField... fields) { - args.add("SORTBY"); - args.add(Integer.toString(fields.length * 2)); + aggrArgs.add(SearchKeyword.SORTBY); + aggrArgs.add(Integer.toString(fields.length * 2)); for (SortedField field : fields) { - args.add(field.getField()); - args.add(field.getOrder()); - } - - return this; - } - - public AggregationBuilder sortBy(int max, SortedField... fields) { - sortBy(fields); - if (max > 0) { - args.add("MAX"); - args.add(Integer.toString(max)); + aggrArgs.add(field.getField()); + aggrArgs.add(field.getOrder()); } return this; } @@ -80,20 +82,51 @@ public AggregationBuilder sortByDesc(String field) { return sortBy(SortedField.desc(field)); } + /** + * {@link AggregationBuilder#sortBy(redis.clients.jedis.search.aggr.SortedField...)} + * (or {@link AggregationBuilder#sortByAsc(java.lang.String)} + * or {@link AggregationBuilder#sortByDesc(java.lang.String)}) + * MUST BE called JUST BEFORE this. + * @param max limit + * @return this + */ + public AggregationBuilder sortByMax(int max) { + aggrArgs.add(SearchKeyword.MAX); + aggrArgs.add(max); + return this; + } + + /** + * Shortcut to {@link AggregationBuilder#sortBy(redis.clients.jedis.search.aggr.SortedField...)} + * and {@link AggregationBuilder#sortByMax(int)}. + * @param max limit + * @param fields sorted fields + * @return this + */ + public AggregationBuilder sortBy(int max, SortedField... fields) { + sortBy(fields); + sortByMax(max); + return this; + } + public AggregationBuilder apply(String projection, String alias) { - args.add("APPLY"); - args.add(projection); - args.add("AS"); - args.add(alias); + aggrArgs.add(SearchKeyword.APPLY); + aggrArgs.add(projection); + aggrArgs.add(SearchKeyword.AS); + aggrArgs.add(alias); + return this; + } + + public AggregationBuilder groupBy(Group group) { + aggrArgs.add(SearchKeyword.GROUPBY); + group.addArgs(aggrArgs); return this; } public AggregationBuilder groupBy(Collection fields, Collection reducers) { String[] fieldsArr = new String[fields.size()]; Group g = new Group(fields.toArray(fieldsArr)); - for (Reducer r : reducers) { - g.reduce(r); - } + reducers.forEach((r) -> g.reduce(r)); groupBy(g); return this; } @@ -102,83 +135,77 @@ public AggregationBuilder groupBy(String field, Reducer... reducers) { return groupBy(Collections.singletonList(field), Arrays.asList(reducers)); } - public AggregationBuilder groupBy(Group group) { - args.add("GROUPBY"); - group.addArgs(args); + public AggregationBuilder filter(String expression) { + aggrArgs.add(SearchKeyword.FILTER); + aggrArgs.add(expression); return this; } - public AggregationBuilder filter(String expression) { - args.add("FILTER"); - args.add(expression); + public AggregationBuilder cursor(int count) { + isWithCursor = true; + aggrArgs.add(SearchKeyword.WITHCURSOR); + aggrArgs.add(SearchKeyword.COUNT); + aggrArgs.add(count); return this; } public AggregationBuilder cursor(int count, long maxIdle) { isWithCursor = true; - if (count > 0) { - args.add("WITHCURSOR"); - args.add("COUNT"); - args.add(Integer.toString(count)); - if (maxIdle < Long.MAX_VALUE && maxIdle >= 0) { - args.add("MAXIDLE"); - args.add(Long.toString(maxIdle)); - } - } + aggrArgs.add(SearchKeyword.WITHCURSOR); + aggrArgs.add(SearchKeyword.COUNT); + aggrArgs.add(count); + aggrArgs.add(SearchKeyword.MAXIDLE); + aggrArgs.add(maxIdle); return this; } public AggregationBuilder verbatim() { - args.add("VERBATIM"); + aggrArgs.add(SearchKeyword.VERBATIM); return this; } public AggregationBuilder timeout(long timeout) { - if (timeout >= 0) { - args.add("TIMEOUT"); - args.add(Long.toString(timeout)); - } + aggrArgs.add(SearchKeyword.TIMEOUT); + aggrArgs.add(timeout); return this; } public AggregationBuilder params(Map params) { - if (params.size() >= 1) { - args.add("PARAMS"); - args.add(Integer.toString(params.size() * 2)); - for (Map.Entry entry : params.entrySet()) { - args.add(entry.getKey()); - args.add(String.valueOf(entry.getValue())); - } - } - + aggrArgs.add(SearchKeyword.PARAMS); + aggrArgs.add(params.size() * 2); + params.forEach((k, v) -> { + aggrArgs.add(k); + aggrArgs.add(v); + }); return this; } public AggregationBuilder dialect(int dialect) { - args.add("DIALECT"); - args.add(Integer.toString(dialect)); + this.dialect = dialect; return this; } - public List getArgs() { - return Collections.unmodifiableList(args); - } - - public void serializeRedisArgs(List redisArgs) { - for (String s : getArgs()) { - redisArgs.add(SafeEncoder.encode(s)); - } - } - - public String getArgsString() { - StringJoiner sj = new StringJoiner(" "); - for (String s : getArgs()) { - sj.add(s); + /** + * This method will not replace the dialect if it has been already set. + * @param dialect dialect + * @return this + */ + public AggregationBuilder dialectOptional(int dialect) { + if (dialect != 0 && this.dialect == null) { + this.dialect = dialect; } - return sj.toString(); + return this; } public boolean isWithCursor() { return isWithCursor; } + + @Override + public void addParams(CommandArguments commArgs) { + commArgs.addObjects(aggrArgs); + if (dialect != null) { + commArgs.add(SearchKeyword.DIALECT).add(dialect); + } + } } diff --git a/src/main/java/redis/clients/jedis/search/aggr/AggregationResult.java b/src/main/java/redis/clients/jedis/search/aggr/AggregationResult.java index fdfa4e23cd..cec65f9cd9 100644 --- a/src/main/java/redis/clients/jedis/search/aggr/AggregationResult.java +++ b/src/main/java/redis/clients/jedis/search/aggr/AggregationResult.java @@ -1,32 +1,32 @@ package redis.clients.jedis.search.aggr; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import redis.clients.jedis.Builder; +import redis.clients.jedis.BuilderFactory; import redis.clients.jedis.exceptions.JedisDataException; +import redis.clients.jedis.util.KeyValue; import redis.clients.jedis.util.SafeEncoder; public class AggregationResult { - /** - * @deprecated Use {@link AggregationResult#getTotalResults()}. - */ - @Deprecated - public final long totalResults; + private final long totalResults; private final List> results; - private long cursorId = -1; + private Long cursorId = -1L; - public AggregationResult(Object resp, long cursorId) { + private AggregationResult(Object resp, long cursorId) { this(resp); this.cursorId = cursorId; } - public AggregationResult(Object resp) { + private AggregationResult(Object resp) { List list = (List) SafeEncoder.encodeObject(resp); // the first element is always the number of results @@ -47,12 +47,25 @@ public AggregationResult(Object resp) { } } + private AggregationResult(long totalResults, List> results) { + this.totalResults = totalResults; + this.results = results; + } + + private void setCursorId(Long cursorId) { + this.cursorId = cursorId; + } + + public Long getCursorId() { + return cursorId; + } + public long getTotalResults() { return totalResults; } public List> getResults() { - return results; + return Collections.unmodifiableList(results); } /** @@ -67,7 +80,75 @@ public Row getRow(int index) { return new Row(results.get(index)); } - public long getCursorId() { - return cursorId; - } + public static final Builder SEARCH_AGGREGATION_RESULT = new Builder() { + + private static final String TOTAL_RESULTS_STR = "total_results"; + private static final String RESULTS_STR = "results"; + // private static final String FIELDS_STR = "fields"; + private static final String FIELDS_STR = "extra_attributes"; + + @Override + public AggregationResult build(Object data) { + // return new AggregationResult(data); + List list = (List) data; + + if (list.get(0) instanceof KeyValue) { + List kvList = (List) data; + long totalResults = -1; + List> results = null; + for (KeyValue kv : kvList) { + String key = BuilderFactory.STRING.build(kv.getKey()); + switch (key) { + case TOTAL_RESULTS_STR: + totalResults = BuilderFactory.LONG.build(kv.getValue()); + break; + case RESULTS_STR: + List> resList = (List>) kv.getValue(); + results = new ArrayList<>(resList.size()); + for (List rikv : resList) { + for (KeyValue ikv : rikv) { + if (FIELDS_STR.equals(BuilderFactory.STRING.build(ikv.getKey()))) { + results.add(BuilderFactory.ENCODED_OBJECT_MAP.build(ikv.getValue())); + break; + } + } + } + break; + } + } + return new AggregationResult(totalResults, results); + } + + list = (List) SafeEncoder.encodeObject(data); + + // the first element is always the number of results + long totalResults = (Long) list.get(0); + List> results = new ArrayList<>(list.size() - 1); + + for (int i = 1; i < list.size(); i++) { + List mapList = (List) list.get(i); + Map map = new HashMap<>(mapList.size() / 2, 1f); + for (int j = 0; j < mapList.size(); j += 2) { + Object r = mapList.get(j); + if (r instanceof JedisDataException) { + throw (JedisDataException) r; + } + map.put((String) r, mapList.get(j + 1)); + } + results.add(map); + } + return new AggregationResult(totalResults, results); + } + }; + + public static final Builder SEARCH_AGGREGATION_RESULT_WITH_CURSOR = new Builder() { + @Override + public AggregationResult build(Object data) { + List list = (List) data; + // return new AggregationResult(list.get(0), (long) list.get(1)); + AggregationResult r = SEARCH_AGGREGATION_RESULT.build(list.get(0)); + r.setCursorId((Long) list.get(1)); + return r; + } + }; } diff --git a/src/main/java/redis/clients/jedis/search/aggr/FtAggregateIteration.java b/src/main/java/redis/clients/jedis/search/aggr/FtAggregateIteration.java new file mode 100644 index 0000000000..931834ed49 --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/aggr/FtAggregateIteration.java @@ -0,0 +1,48 @@ +package redis.clients.jedis.search.aggr; + +import java.util.Collection; + +import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.providers.ConnectionProvider; +import redis.clients.jedis.search.SearchProtocol; +import redis.clients.jedis.util.JedisCommandIterationBase; + +public class FtAggregateIteration extends JedisCommandIterationBase { + + private final String indexName; + private final CommandArguments args; + + /** + * {@link AggregationBuilder#cursor(int, long) CURSOR} must be set. + * @param connectionProvider connection provider + * @param indexName index name + * @param aggr cursor must be set + */ + public FtAggregateIteration(ConnectionProvider connectionProvider, String indexName, AggregationBuilder aggr) { + super(connectionProvider, AggregationResult.SEARCH_AGGREGATION_RESULT_WITH_CURSOR); + if (!aggr.isWithCursor()) throw new IllegalArgumentException("cursor must be set"); + this.indexName = indexName; + this.args = new CommandArguments(SearchProtocol.SearchCommand.AGGREGATE).add(this.indexName).addParams(aggr); + } + + @Override + protected boolean isNodeCompleted(AggregationResult reply) { + return reply.getCursorId() == 0L; + } + + @Override + protected CommandArguments initCommandArguments() { + return args; + } + + @Override + protected CommandArguments nextCommandArguments(AggregationResult lastReply) { + return new CommandArguments(SearchProtocol.SearchCommand.CURSOR).add(SearchProtocol.SearchKeyword.READ) + .add(indexName).add(lastReply.getCursorId()); + } + + @Override + protected Collection convertBatchToData(AggregationResult batch) { + return batch.getRows(); + } +} diff --git a/src/main/java/redis/clients/jedis/search/aggr/Group.java b/src/main/java/redis/clients/jedis/search/aggr/Group.java index a60cb5ac0c..6ef9220845 100644 --- a/src/main/java/redis/clients/jedis/search/aggr/Group.java +++ b/src/main/java/redis/clients/jedis/search/aggr/Group.java @@ -9,9 +9,8 @@ */ public class Group { - private final List reducers = new ArrayList<>(); private final List fields = new ArrayList<>(); - private Limit limit = new Limit(0, 0); + private final List reducers = new ArrayList<>(); public Group(String... fields) { this.fields.addAll(Arrays.asList(fields)); @@ -22,30 +21,11 @@ public Group reduce(Reducer r) { return this; } - public Group limit(Limit limit) { - this.limit = limit; - return this; - } + public void addArgs(List args) { - public void addArgs(List args) { - args.add(Integer.toString(fields.size())); + args.add(fields.size()); args.addAll(fields); - for (Reducer r : reducers) { - args.add("REDUCE"); - args.add(r.getName()); - r.addArgs(args); - String alias = r.getAlias(); - if (alias != null && !alias.isEmpty()) { - args.add("AS"); - args.add(alias); - } - } - args.addAll(limit.getArgs()); - } - public List getArgs() { - List args = new ArrayList<>(); - addArgs(args); - return args; + reducers.forEach((r) -> r.addArgs(args)); } } diff --git a/src/main/java/redis/clients/jedis/search/aggr/Limit.java b/src/main/java/redis/clients/jedis/search/aggr/Limit.java deleted file mode 100644 index 9f512c9713..0000000000 --- a/src/main/java/redis/clients/jedis/search/aggr/Limit.java +++ /dev/null @@ -1,39 +0,0 @@ -package redis.clients.jedis.search.aggr; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Created by mnunberg on 2/22/18. - */ -public class Limit { - - public static final Limit NO_LIMIT = new Limit(0, 0); - - private final int offset; - private final int count; - - public Limit(int offset, int count) { - this.offset = offset; - this.count = count; - } - - public void addArgs(List args) { - if (count == 0) { - return; - } - args.add("LIMIT"); - args.add(Integer.toString(offset)); - args.add(Integer.toString(count)); - } - - public List getArgs() { - if (count == 0) { - return Collections.emptyList(); - } - List ll = new ArrayList<>(3); - addArgs(ll); - return ll; - } -} diff --git a/src/main/java/redis/clients/jedis/search/aggr/Reducer.java b/src/main/java/redis/clients/jedis/search/aggr/Reducer.java index 858fc0f7c2..9cbfb5a00c 100644 --- a/src/main/java/redis/clients/jedis/search/aggr/Reducer.java +++ b/src/main/java/redis/clients/jedis/search/aggr/Reducer.java @@ -1,8 +1,7 @@ package redis.clients.jedis.search.aggr; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; +import redis.clients.jedis.search.SearchProtocol.SearchKeyword; /** * Created by mnunberg on 2/22/18. @@ -11,61 +10,56 @@ */ public abstract class Reducer { - private String alias; + private final String name; private final String field; + private String alias; - protected Reducer(String field) { + protected Reducer(String name) { + this.name = name; + this.field = null; + } + + protected Reducer(String name, String field) { + this.name = name; this.field = field; - this.alias = null; } - protected Reducer() { - this(null); + public final Reducer as(String alias) { + this.alias = alias; + return this; } - protected List getOwnArgs() { - if (field == null) { - return Collections.emptyList(); - } - List ret = new ArrayList<>(); - ret.add(field); - return ret; + public final String getName() { + return name; } - /** - * @return The name of the reducer - */ - public abstract String getName(); + public final String getField() { + return field; + } public final String getAlias() { return alias; } - public final Reducer setAlias(String alias) { - this.alias = alias; - return this; - } + protected abstract List getOwnArgs(); - public final Reducer as(String alias) { - return setAlias(alias); - } + public final void addArgs(List args) { - public final Reducer setAliasAsField() { - if (field == null || field.isEmpty()) { - throw new IllegalArgumentException("Cannot set to field name since no field exists"); - } - return setAlias(field); - } + args.add(SearchKeyword.REDUCE); + args.add(name); - public void addArgs(List args) { - List ownArgs = getOwnArgs(); - args.add(Integer.toString(ownArgs.size())); + List ownArgs = getOwnArgs(); + if (field != null) { + args.add(1 + ownArgs.size()); + args.add(field); + } else { + args.add(ownArgs.size()); + } args.addAll(ownArgs); - } - public final List getArgs() { - List args = new ArrayList<>(); - addArgs(args); - return args; + if (alias != null) { + args.add(SearchKeyword.AS); + args.add(alias); + } } } diff --git a/src/main/java/redis/clients/jedis/search/aggr/Reducers.java b/src/main/java/redis/clients/jedis/search/aggr/Reducers.java index 4ac4d4ccfc..e24dadc871 100644 --- a/src/main/java/redis/clients/jedis/search/aggr/Reducers.java +++ b/src/main/java/redis/clients/jedis/search/aggr/Reducers.java @@ -1,5 +1,7 @@ package redis.clients.jedis.search.aggr; +import java.util.Arrays; +import java.util.Collections; import java.util.List; /** @@ -8,19 +10,17 @@ public class Reducers { public static Reducer count() { - return new Reducer() { - @Override - public String getName() { - return "COUNT"; + return new Reducer("COUNT") { + @Override protected List getOwnArgs() { + return Collections.emptyList(); } }; } private static Reducer singleFieldReducer(String name, String field) { - return new Reducer(field) { - @Override - public String getName() { - return name; + return new Reducer(name, field) { + @Override protected List getOwnArgs() { + return Collections.emptyList(); } }; } @@ -54,21 +54,17 @@ public static Reducer stddev(String field) { } public static Reducer quantile(String field, double percentile) { - return new Reducer(field) { - @Override - public String getName() { - return "QUANTILE"; - } - - @Override - protected List getOwnArgs() { - List args = super.getOwnArgs(); - args.add(Double.toString(percentile)); - return args; + return new Reducer("QUANTILE", field) { + @Override protected List getOwnArgs() { + return Arrays.asList(percentile); } }; } + public static Reducer first_value(String field) { + return singleFieldReducer("FIRST_VALUE", field); + } + /** * REDUCE FIRST_VALUE {nargs} {property} [BY {property} [ASC|DESC]] * @@ -77,45 +73,21 @@ protected List getOwnArgs() { * @return Reducer */ public static Reducer first_value(String field, SortedField sortBy) { - return new Reducer(field) { - @Override - public String getName() { - return "FIRST_VALUE"; - } - - @Override - protected List getOwnArgs() { - List args = super.getOwnArgs(); - if (sortBy != null) { - args.add("BY"); - args.add(sortBy.getField()); - args.add(sortBy.getOrder()); - } - return args; + return new Reducer("FIRST_VALUE", field) { + @Override protected List getOwnArgs() { + return Arrays.asList("BY", sortBy.getField(), sortBy.getOrder()); } }; } - public static Reducer first_value(String field) { - return first_value(field, null); - } - public static Reducer to_list(String field) { return singleFieldReducer("TOLIST", field); } public static Reducer random_sample(String field, int size) { - return new Reducer(field) { - @Override - public String getName() { - return "RANDOM_SAMPLE"; - } - - @Override - protected List getOwnArgs() { - List args = super.getOwnArgs(); - args.add(Integer.toString(size)); - return args; + return new Reducer("RANDOM_SAMPLE", field) { + @Override protected List getOwnArgs() { + return Arrays.asList(size); } }; } diff --git a/src/main/java/redis/clients/jedis/search/querybuilder/Node.java b/src/main/java/redis/clients/jedis/search/querybuilder/Node.java index 013ac79b6f..12e71e5d69 100644 --- a/src/main/java/redis/clients/jedis/search/querybuilder/Node.java +++ b/src/main/java/redis/clients/jedis/search/querybuilder/Node.java @@ -18,7 +18,7 @@ enum Parenthesize { /** * Never encapsulate. Note that this may be ignored if parentheses are semantically required - * (e.g. {@code @foo:(val1|val2)}. However something like {@code @foo:v1 @bar:v2} need not be + * (e.g. {@code @foo:(val1|val2)}. However, something like {@code @foo:v1 @bar:v2} need not be * parenthesized. */ diff --git a/src/main/java/redis/clients/jedis/search/schemafields/GeoShapeField.java b/src/main/java/redis/clients/jedis/search/schemafields/GeoShapeField.java new file mode 100644 index 0000000000..dd3b45e59e --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/schemafields/GeoShapeField.java @@ -0,0 +1,49 @@ +package redis.clients.jedis.search.schemafields; + +import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.GEOSHAPE; + +import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.search.FieldName; + +public class GeoShapeField extends SchemaField { + + public enum CoordinateSystem { + + /** + * For cartesian (X,Y). + */ + FLAT, + + /** + * For geographic (lon, lat). + */ + SPHERICAL + } + + private final CoordinateSystem system; + + public GeoShapeField(String fieldName, CoordinateSystem system) { + super(fieldName); + this.system = system; + } + + public GeoShapeField(FieldName fieldName, CoordinateSystem system) { + super(fieldName); + this.system = system; + } + + public static GeoShapeField of(String fieldName, CoordinateSystem system) { + return new GeoShapeField(fieldName, system); + } + + @Override + public GeoShapeField as(String attribute) { + super.as(attribute); + return this; + } + + @Override + public void addParams(CommandArguments args) { + args.addParams(fieldName).add(GEOSHAPE).add(system); + } +} diff --git a/src/main/java/redis/clients/jedis/search/schemafields/SchemaField.java b/src/main/java/redis/clients/jedis/search/schemafields/SchemaField.java index 473baea472..8678780da2 100644 --- a/src/main/java/redis/clients/jedis/search/schemafields/SchemaField.java +++ b/src/main/java/redis/clients/jedis/search/schemafields/SchemaField.java @@ -19,4 +19,12 @@ public SchemaField as(String attribute) { fieldName.as(attribute); return this; } + + public final FieldName getFieldName() { + return fieldName; + } + + public final String getName() { + return fieldName.getName(); + } } diff --git a/src/main/java/redis/clients/jedis/search/schemafields/TagField.java b/src/main/java/redis/clients/jedis/search/schemafields/TagField.java index 044f9d75f6..407c4dbddc 100644 --- a/src/main/java/redis/clients/jedis/search/schemafields/TagField.java +++ b/src/main/java/redis/clients/jedis/search/schemafields/TagField.java @@ -106,6 +106,14 @@ public void addParams(CommandArguments args) { args.add(SEPARATOR).add(separator); } + if (caseSensitive) { + args.add(CASESENSITIVE); + } + + if (withSuffixTrie) { + args.add(WITHSUFFIXTRIE); + } + if (sortableUNF) { args.add(SORTABLE).add(UNF); } else if (sortable) { @@ -115,13 +123,5 @@ public void addParams(CommandArguments args) { if (noIndex) { args.add(NOINDEX); } - - if (caseSensitive) { - args.add(CASESENSITIVE); - } - - if (withSuffixTrie) { - args.add(WITHSUFFIXTRIE); - } } } diff --git a/src/main/java/redis/clients/jedis/search/schemafields/TextField.java b/src/main/java/redis/clients/jedis/search/schemafields/TextField.java index f7967383c7..573cae90a3 100644 --- a/src/main/java/redis/clients/jedis/search/schemafields/TextField.java +++ b/src/main/java/redis/clients/jedis/search/schemafields/TextField.java @@ -107,29 +107,30 @@ public void addParams(CommandArguments args) { args.addParams(fieldName); args.add(TEXT); - if (sortableUNF) { - args.add(SORTABLE).add(UNF); - } else if (sortable) { - args.add(SORTABLE); + if (weight != null) { + args.add(WEIGHT).add(weight); } if (noStem) { args.add(NOSTEM); } - if (noIndex) { - args.add(NOINDEX); - } if (phoneticMatcher != null) { args.add(PHONETIC).add(phoneticMatcher); } - if (weight != null) { - args.add(WEIGHT).add(weight); - } - if (withSuffixTrie) { args.add(WITHSUFFIXTRIE); } + + if (sortableUNF) { + args.add(SORTABLE).add(UNF); + } else if (sortable) { + args.add(SORTABLE); + } + + if (noIndex) { + args.add(NOINDEX); + } } } diff --git a/src/main/java/redis/clients/jedis/timeseries/AggregationType.java b/src/main/java/redis/clients/jedis/timeseries/AggregationType.java index edc88bdc49..6e3b3decd4 100644 --- a/src/main/java/redis/clients/jedis/timeseries/AggregationType.java +++ b/src/main/java/redis/clients/jedis/timeseries/AggregationType.java @@ -1,5 +1,6 @@ package redis.clients.jedis.timeseries; +import java.util.Locale; import redis.clients.jedis.args.Rawable; import redis.clients.jedis.util.SafeEncoder; @@ -28,7 +29,7 @@ public byte[] getRaw() { public static AggregationType safeValueOf(String str) { try { - return AggregationType.valueOf(str.replace('.', '_')); + return AggregationType.valueOf(str.replace('.', '_').toUpperCase(Locale.ENGLISH)); } catch (IllegalArgumentException iae) { return null; } diff --git a/src/main/java/redis/clients/jedis/timeseries/RedisTimeSeriesCommands.java b/src/main/java/redis/clients/jedis/timeseries/RedisTimeSeriesCommands.java index e805482f0a..c002b94c08 100644 --- a/src/main/java/redis/clients/jedis/timeseries/RedisTimeSeriesCommands.java +++ b/src/main/java/redis/clients/jedis/timeseries/RedisTimeSeriesCommands.java @@ -141,7 +141,7 @@ public interface RedisTimeSeriesCommands { * @param filters * @return multi range elements */ - List tsMRange(long fromTimestamp, long toTimestamp, String... filters); + Map tsMRange(long fromTimestamp, long toTimestamp, String... filters); /** * {@code TS.MRANGE fromTimestamp toTimestamp @@ -157,7 +157,7 @@ public interface RedisTimeSeriesCommands { * @param multiRangeParams * @return multi range elements */ - List tsMRange(TSMRangeParams multiRangeParams); + Map tsMRange(TSMRangeParams multiRangeParams); /** * {@code TS.MREVRANGE fromTimestamp toTimestamp FILTER filter...} @@ -167,7 +167,7 @@ public interface RedisTimeSeriesCommands { * @param filters * @return multi range elements */ - List tsMRevRange(long fromTimestamp, long toTimestamp, String... filters); + Map tsMRevRange(long fromTimestamp, long toTimestamp, String... filters); /** * {@code TS.MREVRANGE fromTimestamp toTimestamp @@ -183,7 +183,7 @@ public interface RedisTimeSeriesCommands { * @param multiRangeParams * @return multi range elements */ - List tsMRevRange(TSMRangeParams multiRangeParams); + Map tsMRevRange(TSMRangeParams multiRangeParams); /** * {@code TS.GET key} @@ -209,7 +209,7 @@ public interface RedisTimeSeriesCommands { * @param filters secondary indexes * @return multi get elements */ - List> tsMGet(TSMGetParams multiGetParams, String... filters); + Map tsMGet(TSMGetParams multiGetParams, String... filters); /** * {@code TS.CREATERULE sourceKey destKey AGGREGATION aggregationType timeBucket} diff --git a/src/main/java/redis/clients/jedis/timeseries/RedisTimeSeriesPipelineCommands.java b/src/main/java/redis/clients/jedis/timeseries/RedisTimeSeriesPipelineCommands.java index 90899d8e9a..85ad9e0b1e 100644 --- a/src/main/java/redis/clients/jedis/timeseries/RedisTimeSeriesPipelineCommands.java +++ b/src/main/java/redis/clients/jedis/timeseries/RedisTimeSeriesPipelineCommands.java @@ -38,19 +38,19 @@ public interface RedisTimeSeriesPipelineCommands { Response> tsRevRange(String key, TSRangeParams rangeParams); - Response> tsMRange(long fromTimestamp, long toTimestamp, String... filters); + Response> tsMRange(long fromTimestamp, long toTimestamp, String... filters); - Response> tsMRange(TSMRangeParams multiRangeParams); + Response> tsMRange(TSMRangeParams multiRangeParams); - Response> tsMRevRange(long fromTimestamp, long toTimestamp, String... filters); + Response> tsMRevRange(long fromTimestamp, long toTimestamp, String... filters); - Response> tsMRevRange(TSMRangeParams multiRangeParams); + Response> tsMRevRange(TSMRangeParams multiRangeParams); Response tsGet(String key); Response tsGet(String key, TSGetParams getParams); - Response>> tsMGet(TSMGetParams multiGetParams, String... filters); + Response> tsMGet(TSMGetParams multiGetParams, String... filters); Response tsCreateRule(String sourceKey, String destKey, AggregationType aggregationType, long timeBucket); diff --git a/src/main/java/redis/clients/jedis/timeseries/TSAlterParams.java b/src/main/java/redis/clients/jedis/timeseries/TSAlterParams.java index c972f167bc..4576a1b6b7 100644 --- a/src/main/java/redis/clients/jedis/timeseries/TSAlterParams.java +++ b/src/main/java/redis/clients/jedis/timeseries/TSAlterParams.java @@ -26,14 +26,6 @@ public static TSAlterParams alterParams() { return new TSAlterParams(); } - /** - * @deprecated Use {@link TSAlterParams#retention(long)}. - */ - @Deprecated - public TSAlterParams retentionTime(long retentionTime) { - return retention(retentionTime); - } - public TSAlterParams retention(long retentionPeriod) { this.retentionPeriod = retentionPeriod; return this; diff --git a/src/main/java/redis/clients/jedis/timeseries/TSInfo.java b/src/main/java/redis/clients/jedis/timeseries/TSInfo.java index 09d48bca56..bc37edf8fe 100644 --- a/src/main/java/redis/clients/jedis/timeseries/TSInfo.java +++ b/src/main/java/redis/clients/jedis/timeseries/TSInfo.java @@ -4,10 +4,12 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import redis.clients.jedis.Builder; import redis.clients.jedis.BuilderFactory; import redis.clients.jedis.util.DoublePrecision; +import redis.clients.jedis.util.KeyValue; import redis.clients.jedis.util.SafeEncoder; public class TSInfo { @@ -101,7 +103,7 @@ public TSInfo build(Object data) { chunksValueList.add(new HashMap<>(chunk)); if (chunk.containsKey(CHUNKS_BYTES_PER_SAMPLE_PROPERTY)) { chunk.put(CHUNKS_BYTES_PER_SAMPLE_PROPERTY, - DoublePrecision.parseFloatingPointNumber((String) chunk.get(CHUNKS_BYTES_PER_SAMPLE_PROPERTY))); + DoublePrecision.parseEncodedFloatingPointNumber(chunk.get(CHUNKS_BYTES_PER_SAMPLE_PROPERTY))); } chunks.add(chunk); } @@ -126,6 +128,68 @@ public TSInfo build(Object data) { } }; + public static Builder TIMESERIES_INFO_RESP3 = new Builder() { + @Override + public TSInfo build(Object data) { + List list = (List) data; + Map properties = new HashMap<>(); + Map labels = null; + Map rules = null; + List> chunks = null; + + for (KeyValue propertyValue : list) { + String prop = BuilderFactory.STRING.build(propertyValue.getKey()); + Object value = propertyValue.getValue(); + if (value instanceof List) { + switch (prop) { + case LABELS_PROPERTY: + labels = BuilderFactory.STRING_MAP.build(value); + value = labels; + break; + case RULES_PROPERTY: + List rulesDataList = (List) value; + Map> rulesValueMap = new HashMap<>(rulesDataList.size(), 1f); + rules = new HashMap<>(rulesDataList.size()); + for (KeyValue rkv : rulesDataList) { + String ruleName = BuilderFactory.STRING.build(rkv.getKey()); + List ruleValueList = BuilderFactory.ENCODED_OBJECT_LIST.build(rkv.getValue()); + rulesValueMap.put(ruleName, ruleValueList); + rules.put(ruleName, new Rule(ruleName, ruleValueList)); + } + value = rulesValueMap; + break; + case CHUNKS_PROPERTY: + List> chunksDataList = (List>) value; + List> chunksValueList = new ArrayList<>(chunksDataList.size()); + chunks = new ArrayList<>(chunksDataList.size()); + for (List chunkDataAsList : chunksDataList) { + Map chunk = chunkDataAsList.stream() + .collect(Collectors.toMap(kv -> BuilderFactory.STRING.build(kv.getKey()), + kv -> BuilderFactory.ENCODED_OBJECT.build(kv.getValue()))); + chunksValueList.add(chunk); + chunks.add(chunk); + } + value = chunksValueList; + break; + default: + value = SafeEncoder.encodeObject(value); + break; + } + } else if (value instanceof byte[]) { + value = BuilderFactory.STRING.build(value); + if (DUPLICATE_POLICY_PROPERTY.equals(prop)) { + try { + value = DuplicatePolicy.valueOf(((String) value).toUpperCase()); + } catch (Exception e) { } + } + } + properties.put(prop, value); + } + + return new TSInfo(properties, labels, rules, chunks); + } + }; + public static class Rule { private final String compactionKey; @@ -133,6 +197,12 @@ public static class Rule { private final AggregationType aggregator; private final long alignmentTimestamp; + private Rule(String compaction, List encodedValues) { + this(compaction, (Long) encodedValues.get(0), + AggregationType.safeValueOf((String) encodedValues.get(1)), + (Long) encodedValues.get(2)); + } + private Rule(String compaction, long bucket, AggregationType aggregation, long alignment) { this.compactionKey = compaction; this.bucketDuration = bucket; diff --git a/src/main/java/redis/clients/jedis/timeseries/TSKeyValue.java b/src/main/java/redis/clients/jedis/timeseries/TSKeyValue.java deleted file mode 100644 index 0ae29dcfbd..0000000000 --- a/src/main/java/redis/clients/jedis/timeseries/TSKeyValue.java +++ /dev/null @@ -1,18 +0,0 @@ -package redis.clients.jedis.timeseries; - -import java.util.Map; -import redis.clients.jedis.util.KeyValue; - -public class TSKeyValue extends KeyValue { - - private final Map labels; - - public TSKeyValue(String key, Map labels, V value) { - super(key, value); - this.labels = labels; - } - - public Map getLabels() { - return labels; - } -} diff --git a/src/main/java/redis/clients/jedis/timeseries/TSKeyedElements.java b/src/main/java/redis/clients/jedis/timeseries/TSKeyedElements.java deleted file mode 100644 index 7cd13ff68b..0000000000 --- a/src/main/java/redis/clients/jedis/timeseries/TSKeyedElements.java +++ /dev/null @@ -1,11 +0,0 @@ -package redis.clients.jedis.timeseries; - -import java.util.List; -import java.util.Map; - -public class TSKeyedElements extends TSKeyValue> { - - public TSKeyedElements(String key, Map labels, List elements) { - super(key, labels, elements); - } -} diff --git a/src/main/java/redis/clients/jedis/timeseries/TSMGetElement.java b/src/main/java/redis/clients/jedis/timeseries/TSMGetElement.java new file mode 100644 index 0000000000..afae79c34a --- /dev/null +++ b/src/main/java/redis/clients/jedis/timeseries/TSMGetElement.java @@ -0,0 +1,31 @@ +package redis.clients.jedis.timeseries; + +import java.util.Map; +import redis.clients.jedis.util.KeyValue; + +public class TSMGetElement extends KeyValue { + + private final Map labels; + + public TSMGetElement(String key, Map labels, TSElement value) { + super(key, value); + this.labels = labels; + } + + public Map getLabels() { + return labels; + } + + public TSElement getElement() { + return getValue(); + } + + @Override + public String toString() { + return new StringBuilder().append(getClass().getSimpleName()) + .append("{key=").append(getKey()) + .append(", labels=").append(labels) + .append(", element=").append(getElement()) + .append('}').toString(); + } +} diff --git a/src/main/java/redis/clients/jedis/timeseries/TSMRangeElements.java b/src/main/java/redis/clients/jedis/timeseries/TSMRangeElements.java new file mode 100644 index 0000000000..e5f44fcd4d --- /dev/null +++ b/src/main/java/redis/clients/jedis/timeseries/TSMRangeElements.java @@ -0,0 +1,70 @@ +package redis.clients.jedis.timeseries; + +import java.util.List; +import java.util.Map; +import redis.clients.jedis.util.KeyValue; + +public class TSMRangeElements extends KeyValue> { + + private final Map labels; + private final List aggregators; + private final List reducers; + private final List sources; + + public TSMRangeElements(String key, Map labels, List value) { + super(key, value); + this.labels = labels; + this.aggregators = null; + this.reducers = null; + this.sources = null; + } + + public TSMRangeElements(String key, Map labels, List aggregators, List value) { + super(key, value); + this.labels = labels; + this.aggregators = aggregators; + this.reducers = null; + this.sources = null; + } + + public TSMRangeElements(String key, Map labels, List reducers, List sources, List value) { + super(key, value); + this.labels = labels; + this.aggregators = null; + this.reducers = reducers; + this.sources = sources; + } + + public Map getLabels() { + return labels; + } + + public List getAggregators() { + return aggregators; + } + + public List getReducers() { + return reducers; + } + + public List getSources() { + return sources; + } + + public List getElements() { + return getValue(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder().append(getClass().getSimpleName()) + .append("{key=").append(getKey()).append(", labels=").append(labels); + if (aggregators != null) { + sb.append(", aggregators=").append(aggregators); + } + if (reducers != null && sources != null) { + sb.append(", reducers").append(reducers).append(", sources").append(sources); + } + return sb.append(", elements=").append(getElements()).append('}').toString(); + } +} diff --git a/src/main/java/redis/clients/jedis/timeseries/TimeSeriesBuilderFactory.java b/src/main/java/redis/clients/jedis/timeseries/TimeSeriesBuilderFactory.java index 8ee566d169..96e40d5769 100644 --- a/src/main/java/redis/clients/jedis/timeseries/TimeSeriesBuilderFactory.java +++ b/src/main/java/redis/clients/jedis/timeseries/TimeSeriesBuilderFactory.java @@ -1,9 +1,14 @@ package redis.clients.jedis.timeseries; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; +import java.util.function.Function; import java.util.stream.Collectors; + import redis.clients.jedis.Builder; import redis.clients.jedis.BuilderFactory; +import redis.clients.jedis.util.KeyValue; public final class TimeSeriesBuilderFactory { @@ -26,26 +31,87 @@ public List build(Object data) { } }; - public static final Builder> TIMESERIES_MRANGE_RESPONSE = new Builder>() { + public static final Builder> TIMESERIES_MRANGE_RESPONSE + = new Builder>() { @Override - public List build(Object data) { + public Map build(Object data) { return ((List) data).stream().map((tsObject) -> (List) tsObject) - .map((tsList) -> new TSKeyedElements(BuilderFactory.STRING.build(tsList.get(0)), + .map((tsList) -> new TSMRangeElements(BuilderFactory.STRING.build(tsList.get(0)), BuilderFactory.STRING_MAP_FROM_PAIRS.build(tsList.get(1)), TIMESERIES_ELEMENT_LIST.build(tsList.get(2)))) - .collect(Collectors.toList()); + .collect(Collectors.toMap(TSMRangeElements::getKey, Function.identity(), + (x, y) -> x, LinkedHashMap::new)); + } + }; + + public static final Builder> TIMESERIES_MRANGE_RESPONSE_RESP3 + = new Builder>() { + @Override + public Map build(Object data) { + List dataList = (List) data; + Map map = new LinkedHashMap<>(dataList.size() / 2, 1f); + for (KeyValue kv : dataList) { + String key = BuilderFactory.STRING.build(kv.getKey()); + List valueList = (List) kv.getValue(); + TSMRangeElements elements; + switch (valueList.size()) { + case 3: + List aggrMapObj = (List) valueList.get(1); + KeyValue aggKV = (KeyValue) aggrMapObj.get(0); + assert "aggregators".equalsIgnoreCase(BuilderFactory.STRING.build(aggKV.getKey())); + elements = new TSMRangeElements(key, + BuilderFactory.STRING_MAP.build(valueList.get(0)), + ((List) aggKV.getValue()).stream().map(BuilderFactory.STRING::build) + .map(AggregationType::safeValueOf).collect(Collectors.toList()), + TIMESERIES_ELEMENT_LIST.build(valueList.get(2))); + break; + case 4: + List rdcMapObj = (List) valueList.get(1); + assert "reducers".equalsIgnoreCase(BuilderFactory.STRING.build(rdcMapObj.get(0).getKey())); + List srcMapObj = (List) valueList.get(2); + assert "sources".equalsIgnoreCase(BuilderFactory.STRING.build(srcMapObj.get(0).getKey())); + elements = new TSMRangeElements(key, + BuilderFactory.STRING_MAP.build(valueList.get(0)), + BuilderFactory.STRING_LIST.build(rdcMapObj.get(0).getValue()), + BuilderFactory.STRING_LIST.build(srcMapObj.get(0).getValue()), + TIMESERIES_ELEMENT_LIST.build(valueList.get(3))); + break; + default: + throw new IllegalStateException(); + } + map.put(key, elements); + } + return map; } }; - public static final Builder>> TIMESERIES_MGET_RESPONSE - = new Builder>>() { + public static final Builder> TIMESERIES_MGET_RESPONSE + = new Builder>() { @Override - public List> build(Object data) { + public Map build(Object data) { return ((List) data).stream().map((tsObject) -> (List) tsObject) - .map((tsList) -> new TSKeyValue<>(BuilderFactory.STRING.build(tsList.get(0)), + .map((tsList) -> new TSMGetElement(BuilderFactory.STRING.build(tsList.get(0)), BuilderFactory.STRING_MAP_FROM_PAIRS.build(tsList.get(1)), TIMESERIES_ELEMENT.build(tsList.get(2)))) - .collect(Collectors.toList()); + .collect(Collectors.toMap(TSMGetElement::getKey, Function.identity())); + } + }; + + public static final Builder> TIMESERIES_MGET_RESPONSE_RESP3 + = new Builder>() { + @Override + public Map build(Object data) { + List dataList = (List) data; + Map map = new LinkedHashMap<>(dataList.size()); + for (KeyValue kv : dataList) { + String key = BuilderFactory.STRING.build(kv.getKey()); + List valueList = (List) kv.getValue(); + TSMGetElement value = new TSMGetElement(key, + BuilderFactory.STRING_MAP.build(valueList.get(0)), + TIMESERIES_ELEMENT.build(valueList.get(1))); + map.put(key, value); + } + return map; } }; diff --git a/src/main/java/redis/clients/jedis/util/DoublePrecision.java b/src/main/java/redis/clients/jedis/util/DoublePrecision.java index 5d090cf209..ddc4289191 100644 --- a/src/main/java/redis/clients/jedis/util/DoublePrecision.java +++ b/src/main/java/redis/clients/jedis/util/DoublePrecision.java @@ -6,7 +6,7 @@ private DoublePrecision() { throw new InstantiationError("Must not instantiate this class"); } - public static Double parseFloatingPointNumber(String str) { + public static Double parseFloatingPointNumber(String str) throws NumberFormatException { if (str == null) return null; @@ -26,6 +26,7 @@ public static Double parseFloatingPointNumber(String str) { return Double.NEGATIVE_INFINITY; case "nan": + case "-nan": // for some module commands // TODO: remove return Double.NaN; default: @@ -33,4 +34,10 @@ public static Double parseFloatingPointNumber(String str) { } } } + + public static Double parseEncodedFloatingPointNumber(Object val) throws NumberFormatException { + if (val == null) return null; + else if (val instanceof Double) return (Double) val; + else return parseFloatingPointNumber((String) val); + } } diff --git a/src/main/java/redis/clients/jedis/util/Hashing.java b/src/main/java/redis/clients/jedis/util/Hashing.java index df815883c3..b10ff04975 100644 --- a/src/main/java/redis/clients/jedis/util/Hashing.java +++ b/src/main/java/redis/clients/jedis/util/Hashing.java @@ -3,6 +3,10 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +/** + * @deprecated Sharding/Sharded feature will be removed in next major release. + */ +@Deprecated public interface Hashing { Hashing MURMUR_HASH = new MurmurHash(); ThreadLocal md5Holder = new ThreadLocal<>(); diff --git a/src/main/java/redis/clients/jedis/util/JedisClusterCRC16.java b/src/main/java/redis/clients/jedis/util/JedisClusterCRC16.java index 7bedf5060a..b296c6209e 100644 --- a/src/main/java/redis/clients/jedis/util/JedisClusterCRC16.java +++ b/src/main/java/redis/clients/jedis/util/JedisClusterCRC16.java @@ -1,13 +1,12 @@ package redis.clients.jedis.util; -import redis.clients.jedis.exceptions.JedisClusterOperationException; - /** * CRC16 Implementation according to CCITT standard Polynomial : 1021 (x^16 + x^12 + x^5 + 1) See Appendix A. CRC16 reference implementation in ANSI * C */ public final class JedisClusterCRC16 { + private static final int[] LOOKUP_TABLE = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, 0xA35A, @@ -33,13 +32,9 @@ public final class JedisClusterCRC16 { 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0, }; - private JedisClusterCRC16() { - throw new InstantiationError("Must not instantiate this class"); - } - public static int getSlot(String key) { if (key == null) { - throw new JedisClusterOperationException("Slot calculation of null is impossible"); + throw new NullPointerException("Slot calculation of null is impossible"); } key = JedisClusterHashTag.getHashTag(key); @@ -49,7 +44,7 @@ public static int getSlot(String key) { public static int getSlot(byte[] key) { if (key == null) { - throw new JedisClusterOperationException("Slot calculation of null is impossible"); + throw new NullPointerException("Slot calculation of null is impossible"); } int s = -1; @@ -97,4 +92,8 @@ public static int getCRC16(String key) { byte[] bytesKey = SafeEncoder.encode(key); return getCRC16(bytesKey, 0, bytesKey.length); } + + private JedisClusterCRC16() { + throw new InstantiationError("Must not instantiate this class"); + } } diff --git a/src/main/java/redis/clients/jedis/util/JedisCommandIterationBase.java b/src/main/java/redis/clients/jedis/util/JedisCommandIterationBase.java new file mode 100644 index 0000000000..97daacdbf1 --- /dev/null +++ b/src/main/java/redis/clients/jedis/util/JedisCommandIterationBase.java @@ -0,0 +1,100 @@ +package redis.clients.jedis.util; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.function.Supplier; + +import redis.clients.jedis.Builder; +import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.Connection; +import redis.clients.jedis.providers.ConnectionProvider; + +/** + * @param Type of each batch reply + * @param Type of each data + */ +public abstract class JedisCommandIterationBase { + + private final Builder builder; + + private final Queue connections; + + private Map.Entry connection; + + private B lastReply; + + private boolean roundRobinCompleted; + private boolean iterationCompleted; + + protected JedisCommandIterationBase(ConnectionProvider connectionProvider, Builder responseBuilder) { + Map connectionMap = connectionProvider.getConnectionMap(); + ArrayList connectionList = new ArrayList<>(connectionMap.entrySet()); + Collections.shuffle(connectionList); + this.connections = new LinkedList<>(connectionList); + this.builder = responseBuilder; + this.iterationCompleted = true; + this.roundRobinCompleted = this.connections.isEmpty(); + } + + public final boolean isIterationCompleted() { + return roundRobinCompleted; + } + + protected abstract boolean isNodeCompleted(B reply); + + protected abstract CommandArguments initCommandArguments(); + + protected abstract CommandArguments nextCommandArguments(B lastReply); + + public final B nextBatch() { + if (roundRobinCompleted) { + throw new NoSuchElementException(); + } + + CommandArguments args; + if (iterationCompleted) { + connection = connections.poll(); + args = initCommandArguments(); + } else { + args = nextCommandArguments(lastReply); + } + + Object rawReply; + if (connection.getValue() instanceof Connection) { + rawReply = ((Connection) connection.getValue()).executeCommand(args); + } else if (connection.getValue() instanceof Pool) { + try (Connection c = ((Pool) connection.getValue()).getResource()) { + rawReply = c.executeCommand(args); + } + } else { + throw new IllegalArgumentException(connection.getValue().getClass() + "is not supported."); + } + + lastReply = builder.build(rawReply); + iterationCompleted = isNodeCompleted(lastReply); + if (iterationCompleted) { + if (connections.isEmpty()) { + roundRobinCompleted = true; + } + } + return lastReply; + } + + protected abstract Collection convertBatchToData(B batch); + + public final Collection nextBatchList() { + return convertBatchToData(nextBatch()); + } + + public final Collection collect(Collection c) { + while (!isIterationCompleted()) { + c.addAll(nextBatchList()); + } + return c; + } +} diff --git a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java index dd502e5e34..6bbd1599a8 100644 --- a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java +++ b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java @@ -2,11 +2,11 @@ import java.net.URI; import redis.clients.jedis.HostAndPort; +import redis.clients.jedis.Protocol; +import redis.clients.jedis.RedisProtocol; public final class JedisURIHelper { - private static final int DEFAULT_DB = 0; - private static final String REDIS = "redis"; private static final String REDISS = "rediss"; @@ -43,12 +43,31 @@ public static int getDBIndex(URI uri) { if (pathSplit.length > 1) { String dbIndexStr = pathSplit[1]; if (dbIndexStr.isEmpty()) { - return DEFAULT_DB; + return Protocol.DEFAULT_DATABASE; } return Integer.parseInt(dbIndexStr); } else { - return DEFAULT_DB; + return Protocol.DEFAULT_DATABASE; + } + } + + public static RedisProtocol getRedisProtocol(URI uri) { + if (uri.getQuery() == null) return null; + + String[] pairs = uri.getQuery().split("&"); + for (String pair : pairs) { + int idx = pair.indexOf("="); + if ("protocol".equals(pair.substring(0, idx))) { + String ver = pair.substring(idx + 1); + for (RedisProtocol proto : RedisProtocol.values()) { + if (proto.version().equals(ver)) { + return proto; + } + } + throw new IllegalArgumentException("Unknown protocol " + ver); + } } + return null; // null (default) when not defined } public static boolean isValid(URI uri) { diff --git a/src/main/java/redis/clients/jedis/search/LazyRawable.java b/src/main/java/redis/clients/jedis/util/LazyRawable.java similarity index 70% rename from src/main/java/redis/clients/jedis/search/LazyRawable.java rename to src/main/java/redis/clients/jedis/util/LazyRawable.java index bc1a346800..74a5820e87 100644 --- a/src/main/java/redis/clients/jedis/search/LazyRawable.java +++ b/src/main/java/redis/clients/jedis/util/LazyRawable.java @@ -1,8 +1,8 @@ -package redis.clients.jedis.search; +package redis.clients.jedis.util; import redis.clients.jedis.args.Rawable; -class LazyRawable implements Rawable { +public class LazyRawable implements Rawable { private byte[] raw = null; diff --git a/src/main/java/redis/clients/jedis/util/MurmurHash.java b/src/main/java/redis/clients/jedis/util/MurmurHash.java index 91bf463b59..a882745bca 100644 --- a/src/main/java/redis/clients/jedis/util/MurmurHash.java +++ b/src/main/java/redis/clients/jedis/util/MurmurHash.java @@ -21,7 +21,9 @@ * The C version of MurmurHash 2.0 found at that site was ported to Java by Andrzej Bialecki (ab at * getopt org). *

+ * @deprecated Sharding/Sharded feature will be removed in next major release. */ +@Deprecated public class MurmurHash implements Hashing { /** * Hashes bytes in an array. diff --git a/src/main/java/redis/clients/jedis/util/RedisInputStream.java b/src/main/java/redis/clients/jedis/util/RedisInputStream.java index bebdb27c07..a0dad9d437 100644 --- a/src/main/java/redis/clients/jedis/util/RedisInputStream.java +++ b/src/main/java/redis/clients/jedis/util/RedisInputStream.java @@ -13,6 +13,7 @@ import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; +import java.math.BigInteger; import redis.clients.jedis.exceptions.JedisConnectionException; /** @@ -47,6 +48,21 @@ public byte readByte() throws JedisConnectionException { return buf[count++]; } + private void ensureCrLf() { + final byte[] buf = this.buf; + + ensureFill(); + if (buf[count++] == '\r') { + + ensureFill(); + if (buf[count++] == '\n') { + return; + } + } + + throw new JedisConnectionException("Unexpected character!"); + } + public String readLine() { final StringBuilder sb = new StringBuilder(); while (true) { @@ -112,7 +128,7 @@ public byte[] readLineBytes() { /** * Slow path in case a line of bytes cannot be read in one #fill() operation. This is still faster - * than creating the StrinbBuilder, String, then encoding as byte[] in Protocol, then decoding + * than creating the StringBuilder, String, then encoding as byte[] in Protocol, then decoding * back into a String. */ private byte[] readLineBytesSlowly() { @@ -147,6 +163,25 @@ private byte[] readLineBytesSlowly() { return bout == null ? new byte[0] : bout.toByteArray(); } + public Object readNullCrLf() { + ensureCrLf(); + return null; + } + + public boolean readBooleanCrLf() { + final byte[] buf = this.buf; + + ensureFill(); + final byte b = buf[count++]; + + ensureCrLf(); + switch (b) { + case 't': return true; + case 'f': return false; + default: throw new JedisConnectionException("Unexpected character!"); + } + } + public int readIntCrLf() { return (int) readLongCrLf(); } @@ -182,6 +217,14 @@ public long readLongCrLf() { return (isNeg ? -value : value); } + public double readDoubleCrLf() { + return DoublePrecision.parseFloatingPointNumber(readLine()); + } + + public BigInteger readBigIntegerCrLf() { + return new BigInteger(readLine()); + } + @Override public int read(byte[] b, int off, int len) throws JedisConnectionException { ensureFill(); @@ -193,7 +236,7 @@ public int read(byte[] b, int off, int len) throws JedisConnectionException { } /** - * This methods assumes there are required bytes to be read. If we cannot read anymore bytes an + * This method assumes there are required bytes to be read. If we cannot read anymore bytes an * exception is thrown to quickly ascertain that the stream was smaller than expected. */ private void ensureFill() throws JedisConnectionException { diff --git a/src/main/java/redis/clients/jedis/util/SafeEncoder.java b/src/main/java/redis/clients/jedis/util/SafeEncoder.java index 314d721851..fb5d8fb24e 100644 --- a/src/main/java/redis/clients/jedis/util/SafeEncoder.java +++ b/src/main/java/redis/clients/jedis/util/SafeEncoder.java @@ -46,6 +46,11 @@ public static Object encodeObject(Object dataToEncode) { return SafeEncoder.encode((byte[]) dataToEncode); } + if (dataToEncode instanceof KeyValue) { + KeyValue keyValue = (KeyValue) dataToEncode; + return new KeyValue<>(encodeObject(keyValue.getKey()), encodeObject(keyValue.getValue())); + } + if (dataToEncode instanceof List) { List arrayToDecode = (List) dataToEncode; List returnValueArray = new ArrayList(arrayToDecode.size()); diff --git a/src/main/resources/redis/clients/jedis/pom.properties b/src/main/resources/redis/clients/jedis/pom.properties new file mode 100644 index 0000000000..951752f2de --- /dev/null +++ b/src/main/resources/redis/clients/jedis/pom.properties @@ -0,0 +1,3 @@ +groupId=${project.groupId} +artifactId=${project.artifactId} +version=${project.version} diff --git a/src/test/java/io/redis/examples/SearchQuickstartExample.java b/src/test/java/io/redis/examples/SearchQuickstartExample.java new file mode 100644 index 0000000000..5ef34b7529 --- /dev/null +++ b/src/test/java/io/redis/examples/SearchQuickstartExample.java @@ -0,0 +1,218 @@ +//EXAMPLE: set_and_get +//HIDE_START +package io.redis.examples; + +import java.math.BigDecimal; +import java.util.*; + +import redis.clients.jedis.*; +import redis.clients.jedis.exceptions.*; +import redis.clients.jedis.search.*; +import redis.clients.jedis.search.aggr.*; +import redis.clients.jedis.search.schemafields.*; +//REMOVE_START +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +//REMOVE_END + +class Bicycle { + public String brand; + public String model; + public BigDecimal price; + public String description; + public String condition; + + public Bicycle(String brand, String model, BigDecimal price, String description, String condition) { + this.brand = brand; + this.model = model; + this.price = price; + this.description = description; + this.condition = condition; + } +} + +public class SearchQuickstartExample { + + @Test + public void run() { + //HIDE_END + + // STEP_START connect + UnifiedJedis jedis = new UnifiedJedis("redis://localhost:6379"); + // STEP_END + // REMOVE_START + try { + jedis.ftDropIndex("idx:bicycle"); + } catch (JedisDataException e) { + // ignore + } + // REMOVE_END + + // STEP_START data_sample + Bicycle bike1 = new Bicycle( + "Diaz Ltd", + "Dealer Sl", + new BigDecimal(7315.58), + "The Diaz Ltd Dealer Sl is a reliable choice" + + " for urban cycling. The Diaz Ltd Dealer Sl " + + "is a comfortable choice for urban cycling.", + "used" + ); + // STEP_END + + Bicycle[] bicycles = { + bike1, + new Bicycle( + "Bridges Group", + "Project Pro", + new BigDecimal(3610.82), + "This mountain bike is perfect for mountain biking. The Bridges" + + " Group Project Pro is a responsive choice for mountain biking.", + "used" + ), + new Bicycle( + "Vega, Cole and Miller", + "Group Advanced", + new BigDecimal(8961.42), + "The Vega, Cole and Miller Group Advanced provides a excellent" + + " ride. With its fast carbon frame and 24 gears, this bicycle is" + + " perfect for any terrain.", + "used" + ), + new Bicycle( + "Powell-Montgomery", + "Angle Race", + new BigDecimal(4050.27), + "The Powell-Montgomery Angle Race is a smooth choice for road" + + " cycling. The Powell-Montgomery Angle Race provides a durable" + + " ride.", + "used" + ), + new Bicycle( + "Gill-Lewis", + "Action Evo", + new BigDecimal(283.68), + "The Gill-Lewis Action Evo provides a smooth ride. The Gill-Lewis" + + " Action Evo provides a excellent ride.", + "used" + ), + new Bicycle( + "Rodriguez-Guerrero", + "Drama Comp", + new BigDecimal(4462.55), + "This kids bike is perfect for young riders. With its excellent" + + " aluminum frame and 12 gears, this bicycle is perfect for any" + + " terrain.", + "new" + ), + new Bicycle( + "Moore PLC", + "Award Race", + new BigDecimal(3790.76), + + "This olive folding bike features a carbon frame and 27.5 inch" + + " wheels. This folding bike is perfect for compact storage and" + + " transportation.", + "new" + ), + new Bicycle( + "Hall, Haley and Hayes", + "Weekend Plus", + new BigDecimal(2008.4), + "The Hall, Haley and Hayes Weekend Plus provides a comfortable" + + " ride. This blue kids bike features a steel frame and 29.0 inch" + + " wheels.", + "new" + ), + new Bicycle( + "Peck-Carson", + "Sun Hybrid", + new BigDecimal(9874.95), + "With its comfortable aluminum frame and 25 gears, this bicycle is" + + " perfect for any terrain. The Peck-Carson Sun Hybrid provides a" + + " comfortable ride.", + "new" + ), + new Bicycle( + "Fowler Ltd", + "Weekend Trail", + new BigDecimal(3833.71), + "The Fowler Ltd Letter Trail is a comfortable choice for" + + " transporting cargo. This cargo bike is perfect for transporting" + + " cargo.", + "refurbished" + ) + }; + + // STEP_START define_index + SchemaField[] schema = { + TextField.of("$.brand").as("brand"), + TextField.of("$.model").as("model"), + TextField.of("$.description").as("description"), + NumericField.of("$.price").as("price"), + TagField.of("$.condition").as("condition") + }; + // STEP_END + + // STEP_START create_index + jedis.ftCreate("idx:bicycle", + FTCreateParams.createParams() + .on(IndexDataType.JSON) + .addPrefix("bicycle:"), + schema + ); + // STEP_END + // STEP_START add_documents + for (int i = 0; i < bicycles.length; i++) { + jedis.jsonSetWithEscape(String.format("bicycle:%d", i), bicycles[i]); + } + // STEP_END + + // STEP_START query_single_term_and_num_range + Query query = new Query("folding @price:[1000 4000]"); + List result = jedis.ftSearch("idx:bicycle", query).getDocuments(); + System.out.println(result); + // Prints: [id:bicycle:6, score: 1.0, payload:null, properties:[ + // $={"brand":"Moore PLC","model":"Award Race","price":3790.76, + // "description":"This olive folding bike features a carbon frame and 27.5 inch wheels. + // This folding bike is perfect for compact storage and transportation.","condition":"new"}] + // ] + // STEP_END + // REMOVE_START + assertEquals("Validate folding bike id", "bicycle:6", result.get(0).getId()); + // REMOVE_END + + // STEP_START query_single_term_limit_fields + Query cargo_query = new Query("cargo").returnFields("price"); + List cargo_result = jedis.ftSearch( + "idx:bicycle", cargo_query).getDocuments(); + System.out.println(cargo_result); + // Prints: [id:bicycle:9, score: 1.0, payload:null, properties:[price=3833.71]] + // STEP_END + // REMOVE_START + assertEquals("Validate cargo bike id", "bicycle:9", cargo_result.get(0).getId()); + // REMOVE_END + + // STEP_START simple_aggregation + AggregationBuilder ab = new AggregationBuilder("*") + .groupBy("@condition", Reducers.count().as("count")); + AggregationResult ar = jedis.ftAggregate("idx:bicycle", ab); + + for (int i = 0; i < ar.getTotalResults(); i++) { + System.out.println( + ar.getRow(i).getString("condition") + + " - " + + ar.getRow(i).getString("count")); + } + // Prints: + // refurbished - 1 + // used - 5 + // new - 4 + // STEP_END + // REMOVE_START + assertEquals("Validate aggregation results", 3, ar.getTotalResults()); + // REMOVE_END + } +} +//HIDE_END diff --git a/src/test/java/io/redis/examples/SetGetExample.java b/src/test/java/io/redis/examples/SetGetExample.java new file mode 100644 index 0000000000..282f1aebb2 --- /dev/null +++ b/src/test/java/io/redis/examples/SetGetExample.java @@ -0,0 +1,36 @@ +//EXAMPLE: set_and_get +//HIDE_START +package io.redis.examples; + +import redis.clients.jedis.UnifiedJedis; +//REMOVE_START +import org.junit.Test; +import static org.junit.Assert.assertEquals; +//REMOVE_END + +public class SetGetExample { + + @Test + public void run() { + + UnifiedJedis jedis = new UnifiedJedis("redis://localhost:6379"); + + //HIDE_END + String status = jedis.set("bike:1", "Process 134"); + + if ("OK".equals(status)) + System.out.println("Successfully added a bike."); + + String value = jedis.get("bike:1"); + + if ( value != null) + System.out.println("The name of the bike is: " + value + "."); + //HIDE_START + + //REMOVE_START + assertEquals("OK", status); + assertEquals("Process 134", value); + //REMOVE_END + } +} +//HIDE_END diff --git a/src/test/java/redis/clients/jedis/ACLJedisPoolTest.java b/src/test/java/redis/clients/jedis/ACLJedisPoolTest.java index 7a878b015a..36474e12d5 100644 --- a/src/test/java/redis/clients/jedis/ACLJedisPoolTest.java +++ b/src/test/java/redis/clients/jedis/ACLJedisPoolTest.java @@ -2,7 +2,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -61,7 +60,7 @@ public void checkResourceIsClosableAndReusable() { config.setBlockWhenExhausted(false); try (JedisPool pool = new JedisPool(config, hnp.getHost(), hnp.getPort(), Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT, 0 /* infinite */, "acljedis", - "fizzbuzz", Protocol.DEFAULT_DATABASE, "closable-resuable-pool", false, null, null, null)) { + "fizzbuzz", Protocol.DEFAULT_DATABASE, "closable-reusable-pool", false, null, null, null)) { Jedis jedis = pool.getResource(); jedis.set("hello", "jedis"); @@ -80,7 +79,7 @@ public void checkResourceWithConfigIsClosableAndReusable() { config.setMaxTotal(1); config.setBlockWhenExhausted(false); try (JedisPool pool = new JedisPool(config, hnp, DefaultJedisClientConfig.builder() - .user("acljedis").password("fizzbuzz").clientName("closable-resuable-pool") + .user("acljedis").password("fizzbuzz").clientName("closable-reusable-pool") .build())) { Jedis jedis = pool.getResource(); @@ -90,7 +89,7 @@ public void checkResourceWithConfigIsClosableAndReusable() { Jedis jedis2 = pool.getResource(); assertEquals(jedis, jedis2); assertEquals("jedis", jedis2.get("hello")); - assertEquals("closable-resuable-pool", jedis2.clientGetname()); + assertEquals("closable-reusable-pool", jedis2.clientGetname()); jedis2.close(); } } @@ -102,7 +101,7 @@ public void checkPoolRepairedWhenJedisIsBroken() { "fizzbuzz", Protocol.DEFAULT_DATABASE, "repairable-pool"); try (Jedis jedis = pool.getResource()) { jedis.set("foo", "0"); - jedis.quit(); + jedis.disconnect(); } try (Jedis jedis = pool.getResource()) { @@ -270,50 +269,4 @@ public void testCloseConnectionOnMakeObject() { private int getClientCount(final String clientList) { return clientList.split("\n").length; } - - @Test - public void testResetInvalidPassword() { - JedisFactory factory = new JedisFactory(hnp.getHost(), hnp.getPort(), 2000, 2000, - "acljedis", "fizzbuzz", 0, "my_shiny_client_name") { }; - - try (JedisPool pool = new JedisPool(new JedisPoolConfig(), factory)) { - Jedis obj1_ref; - try (Jedis obj1_1 = pool.getResource()) { - obj1_ref = obj1_1; - obj1_1.set("foo", "bar"); - assertEquals("bar", obj1_1.get("foo")); - assertEquals(1, pool.getNumActive()); - } - assertEquals(0, pool.getNumActive()); - try (Jedis obj1_2 = pool.getResource()) { - assertSame(obj1_ref, obj1_2); - assertEquals(1, pool.getNumActive()); - factory.setPassword("wrong password"); - try (Jedis obj2 = pool.getResource()) { - fail("Should not get resource from pool"); - } catch (JedisException e) { } - assertEquals(1, pool.getNumActive()); - } - assertEquals(0, pool.getNumActive()); - } - } - - @Test - public void testResetValidPassword() { - JedisFactory factory = new JedisFactory(hnp.getHost(), hnp.getPort(), 2000, 2000, - "acljedis", "bad password", 0, "my_shiny_client_name") { }; - - try (JedisPool pool = new JedisPool(new JedisPoolConfig(), factory)) { - try (Jedis obj1 = pool.getResource()) { - fail("Should not get resource from pool"); - } catch (JedisException e) { } - assertEquals(0, pool.getNumActive()); - - factory.setPassword("fizzbuzz"); - try (Jedis obj2 = pool.getResource()) { - obj2.set("foo", "bar"); - assertEquals("bar", obj2.get("foo")); - } - } - } } diff --git a/src/test/java/redis/clients/jedis/ACLJedisTest.java b/src/test/java/redis/clients/jedis/ACLJedisTest.java index 577280daa6..81517b5556 100644 --- a/src/test/java/redis/clients/jedis/ACLJedisTest.java +++ b/src/test/java/redis/clients/jedis/ACLJedisTest.java @@ -89,42 +89,14 @@ public void startWithUri() throws URISyntaxException { assertEquals("OK", j.select(2)); j.set("foo", "bar"); } - try (Jedis j2 = new Jedis(new URI("redis://acljedis:fizzbuzz@localhost:6379/2"))) { - assertEquals("PONG", j2.ping()); - assertEquals("bar", j2.get("foo")); - } - } - - @Test - public void connectWithURICredentials() throws URISyntaxException { - jedis.set("foo", "bar"); - - try (Jedis j1 = new Jedis(new URI("redis://default:foobared@localhost:6379"))) { + try (Jedis j1 = new Jedis(new URI("redis://acljedis:fizzbuzz@localhost:6379/2"))) { assertEquals("PONG", j1.ping()); assertEquals("bar", j1.get("foo")); } - - try (Jedis j2 = new Jedis(new URI("redis://acljedis:fizzbuzz@localhost:6379"))) { + try (Jedis j2 = new Jedis(new URI("redis://acljedis:fizzbuzz@localhost:6379/2"))) { assertEquals("PONG", j2.ping()); assertEquals("bar", j2.get("foo")); } } - @Test - public void allowUrlWithNoDBAndNoPassword() { - try (Jedis j1 = new Jedis("redis://localhost:6379")) { - assertEquals("OK", j1.auth("acljedis", "fizzbuzz")); -// assertEquals("localhost", j1.getClient().getHost()); -// assertEquals(6379, j1.getClient().getPort()); - assertEquals(0, j1.getDB()); - } - - try (Jedis j2 = new Jedis("redis://localhost:6379/")) { - assertEquals("OK", j2.auth("acljedis", "fizzbuzz")); -// assertEquals("localhost", j2.getClient().getHost()); -// assertEquals(6379, j2.getClient().getPort()); - assertEquals(0, j2.getDB()); - } - } - } diff --git a/src/test/java/redis/clients/jedis/ClusterCommandExecutorTest.java b/src/test/java/redis/clients/jedis/ClusterCommandExecutorTest.java index 6f9e941332..4601bf0b6f 100644 --- a/src/test/java/redis/clients/jedis/ClusterCommandExecutorTest.java +++ b/src/test/java/redis/clients/jedis/ClusterCommandExecutorTest.java @@ -2,11 +2,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; @@ -15,8 +11,12 @@ import java.time.Duration; import java.util.concurrent.atomic.AtomicLong; import java.util.function.LongConsumer; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; import org.junit.Test; +import org.mockito.ArgumentMatchers; import org.mockito.InOrder; +import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; @@ -99,7 +99,7 @@ protected void sleep(long sleepMillis) { } InOrder inOrder = inOrder(connectionHandler, sleep); inOrder.verify(connectionHandler, times(2)).getConnection(STR_COM_OBJECT.getArguments()); - inOrder.verify(sleep).accept(anyLong()); + inOrder.verify(sleep).accept(ArgumentMatchers.anyLong()); inOrder.verify(connectionHandler).renewSlotCache(); inOrder.verify(connectionHandler).getConnection(STR_COM_OBJECT.getArguments()); inOrder.verifyNoMoreInteractions(); @@ -134,7 +134,7 @@ protected void sleep(long ignored) { InOrder inOrder = inOrder(connectionHandler); inOrder.verify(connectionHandler).getConnection(STR_COM_OBJECT.getArguments()); - inOrder.verify(connectionHandler).renewSlotCache(any()); + inOrder.verify(connectionHandler).renewSlotCache(ArgumentMatchers.any()); inOrder.verify(connectionHandler).getConnection(movedTarget); inOrder.verifyNoMoreInteractions(); } @@ -191,8 +191,8 @@ public void runMovedThenAllNodesFailing() { when(connectionHandler.getConnection(STR_COM_OBJECT.getArguments())).thenReturn(redirecter); final Connection failer = mock(Connection.class); - when(connectionHandler.getConnection(any(HostAndPort.class))).thenReturn(failer); - doAnswer((Answer) (InvocationOnMock invocation) -> { + when(connectionHandler.getConnection(ArgumentMatchers.any(HostAndPort.class))).thenReturn(failer); + Mockito.doAnswer((Answer) (InvocationOnMock invocation) -> { when(connectionHandler.getConnection(STR_COM_OBJECT.getArguments())).thenReturn(failer); return null; }).when(connectionHandler).renewSlotCache(); @@ -231,10 +231,10 @@ protected void sleep(long sleepMillis) { inOrder.verify(connectionHandler).getConnection(STR_COM_OBJECT.getArguments()); inOrder.verify(connectionHandler).renewSlotCache(redirecter); inOrder.verify(connectionHandler, times(2)).getConnection(movedTarget); - inOrder.verify(sleep).accept(anyLong()); + inOrder.verify(sleep).accept(ArgumentMatchers.anyLong()); inOrder.verify(connectionHandler).renewSlotCache(); inOrder.verify(connectionHandler, times(2)).getConnection(STR_COM_OBJECT.getArguments()); - inOrder.verify(sleep).accept(anyLong()); + inOrder.verify(sleep).accept(ArgumentMatchers.anyLong()); inOrder.verify(connectionHandler).renewSlotCache(); inOrder.verifyNoMoreInteractions(); } @@ -260,13 +260,13 @@ public void runMasterFailingReplicaRecovering() { when(connectionHandler.getConnection(STR_COM_OBJECT.getArguments())).thenReturn(master); - doAnswer((Answer) (InvocationOnMock invocation) -> { + Mockito.doAnswer((Answer) (InvocationOnMock invocation) -> { when(connectionHandler.getConnection(STR_COM_OBJECT.getArguments())).thenReturn(replica); return null; }).when(connectionHandler).renewSlotCache(); final AtomicLong totalSleepMs = new AtomicLong(); - ClusterCommandExecutor testMe = new ClusterCommandExecutor(connectionHandler, 10, ONE_SECOND) { + ClusterCommandExecutor testMe = new ClusterCommandExecutor(connectionHandler, 5, ONE_SECOND) { @Override public T execute(Connection connection, CommandObject commandObject) { @@ -283,7 +283,7 @@ public T execute(Connection connection, CommandObject commandObject) { @Override protected void sleep(long sleepMillis) { - assert sleepMillis > 0; + // assert sleepMillis > 0; totalSleepMs.addAndGet(sleepMillis); } }; @@ -294,7 +294,7 @@ protected void sleep(long sleepMillis) { inOrder.verify(connectionHandler).renewSlotCache(); inOrder.verify(connectionHandler).getConnection(STR_COM_OBJECT.getArguments()); inOrder.verifyNoMoreInteractions(); - assertTrue(totalSleepMs.get() > 0); + MatcherAssert.assertThat(totalSleepMs.get(), Matchers.greaterThan(0L)); } @Test(expected = JedisClusterOperationException.class) @@ -322,7 +322,8 @@ protected void sleep(long ignored) { public void runStopsRetryingAfterTimeout() { ClusterConnectionProvider connectionHandler = mock(ClusterConnectionProvider.class); - final LongConsumer sleep = mock(LongConsumer.class); + //final LongConsumer sleep = mock(LongConsumer.class); + final AtomicLong totalSleepMs = new AtomicLong(); ClusterCommandExecutor testMe = new ClusterCommandExecutor(connectionHandler, 3, Duration.ZERO) { @Override public T execute(Connection connection, CommandObject commandObject) { @@ -337,7 +338,8 @@ public T execute(Connection connection, CommandObject commandObject) { @Override protected void sleep(long sleepMillis) { - sleep.accept(sleepMillis); + //sleep.accept(sleepMillis); + totalSleepMs.addAndGet(sleepMillis); } }; @@ -347,8 +349,10 @@ protected void sleep(long sleepMillis) { } catch (JedisClusterOperationException e) { // expected } - InOrder inOrder = inOrder(connectionHandler, sleep); + //InOrder inOrder = inOrder(connectionHandler, sleep); + InOrder inOrder = inOrder(connectionHandler); inOrder.verify(connectionHandler).getConnection(STR_COM_OBJECT.getArguments()); inOrder.verifyNoMoreInteractions(); + assertEquals(0L, totalSleepMs.get()); } } diff --git a/src/test/java/redis/clients/jedis/ClusterPipeliningTest.java b/src/test/java/redis/clients/jedis/ClusterPipeliningTest.java index b7f8701a29..3ed45bae63 100644 --- a/src/test/java/redis/clients/jedis/ClusterPipeliningTest.java +++ b/src/test/java/redis/clients/jedis/ClusterPipeliningTest.java @@ -1,17 +1,16 @@ package redis.clients.jedis; -import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.*; import static redis.clients.jedis.Protocol.CLUSTER_HASHSLOTS; import java.util.*; -import org.hamcrest.CoreMatchers; -import org.hamcrest.Matcher; import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import redis.clients.jedis.args.*; @@ -21,6 +20,7 @@ import redis.clients.jedis.resps.GeoRadiusResponse; import redis.clients.jedis.resps.StreamEntry; import redis.clients.jedis.resps.Tuple; +import redis.clients.jedis.util.AssertUtil; import redis.clients.jedis.util.JedisClusterTestUtil; import redis.clients.jedis.util.SafeEncoder; @@ -35,13 +35,13 @@ public class ClusterPipeliningTest { private static Jedis node2; private static Jedis node3; - private HostAndPort nodeInfo1 = HostAndPorts.getClusterServers().get(0); - private HostAndPort nodeInfo2 = HostAndPorts.getClusterServers().get(1); - private HostAndPort nodeInfo3 = HostAndPorts.getClusterServers().get(2); + private static HostAndPort nodeInfo1 = HostAndPorts.getClusterServers().get(0); + private static HostAndPort nodeInfo2 = HostAndPorts.getClusterServers().get(1); + private static HostAndPort nodeInfo3 = HostAndPorts.getClusterServers().get(2); private Set nodes = new HashSet<>(Arrays.asList(nodeInfo1, nodeInfo2, nodeInfo3)); - @Before - public void setUp() throws InterruptedException { + @BeforeClass + public static void setUp() throws InterruptedException { node1 = new Jedis(nodeInfo1); node1.auth("cluster"); node1.flushAll(); @@ -80,8 +80,22 @@ public void setUp() throws InterruptedException { JedisClusterTestUtil.waitForClusterReady(node1, node2, node3); } + @Before + public void prepare() { + node1.flushAll(); + node2.flushAll(); + node3.flushAll(); + } + + @After + public void cleanUp() { + node1.flushDB(); + node2.flushDB(); + node3.flushDB(); + } + @AfterClass - public static void cleanUp() { + public static void tearDown() throws InterruptedException { node1.flushDB(); node2.flushDB(); node3.flushDB(); @@ -90,11 +104,6 @@ public static void cleanUp() { node3.clusterReset(ClusterResetType.SOFT); } - @After - public void tearDown() throws InterruptedException { - cleanUp(); - } - @Test public void constructorClientConfig() { try (ClusterPipeline pipe = new ClusterPipeline(nodes, DEFAULT_CLIENT_CONFIG)) { @@ -518,7 +527,7 @@ public void clusterPipelineSet() { Response r1 = p.sadd("my{set}", "hello", "hello", "world", "foo", "bar"); p.sadd("mynew{set}", "hello", "hello", "world"); Response> r2 = p.sdiff("my{set}", "mynew{set}"); - Response r3 = p.sdiffstore("diffset{set}", "my{set}", "mynew{set}"); + Response r3 = p.sdiffStore("diffset{set}", "my{set}", "mynew{set}"); Response> r4 = p.smembers("diffset{set}"); Response> r5 = p.sinter("my{set}", "mynew{set}"); Response r6 = p.sinterstore("interset{set}", "my{set}", "mynew{set}"); @@ -649,9 +658,11 @@ public void clusterPipelineHash() { Response> r11 = p.hvals("mynewhash"); Response> r12 = p.hmget("myhash", "field1", "field2"); Response r13 = p.hrandfield("myotherhash"); - Response> r14 = p.hrandfield("myotherhash", 2); - Response> r15 = p.hrandfieldWithValues("myotherhash", 2); + Response> r14 = p.hrandfield("myotherhash", 4); + Response> r15 = p.hrandfield("myotherhash", -4); Response r16 = p.hstrlen("myhash", "field1"); + Response>> r17 = p.hrandfieldWithValues("myotherhash", 4); + Response>> r18 = p.hrandfieldWithValues("myotherhash", -4); p.sync(); assertEquals(Long.valueOf(1), r1.get()); @@ -666,10 +677,12 @@ public void clusterPipelineHash() { assertEquals(keys, r10.get()); assertEquals(vals, r11.get()); assertEquals(vals2, r12.get()); - assertTrue(hm.keySet().contains(r13.get())); + AssertUtil.assertCollectionContains(hm.keySet(), r13.get()); assertEquals(2, r14.get().size()); - assertTrue(r15.get().containsKey("field3") && r15.get().containsValue("5")); + assertEquals(4, r15.get().size()); assertEquals(Long.valueOf(5), r16.get()); + assertEquals(2, r17.get().size()); + assertEquals(4, r18.get().size()); } @Test @@ -816,8 +829,8 @@ public void clusterPipelineStream() { Response r3 = p.xlen("mystream"); Response> r4 = p.xrange("mystream", streamId1, streamId2); Response> r5 = p.xrange("mystream", streamId1, streamId2, 1); - Response> r6 = p.xrevrange("mystream", streamId1, streamId2); - Response> r7 = p.xrevrange("mystream", streamId1, streamId2, 1); + Response> r6 = p.xrevrange("mystream", streamId2, streamId1); + Response> r7 = p.xrevrange("mystream", streamId2, streamId1, 1); Response r8 = p.xgroupCreate("mystream", "group", streamId1, false); Response r9 = p.xgroupSetID("mystream", "group", streamId2); // More stream commands are missing @@ -917,8 +930,8 @@ public void testEvalNestedLists() { p.sync(); List results = (List) result.get(); - MatcherAssert.assertThat((List) results.get(0), listWithItem("key1")); - MatcherAssert.assertThat((List) results.get(1), listWithItem(2L)); + MatcherAssert.assertThat((List) results.get(0), Matchers.hasItem("key1")); + MatcherAssert.assertThat((List) results.get(1), Matchers.hasItem(2L)); } } @@ -933,8 +946,8 @@ public void testEvalNestedListsWithBinary() { p.sync(); List results = (List) result.get(); - MatcherAssert.assertThat((List) results.get(0), listWithItem(bKey)); - MatcherAssert.assertThat((List) results.get(1), listWithItem(2L)); + MatcherAssert.assertThat((List) results.get(0), Matchers.hasItem(bKey)); + MatcherAssert.assertThat((List) results.get(1), Matchers.hasItem(2L)); } } @@ -1009,10 +1022,6 @@ public void testEvalshaKeyAndArgWithBinary() { } } - private Matcher> listWithItem(T expected) { - return CoreMatchers.hasItem(equalTo(expected)); - } - @Test public void simple() { // TODO: move into 'redis.clients.jedis.commands.unified.cluster' package try (JedisCluster jedis = new JedisCluster(nodes, DEFAULT_CLIENT_CONFIG)) { @@ -1045,4 +1054,47 @@ public void simple() { // TODO: move into 'redis.clients.jedis.commands.unified. } } } + + @Test + public void transaction() { + try (JedisCluster cluster = new JedisCluster(nodes, DEFAULT_CLIENT_CONFIG)) { + assertThrows(UnsupportedOperationException.class, () -> cluster.multi()); + } + } + + @Test(timeout = 10_000L) + public void multiple() { + final int maxTotal = 100; + ConnectionPoolConfig poolConfig = new ConnectionPoolConfig(); + poolConfig.setMaxTotal(maxTotal); + try (JedisCluster cluster = new JedisCluster(nodes, DEFAULT_CLIENT_CONFIG, 5, poolConfig)) { + for (int i = 0; i < maxTotal; i++) { + assertThreadsCount(); + String s = Integer.toString(i); + try (ClusterPipeline pipeline = cluster.pipelined()) { + pipeline.set(s, s); + pipeline.sync(); + } + assertThreadsCount(); + } + } + } + + private static void assertThreadsCount() { + // Get the root thread group + final ThreadGroup rootGroup = Thread.currentThread().getThreadGroup().getParent(); + + // Create a buffer to store the thread information + final Thread[] threads = new Thread[rootGroup.activeCount()]; + + // Enumerate all threads into the buffer + rootGroup.enumerate(threads); + + // Assert information about threads + final int count = (int) Arrays.stream(threads) + .filter(thread -> thread != null && thread.getName() != null + && thread.getName().startsWith("pool-")) + .count(); + MatcherAssert.assertThat(count, Matchers.lessThanOrEqualTo(20)); + } } diff --git a/src/test/java/redis/clients/jedis/ConnectionTest.java b/src/test/java/redis/clients/jedis/ConnectionTest.java index ee9a0a9742..28eba8100c 100644 --- a/src/test/java/redis/clients/jedis/ConnectionTest.java +++ b/src/test/java/redis/clients/jedis/ConnectionTest.java @@ -17,7 +17,7 @@ public void tearDown() throws Exception { } @Test(expected = JedisConnectionException.class) - public void checkUnkownHost() { + public void checkUnknownHost() { client = new Connection("someunknownhost", Protocol.DEFAULT_PORT); client.connect(); } diff --git a/src/test/java/redis/clients/jedis/JedisClusterTest.java b/src/test/java/redis/clients/jedis/JedisClusterTest.java index b93fa2409e..8297eb90c6 100644 --- a/src/test/java/redis/clients/jedis/JedisClusterTest.java +++ b/src/test/java/redis/clients/jedis/JedisClusterTest.java @@ -741,6 +741,65 @@ public void clusterRefreshNodes() throws Exception { } } + @Test(timeout = 30_000) + public void clusterPeriodTopologyRefreshTest() throws Exception { + Set jedisClusterNode = new HashSet<>(); + jedisClusterNode.add(nodeInfo1); + jedisClusterNode.add(nodeInfo2); + jedisClusterNode.add(nodeInfo3); + + // we set topologyRefreshPeriod is 1s + Duration topologyRefreshPeriod = Duration.ofSeconds(1); + try (JedisCluster cluster = new JedisCluster(jedisClusterNode, DEFAULT_CLIENT_CONFIG, DEFAULT_POOL_CONFIG, + topologyRefreshPeriod, DEFAULT_REDIRECTIONS, Duration.ofSeconds(10))) { + assertEquals(3, cluster.getClusterNodes().size()); + cleanUp(); // cleanup and add node4 + + // at first, join node4 to cluster + node1.clusterMeet(LOCAL_IP, nodeInfo2.getPort()); + node1.clusterMeet(LOCAL_IP, nodeInfo3.getPort()); + node1.clusterMeet(LOCAL_IP, nodeInfo4.getPort()); + // split available slots across the three nodes + int slotsPerNode = CLUSTER_HASHSLOTS / 4; + int[] node1Slots = new int[slotsPerNode]; + int[] node2Slots = new int[slotsPerNode]; + int[] node3Slots = new int[slotsPerNode]; + int[] node4Slots = new int[slotsPerNode]; + for (int i = 0, slot1 = 0, slot2 = 0, slot3 = 0, slot4 = 0; i < CLUSTER_HASHSLOTS; i++) { + if (i < slotsPerNode) { + node1Slots[slot1++] = i; + } else if (i >= slotsPerNode && i < slotsPerNode*2) { + node2Slots[slot2++] = i; + } else if (i >= slotsPerNode*2 && i < slotsPerNode*3) { + node3Slots[slot3++] = i; + } else { + node4Slots[slot4++] = i; + } + } + + node1.clusterAddSlots(node1Slots); + node2.clusterAddSlots(node2Slots); + node3.clusterAddSlots(node3Slots); + node4.clusterAddSlots(node4Slots); + JedisClusterTestUtil.waitForClusterReady(node1, node2, node3, node4); + + // Now we just wait topologyRefreshPeriod * 3 (executor will delay) for cluster topology refresh (3 -> 4) + Thread.sleep(topologyRefreshPeriod.toMillis() * 3); + + assertEquals(4, cluster.getClusterNodes().size()); + String nodeKey4 = LOCAL_IP + ":" + nodeInfo4.getPort(); + assertTrue(cluster.getClusterNodes().keySet().contains(nodeKey4)); + + // make 4 nodes to 3 nodes + cleanUp(); + setUp(); + + // Now we just wait topologyRefreshPeriod * 3 (executor will delay) for cluster topology refresh (4 -> 3) + Thread.sleep(topologyRefreshPeriod.toMillis() * 3); + assertEquals(3, cluster.getClusterNodes().size()); + } + } + private static String getNodeServingSlotRange(String infoOutput) { // f4f3dc4befda352a4e0beccf29f5e8828438705d 127.0.0.1:7380 master - 0 // 1394372400827 0 connected 5461-10922 diff --git a/src/test/java/redis/clients/jedis/JedisClusterTestBase.java b/src/test/java/redis/clients/jedis/JedisClusterTestBase.java index 6094575a54..0746c2d37c 100644 --- a/src/test/java/redis/clients/jedis/JedisClusterTestBase.java +++ b/src/test/java/redis/clients/jedis/JedisClusterTestBase.java @@ -77,10 +77,10 @@ protected void cleanUp() { node2.flushDB(); node3.flushDB(); node4.flushDB(); - node1.clusterReset(ClusterResetType.SOFT); - node2.clusterReset(ClusterResetType.SOFT); - node3.clusterReset(ClusterResetType.SOFT); - node4.clusterReset(ClusterResetType.SOFT); + node1.clusterReset(ClusterResetType.HARD); + node2.clusterReset(ClusterResetType.HARD); + node3.clusterReset(ClusterResetType.HARD); + node4.clusterReset(ClusterResetType.HARD); } @After diff --git a/src/test/java/redis/clients/jedis/JedisPoolTest.java b/src/test/java/redis/clients/jedis/JedisPoolTest.java index 89537df974..a256abcae0 100644 --- a/src/test/java/redis/clients/jedis/JedisPoolTest.java +++ b/src/test/java/redis/clients/jedis/JedisPoolTest.java @@ -13,6 +13,7 @@ import org.apache.commons.pool2.PooledObjectFactory; import org.apache.commons.pool2.impl.DefaultPooledObject; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import org.junit.Assert; import org.junit.Test; import redis.clients.jedis.exceptions.InvalidURIException; @@ -78,7 +79,7 @@ public void checkResourceIsClosableAndReusable() { config.setMaxTotal(1); config.setBlockWhenExhausted(false); try (JedisPool pool = new JedisPool(config, hnp.getHost(), hnp.getPort(), 2000, "foobared", 0, - "closable-resuable-pool", false, null, null, null)) { + "closable-reusable-pool", false, null, null, null)) { Jedis jedis = pool.getResource(); jedis.set("hello", "jedis"); @@ -97,7 +98,7 @@ public void checkPoolRepairedWhenJedisIsBroken() { try (Jedis jedis = pool.getResource()) { jedis.auth("foobared"); jedis.set("foo", "0"); - jedis.quit(); + jedis.disconnect(); } try (Jedis jedis = pool.getResource()) { @@ -219,6 +220,17 @@ public void customClientName() { } } + @Test + public void invalidClientName() { + try (JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), hnp.getPort(), 2000, + "foobared", 0, "invalid client name"); Jedis jedis = pool.getResource()) { + } catch (Exception e) { + if (!e.getMessage().startsWith("client info cannot contain space")) { + Assert.fail("invalid client name test fail"); + } + } + } + @Test public void returnResourceDestroysResourceOnException() { @@ -393,9 +405,11 @@ private int getClientCount(final String clientList) { } @Test - public void testResetInvalidPassword() { - JedisFactory factory = new JedisFactory(hnp.getHost(), hnp.getPort(), 2000, 2000, - "foobared", 0, "my_shiny_client_name") { }; + public void testResetInvalidCredentials() { + DefaultRedisCredentialsProvider credentialsProvider + = new DefaultRedisCredentialsProvider(new DefaultRedisCredentials(null, "foobared")); + JedisFactory factory = new JedisFactory(hnp, DefaultJedisClientConfig.builder() + .credentialsProvider(credentialsProvider).clientName("my_shiny_client_name").build()); try (JedisPool pool = new JedisPool(new JedisPoolConfig(), factory)) { Jedis obj1_ref; @@ -409,7 +423,7 @@ public void testResetInvalidPassword() { try (Jedis obj1_2 = pool.getResource()) { assertSame(obj1_ref, obj1_2); assertEquals(1, pool.getNumActive()); - factory.setPassword("wrong password"); + credentialsProvider.setCredentials(new DefaultRedisCredentials(null, "wrong password")); try (Jedis obj2 = pool.getResource()) { fail("Should not get resource from pool"); } catch (JedisException e) { } @@ -420,9 +434,11 @@ public void testResetInvalidPassword() { } @Test - public void testResetValidPassword() { - JedisFactory factory = new JedisFactory(hnp.getHost(), hnp.getPort(), 2000, 2000, - "bad password", 0, "my_shiny_client_name") { }; + public void testResetValidCredentials() { + DefaultRedisCredentialsProvider credentialsProvider + = new DefaultRedisCredentialsProvider(new DefaultRedisCredentials(null, "bad password")); + JedisFactory factory = new JedisFactory(hnp, DefaultJedisClientConfig.builder() + .credentialsProvider(credentialsProvider).clientName("my_shiny_client_name").build()); try (JedisPool pool = new JedisPool(new JedisPoolConfig(), factory)) { try (Jedis obj1 = pool.getResource()) { @@ -430,7 +446,7 @@ public void testResetValidPassword() { } catch (JedisException e) { } assertEquals(0, pool.getNumActive()); - factory.setPassword("foobared"); + credentialsProvider.setCredentials(new DefaultRedisCredentials(null, "foobared")); try (Jedis obj2 = pool.getResource()) { obj2.set("foo", "bar"); assertEquals("bar", obj2.get("foo")); diff --git a/src/test/java/redis/clients/jedis/JedisPooledTest.java b/src/test/java/redis/clients/jedis/JedisPooledTest.java index 92614a30fb..6036062f5b 100644 --- a/src/test/java/redis/clients/jedis/JedisPooledTest.java +++ b/src/test/java/redis/clients/jedis/JedisPooledTest.java @@ -1,12 +1,19 @@ package redis.clients.jedis; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.anything; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.net.URI; import java.net.URISyntaxException; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import org.junit.Assert; import org.junit.Test; import redis.clients.jedis.exceptions.JedisConnectionException; @@ -15,6 +22,7 @@ public class JedisPooledTest { private static final HostAndPort hnp = HostAndPorts.getRedisServers().get(7); + private static final HostAndPort pwp = HostAndPorts.getRedisServers().get(1); // password protected @Test public void checkCloseableConnections() { @@ -89,12 +97,25 @@ public void allowUrlWithNoDBAndNoPassword() throws URISyntaxException { @Test public void customClientName() { - try (JedisPooled pool = new JedisPooled(hnp, DefaultJedisClientConfig.builder().clientName("my_shiny_client_name").build()); + try (JedisPooled pool = new JedisPooled(hnp, DefaultJedisClientConfig.builder() + .clientName("my_shiny_client_name").build()); Connection jedis = pool.getPool().getResource()) { assertEquals("my_shiny_client_name", new Jedis(jedis).clientGetname()); } } + @Test + public void invalidClientName() { + try (JedisPooled pool = new JedisPooled(hnp, DefaultJedisClientConfig.builder() + .clientName("invalid client name").build()); + Connection jedis = pool.getPool().getResource()) { + } catch (Exception e) { + if (!e.getMessage().startsWith("client info cannot contain space")) { + Assert.fail("invalid client name test fail"); + } + } + } + @Test public void getNumActiveWhenPoolIsClosed() { JedisPooled pool = new JedisPooled(hnp); @@ -153,21 +174,85 @@ public void closeBrokenResourceTwice() { } @Test - public void testResetValidPassword() { - ConnectionFactory factory = new ConnectionFactory(HostAndPorts.getRedisServers().get(0), - DefaultJedisClientConfig.builder().password("bad password") - .clientName("my_shiny_client_name").build()); + public void testResetValidCredentials() { + DefaultRedisCredentialsProvider credentialsProvider = + new DefaultRedisCredentialsProvider(new DefaultRedisCredentials(null, "bad password")); - try (JedisPooled pool = new JedisPooled(new ConnectionPoolConfig(), factory)) { + try (JedisPooled pool = new JedisPooled(pwp, DefaultJedisClientConfig.builder() + .credentialsProvider(credentialsProvider).build())) { try { pool.get("foo"); fail("Should not get resource from pool"); } catch (JedisException e) { } assertEquals(0, pool.getPool().getNumActive()); - factory.setPassword("foobared"); - pool.set("foo", "bar"); - assertEquals("bar", pool.get("foo")); + credentialsProvider.setCredentials(new DefaultRedisCredentials(null, "foobared")); + assertThat(pool.get("foo"), anything()); + } + } + + @Test + public void testCredentialsProvider() { + final AtomicInteger prepareCount = new AtomicInteger(); + final AtomicInteger cleanupCount = new AtomicInteger(); + final AtomicBoolean validPassword = new AtomicBoolean(false); + + RedisCredentialsProvider credentialsProvider = new RedisCredentialsProvider() { + + @Override + public void prepare() { + prepareCount.incrementAndGet(); + } + + @Override + public RedisCredentials get() { + if (!validPassword.get()) { + return new RedisCredentials() { + @Override + public char[] getPassword() { + return "invalidPass".toCharArray(); + } + }; + } + + return new RedisCredentials() { + @Override + public String getUser() { + return null; + } + + @Override + public char[] getPassword() { + return "foobared".toCharArray(); + } + }; + } + + @Override + public void cleanUp() { + cleanupCount.incrementAndGet(); + } + }; + + // TODO: do it without the help of pool config; from Connection constructor? (configurable) force ping? + GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig<>(); + poolConfig.setMaxTotal(1); + poolConfig.setTestOnBorrow(true); + try (JedisPooled pool = new JedisPooled(pwp, DefaultJedisClientConfig.builder() + .credentialsProvider(credentialsProvider).build(), poolConfig)) { + try { + pool.get("foo"); + fail("Should not get resource from pool"); + } catch (JedisException e) { + } + assertEquals(0, pool.getPool().getNumActive() + pool.getPool().getNumIdle() + pool.getPool().getNumWaiters()); + assertThat(prepareCount.getAndSet(0), greaterThanOrEqualTo(1)); + assertThat(cleanupCount.getAndSet(0), greaterThanOrEqualTo(1)); + + validPassword.set(true); + assertThat(pool.get("foo"), anything()); + assertThat(prepareCount.get(), equalTo(1)); + assertThat(cleanupCount.get(), equalTo(1)); } } } diff --git a/src/test/java/redis/clients/jedis/JedisSentinelPoolTest.java b/src/test/java/redis/clients/jedis/JedisSentinelPoolTest.java index 1d52d14784..d00da82447 100644 --- a/src/test/java/redis/clients/jedis/JedisSentinelPoolTest.java +++ b/src/test/java/redis/clients/jedis/JedisSentinelPoolTest.java @@ -3,7 +3,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertSame; -import static org.junit.Assert.fail; import java.util.HashSet; import java.util.Set; @@ -145,42 +144,4 @@ public void customClientName() { assertTrue(pool.isClosed()); } - - @Test - public void testResetInvalidPassword() { - JedisFactory factory = new JedisFactory(null, 0, 2000, 2000, "foobared", 0, "my_shiny_client_name") { }; - - try (JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels, new JedisPoolConfig(), factory)) { - Jedis obj1_ref; - try (Jedis obj1_1 = pool.getResource()) { - obj1_ref = obj1_1; - obj1_1.set("foo", "bar"); - assertEquals("bar", obj1_1.get("foo")); - } - try (Jedis obj1_2 = pool.getResource()) { - assertSame(obj1_ref, obj1_2); - factory.setPassword("wrong password"); - try (Jedis obj2 = pool.getResource()) { - fail("Should not get resource from pool"); - } catch (JedisException e) { } - } - } - } - - @Test - public void testResetValidPassword() { - JedisFactory factory = new JedisFactory(null, 0, 2000, 2000, "wrong password", 0, "my_shiny_client_name") { }; - - try (JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels, new JedisPoolConfig(), factory)) { - try (Jedis obj1 = pool.getResource()) { - fail("Should not get resource from pool"); - } catch (JedisException e) { } - - factory.setPassword("foobared"); - try (Jedis obj2 = pool.getResource()) { - obj2.set("foo", "bar"); - assertEquals("bar", obj2.get("foo")); - } - } - } } diff --git a/src/test/java/redis/clients/jedis/JedisTest.java b/src/test/java/redis/clients/jedis/JedisTest.java index d2344967b7..e9520ff394 100644 --- a/src/test/java/redis/clients/jedis/JedisTest.java +++ b/src/test/java/redis/clients/jedis/JedisTest.java @@ -60,12 +60,16 @@ public void connectWithConfig() { } @Test - public void connectWithConfigInterface() { + public void connectWithEmptyConfigInterface() { try (Jedis jedis = new Jedis(hnp, new JedisClientConfig() { })) { jedis.auth("foobared"); assertEquals("PONG", jedis.ping()); } + } + + @Test + public void connectWithConfigInterface() { try (Jedis jedis = new Jedis(hnp, new JedisClientConfig() { @Override public String getPassword() { @@ -76,31 +80,54 @@ public String getPassword() { } } + @Test + public void connectOnResp3Protocol() { + try (Jedis jedis = new Jedis(hnp, DefaultJedisClientConfig.builder() + .protocol(RedisProtocol.RESP3).password("foobared").build())) { + assertEquals("PONG", jedis.ping()); + assertEquals(RedisProtocol.RESP3, jedis.getConnection().getRedisProtocol()); + } + } + + @Test + public void connectOnResp3ProtocolShortcut() { + try (Jedis jedis = new Jedis(hnp, DefaultJedisClientConfig.builder().resp3() + .password("foobared").build())) { + assertEquals("PONG", jedis.ping()); + assertEquals(RedisProtocol.RESP3, jedis.getConnection().getRedisProtocol()); + } + } + @Test public void timeoutConnection() throws Exception { + final String TIMEOUT_STR = "timeout"; + Jedis jedis = new Jedis("localhost", 6379, 15000); jedis.auth("foobared"); - String timeout = jedis.configGet("timeout").get(1); - jedis.configSet("timeout", "1"); - Thread.sleep(2000); + // read current config + final String timeout = jedis.configGet(TIMEOUT_STR).get(TIMEOUT_STR); try { - jedis.hmget("foobar", "foo"); - fail("Operation should throw JedisConnectionException"); - } catch (JedisConnectionException jce) { - // expected + jedis.configSet("timeout", "1"); + Thread.sleep(5000); + try { + jedis.hmget("foobar", "foo"); + fail("Operation should throw JedisConnectionException"); + } catch (JedisConnectionException jce) { + // expected + } + jedis.close(); + } finally { + // reset config + jedis = new Jedis("localhost", 6379); + jedis.auth("foobared"); + jedis.configSet(TIMEOUT_STR, timeout); + jedis.close(); } - jedis.close(); - - // reset config - jedis = new Jedis("localhost", 6379); - jedis.auth("foobared"); - jedis.configSet("timeout", timeout); - jedis.close(); } @Test public void infiniteTimeout() throws Exception { - try (Jedis timeoutJedis = new Jedis("localhost", 6379, 350, 350, 350)) { + try (Jedis timeoutJedis = new Jedis("localhost", 6379, 200, 200, 200)) { timeoutJedis.auth("foobared"); try { timeoutJedis.blpop(0, "foo"); @@ -133,7 +160,7 @@ public void shouldThrowInvalidURIExceptionForInvalidURI() throws URISyntaxExcept // } @Test - public void startWithUrl() { + public void connectWithUrl() { try (Jedis j = new Jedis("localhost", 6380)) { j.auth("foobared"); j.select(2); @@ -147,7 +174,7 @@ public void startWithUrl() { } @Test - public void startWithUri() throws URISyntaxException { + public void connectWithUri() throws URISyntaxException { try (Jedis j = new Jedis("localhost", 6380)) { j.auth("foobared"); j.select(2); @@ -160,6 +187,34 @@ public void startWithUri() throws URISyntaxException { } } + @Test + public void connectWithUrlOnResp3() { + try (Jedis j = new Jedis("localhost", 6380)) { + j.auth("foobared"); + j.select(2); + j.set("foo", "bar"); + } + + try (Jedis j2 = new Jedis("redis://:foobared@localhost:6380/2?protocol=3")) { + assertEquals("PONG", j2.ping()); + assertEquals("bar", j2.get("foo")); + } + } + + @Test + public void connectWithUriOnResp3() throws URISyntaxException { + try (Jedis j = new Jedis("localhost", 6380)) { + j.auth("foobared"); + j.select(2); + j.set("foo", "bar"); + } + + try (Jedis jedis = new Jedis(new URI("redis://:foobared@localhost:6380/2?protocol=3"))) { + assertEquals("PONG", jedis.ping()); + assertEquals("bar", jedis.get("foo")); + } + } + @Test public void shouldNotUpdateDbIndexIfSelectFails() { int currentDb = jedis.getDB(); @@ -229,8 +284,43 @@ public void checkCloseableAfterCommand() { @Test public void checkDisconnectOnQuit() { - jedis.quit(); + jedis.disconnect(); assertFalse(jedis.isConnected()); } + @Test + public void clientSetInfoDefault() { + try (Jedis jedis = new Jedis(hnp, DefaultJedisClientConfig.builder().password("foobared") + .clientSetInfoConfig(ClientSetInfoConfig.DEFAULT).build())) { + assertEquals("PONG", jedis.ping()); + String info = jedis.clientInfo(); + assertTrue(info.contains("lib-name=" + JedisMetaInfo.getArtifactId())); + assertTrue(info.contains("lib-ver=" + JedisMetaInfo.getVersion())); + } + } + + @Test + public void clientSetInfoDisabled() { + try (Jedis jedis = new Jedis(hnp, DefaultJedisClientConfig.builder().password("foobared") + .clientSetInfoConfig(ClientSetInfoConfig.DISABLED).build())) { + assertEquals("PONG", jedis.ping()); + String info = jedis.clientInfo(); + assertFalse(info.contains("lib-name=" + JedisMetaInfo.getArtifactId())); + assertFalse(info.contains("lib-ver=" + JedisMetaInfo.getVersion())); + } + } + + @Test + public void clientSetInfoLibNameSuffix() { + final String libNameSuffix = "for-redis"; + ClientSetInfoConfig setInfoConfig = ClientSetInfoConfig.withLibNameSuffix(libNameSuffix); + try (Jedis jedis = new Jedis(hnp, DefaultJedisClientConfig.builder().password("foobared") + .clientSetInfoConfig(setInfoConfig).build())) { + assertEquals("PONG", jedis.ping()); + String info = jedis.clientInfo(); + assertTrue(info.contains("lib-name=" + JedisMetaInfo.getArtifactId() + '(' + libNameSuffix + ')')); + assertTrue(info.contains("lib-ver=" + JedisMetaInfo.getVersion())); + } + } + } diff --git a/src/test/java/redis/clients/jedis/PipeliningTest.java b/src/test/java/redis/clients/jedis/PipeliningTest.java index 8d2e02f9d2..bb9834c8d6 100644 --- a/src/test/java/redis/clients/jedis/PipeliningTest.java +++ b/src/test/java/redis/clients/jedis/PipeliningTest.java @@ -1,12 +1,10 @@ package redis.clients.jedis; -import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -18,8 +16,8 @@ import java.util.Set; import java.util.UUID; -import org.hamcrest.CoreMatchers; -import org.hamcrest.Matcher; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; import org.junit.Test; import redis.clients.jedis.exceptions.JedisDataException; @@ -210,9 +208,13 @@ private void verifyHasBothValues(byte[] firstKey, byte[] secondKey, byte[] value @Test public void pipelineSelect() { + jedis.set("foo", "bar"); + jedis.swapDB(0, 1); Pipeline p = jedis.pipelined(); + p.get("foo"); p.select(1); - p.sync(); + p.get("foo"); + assertEquals(Arrays.asList(null, "OK", "bar"), p.syncAndReturnAll()); } @Test @@ -465,6 +467,19 @@ public void waitReplicas() { } } + @Test + public void waitAof() { + Pipeline p = jedis.pipelined(); + p.set("wait", "aof"); + p.waitAOF(1L, 0L, 0L); + p.sync(); + + try (Jedis j = new Jedis(HostAndPorts.getRedisServers().get(4))) { + j.auth("foobared"); + assertEquals("aof", j.get("wait")); + } + } + @Test public void setGet() { Pipeline p = jedis.pipelined(); @@ -566,8 +581,8 @@ public void testEvalNestedLists() { p.sync(); List results = (List) result.get(); - assertThat((List) results.get(0), listWithItem("key1")); - assertThat((List) results.get(1), listWithItem(2L)); + MatcherAssert.assertThat((List) results.get(0), Matchers.hasItem("key1")); + MatcherAssert.assertThat((List) results.get(1), Matchers.hasItem(2L)); } @Test @@ -580,8 +595,8 @@ public void testEvalNestedListsWithBinary() { p.sync(); List results = (List) result.get(); - assertThat((List) results.get(0), listWithItem(bKey)); - assertThat((List) results.get(1), listWithItem(2L)); + MatcherAssert.assertThat((List) results.get(0), Matchers.hasItem(bKey)); + MatcherAssert.assertThat((List) results.get(1), Matchers.hasItem(2L)); } @Test @@ -852,8 +867,4 @@ public void testCloseable() throws IOException { // assertTrue(firstKey.equals(value1) || firstKey.equals(value2)); // assertTrue(secondKey.equals(value1) || secondKey.equals(value2)); // } - - private Matcher> listWithItem(T expected) { - return CoreMatchers. hasItem(equalTo(expected)); - } } diff --git a/src/test/java/redis/clients/jedis/SSLACLJedisTest.java b/src/test/java/redis/clients/jedis/SSLACLJedisTest.java index a5f8d4adf5..0d0ca4e7eb 100644 --- a/src/test/java/redis/clients/jedis/SSLACLJedisTest.java +++ b/src/test/java/redis/clients/jedis/SSLACLJedisTest.java @@ -42,8 +42,8 @@ public void connectWithSsl() { @Test public void connectWithConfig() { - try (Jedis jedis = new Jedis(new HostAndPort("localhost", 6390), DefaultJedisClientConfig - .builder().ssl(true).build())) { + try (Jedis jedis = new Jedis(new HostAndPort("localhost", 6390), + DefaultJedisClientConfig.builder().ssl(true).build())) { jedis.auth("acljedis", "fizzbuzz"); assertEquals("PONG", jedis.ping()); } @@ -51,19 +51,6 @@ public void connectWithConfig() { @Test public void connectWithUrl() { - // The "rediss" scheme instructs jedis to open a SSL/TLS connection. - try (Jedis jedis = new Jedis("rediss://localhost:6390")) { - jedis.auth("default", "foobared"); - assertEquals("PONG", jedis.ping()); - } - try (Jedis jedis = new Jedis("rediss://localhost:6390")) { - jedis.auth("acljedis", "fizzbuzz"); - assertEquals("PONG", jedis.ping()); - } - } - - @Test - public void connectWithCompleteCredentialsUrl() { // The "rediss" scheme instructs jedis to open a SSL/TLS connection. try (Jedis jedis = new Jedis("rediss://default:foobared@localhost:6390")) { assertEquals("PONG", jedis.ping()); @@ -75,15 +62,6 @@ public void connectWithCompleteCredentialsUrl() { @Test public void connectWithUri() { - // The "rediss" scheme instructs jedis to open a SSL/TLS connection. - try (Jedis jedis = new Jedis(URI.create("rediss://localhost:6390"))) { - jedis.auth("acljedis", "fizzbuzz"); - assertEquals("PONG", jedis.ping()); - } - } - - @Test - public void connectWithCompleteCredentialsUri() { // The "rediss" scheme instructs jedis to open a SSL/TLS connection. try (Jedis jedis = new Jedis(URI.create("rediss://default:foobared@localhost:6390"))) { assertEquals("PONG", jedis.ping()); diff --git a/src/test/java/redis/clients/jedis/SSLJedisTest.java b/src/test/java/redis/clients/jedis/SSLJedisTest.java index 5c6d22de99..75619dfef9 100644 --- a/src/test/java/redis/clients/jedis/SSLJedisTest.java +++ b/src/test/java/redis/clients/jedis/SSLJedisTest.java @@ -52,8 +52,8 @@ public void connectWithSsl() { @Test public void connectWithConfig() { - try (Jedis jedis = new Jedis(new HostAndPort("localhost", 6390), DefaultJedisClientConfig - .builder().ssl(true).build())) { + try (Jedis jedis = new Jedis(new HostAndPort("localhost", 6390), + DefaultJedisClientConfig.builder().ssl(true).build())) { jedis.auth("foobared"); assertEquals("PONG", jedis.ping()); } @@ -63,11 +63,11 @@ public void connectWithConfig() { public void connectWithConfigInterface() { try (Jedis jedis = new Jedis(new HostAndPort("localhost", 6390), new JedisClientConfig() { - @Override - public boolean isSsl() { - return true; - } - })) { + @Override + public boolean isSsl() { + return true; + } + })) { jedis.auth("foobared"); assertEquals("PONG", jedis.ping()); } diff --git a/src/test/java/redis/clients/jedis/SentineledConnectionProviderTest.java b/src/test/java/redis/clients/jedis/SentineledConnectionProviderTest.java index 97b2d96932..593875710b 100644 --- a/src/test/java/redis/clients/jedis/SentineledConnectionProviderTest.java +++ b/src/test/java/redis/clients/jedis/SentineledConnectionProviderTest.java @@ -2,6 +2,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; +import static org.junit.Assert.fail; import java.util.HashSet; import java.util.Set; @@ -87,60 +88,77 @@ public void checkResourceIsCloseable() { GenericObjectPoolConfig config = new GenericObjectPoolConfig<>(); config.setMaxTotal(1); config.setBlockWhenExhausted(false); - JedisSentineled jedis = new JedisSentineled(MASTER_NAME, + + try (JedisSentineled jedis = new JedisSentineled(MASTER_NAME, DefaultJedisClientConfig.builder().timeoutMillis(1000).password("foobared").database(2).build(), - config, sentinels, DefaultJedisClientConfig.builder().build()); + config, sentinels, DefaultJedisClientConfig.builder().build())) { + + Connection conn = jedis.provider.getConnection(); + try { + conn.ping(); + } finally { + conn.close(); + } + + Connection conn2 = jedis.provider.getConnection(); + try { + assertEquals(conn, conn2); + } finally { + conn2.close(); + } + } + } + + @Test + public void testResetInvalidPassword() { + DefaultRedisCredentialsProvider credentialsProvider + = new DefaultRedisCredentialsProvider(new DefaultRedisCredentials(null, "foobared")); + + try (JedisSentineled jedis = new JedisSentineled(MASTER_NAME, DefaultJedisClientConfig.builder() + .timeoutMillis(2000).credentialsProvider(credentialsProvider).database(2) + .clientName("my_shiny_client_name").build(), new ConnectionPoolConfig(), + sentinels, DefaultJedisClientConfig.builder().build())) { + + jedis.set("foo", "bar"); + + Connection conn1_ref; + try (Connection conn1_1 = jedis.provider.getConnection()) { + conn1_ref = conn1_1; + assertEquals("bar", new Jedis(conn1_1).get("foo")); + } + + credentialsProvider.setCredentials(new DefaultRedisCredentials(null, "wrong password")); - Connection conn = jedis.provider.getConnection(); - try { - conn.ping(); - } finally { - conn.close(); + try (Connection conn1_2 = jedis.provider.getConnection()) { + assertSame(conn1_ref, conn1_2); + + try (Connection conn2 = jedis.provider.getConnection()) { + fail("Should not get resource from pool"); + } catch (JedisException e) { } + } } + } - Connection conn2 = jedis.provider.getConnection(); - try { - assertEquals(conn, conn2); - } finally { - conn2.close(); + @Test + public void testResetValidPassword() { + DefaultRedisCredentialsProvider credentialsProvider + = new DefaultRedisCredentialsProvider(new DefaultRedisCredentials(null, "wrong password")); + + try (JedisSentineled jedis = new JedisSentineled(MASTER_NAME, DefaultJedisClientConfig.builder() + .timeoutMillis(2000).credentialsProvider(credentialsProvider).database(2) + .clientName("my_shiny_client_name").build(), new ConnectionPoolConfig(), + sentinels, DefaultJedisClientConfig.builder().build())) { + + try (Connection conn1 = jedis.provider.getConnection()) { + fail("Should not get resource from pool"); + } catch (JedisException e) { } + + credentialsProvider.setCredentials(new DefaultRedisCredentials(null, "foobared")); + + try (Connection conn2 = jedis.provider.getConnection()) { + new Jedis(conn2).set("foo", "bar"); + assertEquals("bar", jedis.get("foo")); + } } } -// -// @Test -// public void testResetInvalidPassword() { -// JedisFactory factory = new JedisFactory(null, 0, 2000, 2000, "foobared", 0, "my_shiny_client_name") { }; -// -// try (JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels, new JedisPoolConfig(), factory)) { -// Jedis obj1_ref; -// try (Jedis obj1_1 = pool.getResource()) { -// obj1_ref = obj1_1; -// obj1_1.set("foo", "bar"); -// assertEquals("bar", obj1_1.get("foo")); -// } -// try (Jedis obj1_2 = pool.getResource()) { -// assertSame(obj1_ref, obj1_2); -// factory.setPassword("wrong password"); -// try (Jedis obj2 = pool.getResource()) { -// fail("Should not get resource from pool"); -// } catch (JedisException e) { } -// } -// } -// } -// -// @Test -// public void testResetValidPassword() { -// JedisFactory factory = new JedisFactory(null, 0, 2000, 2000, "wrong password", 0, "my_shiny_client_name") { }; -// -// try (JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels, new JedisPoolConfig(), factory)) { -// try (Jedis obj1 = pool.getResource()) { -// fail("Should not get resource from pool"); -// } catch (JedisException e) { } -// -// factory.setPassword("foobared"); -// try (Jedis obj2 = pool.getResource()) { -// obj2.set("foo", "bar"); -// assertEquals("bar", obj2.get("foo")); -// } -// } -// } } diff --git a/src/test/java/redis/clients/jedis/ShardedConnectionTest.java b/src/test/java/redis/clients/jedis/ShardedConnectionTest.java index e26acd6cdf..2318b7b3d2 100644 --- a/src/test/java/redis/clients/jedis/ShardedConnectionTest.java +++ b/src/test/java/redis/clients/jedis/ShardedConnectionTest.java @@ -43,38 +43,38 @@ public void checkConnections() { } } - @Test - public void checkPoolWhenJedisIsBroken() { - GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig<>(); - poolConfig.setMaxTotal(1); - try (JedisSharding jedis = new JedisSharding(shards, clientConfig, poolConfig)) { - jedis.sendCommand(Protocol.Command.QUIT); - jedis.incr("foo"); - } catch (JedisConnectionException jce) { - } - } - - @Test - public void checkPoolTestOnBorrowWhenJedisIsBroken() { - GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig<>(); - poolConfig.setMaxTotal(1); - poolConfig.setTestOnBorrow(true); - try (JedisSharding jedis = new JedisSharding(shards, clientConfig, poolConfig)) { - jedis.sendCommand(Protocol.Command.QUIT); - jedis.incr("foo"); - } - } - - @Test - public void checkPoolTestOnReturnWhenJedisIsBroken() { - GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig<>(); - poolConfig.setMaxTotal(1); - poolConfig.setTestOnReturn(true); - try (JedisSharding jedis = new JedisSharding(shards, clientConfig, poolConfig)) { - jedis.sendCommand(Protocol.Command.QUIT); - jedis.incr("foo"); - } - } +// @Test +// public void checkPoolWhenJedisIsBroken() { +// GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig<>(); +// poolConfig.setMaxTotal(1); +// try (JedisSharding jedis = new JedisSharding(shards, clientConfig, poolConfig)) { +// jedis.sendCommand(Protocol.Command.QUIT); +// jedis.incr("foo"); +// } catch (JedisConnectionException jce) { +// } +// } +// +// @Test +// public void checkPoolTestOnBorrowWhenJedisIsBroken() { +// GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig<>(); +// poolConfig.setMaxTotal(1); +// poolConfig.setTestOnBorrow(true); +// try (JedisSharding jedis = new JedisSharding(shards, clientConfig, poolConfig)) { +// jedis.sendCommand(Protocol.Command.QUIT); +// jedis.incr("foo"); +// } +// } +// +// @Test +// public void checkPoolTestOnReturnWhenJedisIsBroken() { +// GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig<>(); +// poolConfig.setMaxTotal(1); +// poolConfig.setTestOnReturn(true); +// try (JedisSharding jedis = new JedisSharding(shards, clientConfig, poolConfig)) { +// jedis.sendCommand(Protocol.Command.QUIT); +// jedis.incr("foo"); +// } +// } @Test public void checkFailedJedisServer() { diff --git a/src/test/java/redis/clients/jedis/UdsTest.java b/src/test/java/redis/clients/jedis/UdsTest.java index 9330c99f71..e29c65dedd 100644 --- a/src/test/java/redis/clients/jedis/UdsTest.java +++ b/src/test/java/redis/clients/jedis/UdsTest.java @@ -6,12 +6,6 @@ import org.junit.Test; import org.newsclub.net.unix.AFUNIXSocket; import org.newsclub.net.unix.AFUNIXSocketAddress; - -//import redis.clients.jedis.HostAndPort; -//import redis.clients.jedis.Jedis; -import redis.clients.jedis.UnifiedJedis; -import redis.clients.jedis.JedisSocketFactory; -import redis.clients.jedis.Protocol; import redis.clients.jedis.exceptions.JedisConnectionException; import static org.junit.Assert.assertEquals; @@ -19,9 +13,32 @@ public class UdsTest { @Test - public void testConnectsToUds() { + public void jedisConnectsToUds() { + try (Jedis jedis = new Jedis(new UdsJedisSocketFactory())) { + assertEquals("PONG", jedis.ping()); + } + } + + @Test + public void jedisConnectsToUdsResp3() { + try (Jedis jedis = new Jedis(new UdsJedisSocketFactory(), + DefaultJedisClientConfig.builder().resp3().build())) { + assertEquals("PONG", jedis.ping()); + } + } + + @Test + public void unifiedJedisConnectsToUds() { try (UnifiedJedis jedis = new UnifiedJedis(new UdsJedisSocketFactory())) { -// assertEquals("PONG", jedis.ping()); + assertEquals("PONG", jedis.ping()); + } + } + + @Test + public void unifiedJedisConnectsToUdsResp3() { + try (UnifiedJedis jedis = new UnifiedJedis(new UdsJedisSocketFactory(), + DefaultJedisClientConfig.builder().resp3().build())) { + assertEquals("PONG", jedis.ping()); } } diff --git a/src/test/java/redis/clients/jedis/benchmark/PoolBenchmark.java b/src/test/java/redis/clients/jedis/benchmark/PoolBenchmark.java index 2d6d0c561d..5b8dc5dc06 100644 --- a/src/test/java/redis/clients/jedis/benchmark/PoolBenchmark.java +++ b/src/test/java/redis/clients/jedis/benchmark/PoolBenchmark.java @@ -21,7 +21,6 @@ public static void main(String[] args) throws Exception { j.connect(); j.auth("foobared"); j.flushAll(); - j.quit(); j.disconnect(); long t = System.currentTimeMillis(); // withoutPool(); diff --git a/src/test/java/redis/clients/jedis/benchmark/PooledBenchmark.java b/src/test/java/redis/clients/jedis/benchmark/PooledBenchmark.java index 44ebe16e47..2c34beef31 100644 --- a/src/test/java/redis/clients/jedis/benchmark/PooledBenchmark.java +++ b/src/test/java/redis/clients/jedis/benchmark/PooledBenchmark.java @@ -18,7 +18,7 @@ public static void main(String[] args) throws Exception { try (Jedis j = new Jedis(hnp.getHost(), hnp.getPort())) { j.auth("foobared"); j.flushAll(); - j.quit(); + j.disconnect(); } long t = System.currentTimeMillis(); withPool(); diff --git a/src/test/java/redis/clients/jedis/commands/jedis/AccessControlListCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/AccessControlListCommandsTest.java index 384441bd3b..9d4f3c6568 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/AccessControlListCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/AccessControlListCommandsTest.java @@ -1,20 +1,20 @@ package redis.clients.jedis.commands.jedis; -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.CoreMatchers.endsWith; -import static org.hamcrest.CoreMatchers.hasItem; -import static org.hamcrest.CoreMatchers.startsWith; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.endsWith; +import static org.hamcrest.Matchers.startsWith; + import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.util.Arrays; import java.util.List; +import org.hamcrest.Matchers; import org.junit.After; import org.junit.BeforeClass; import org.junit.Test; @@ -25,6 +25,7 @@ import redis.clients.jedis.Transaction; import redis.clients.jedis.exceptions.JedisAccessControlException; import redis.clients.jedis.exceptions.JedisDataException; +import redis.clients.jedis.resps.AccessControlLogEntry; import redis.clients.jedis.resps.AccessControlUser; import redis.clients.jedis.util.RedisVersionUtil; import redis.clients.jedis.util.SafeEncoder; @@ -64,8 +65,8 @@ public void aclWhoAmI() { @Test public void aclListDefault() { - assertThat(jedis.aclList().size(), greaterThan(0)); - assertThat(jedis.aclListBinary().size(), greaterThan(0)); + assertFalse(jedis.aclList().isEmpty()); + assertFalse(jedis.aclListBinary().isEmpty()); } @Test @@ -87,7 +88,7 @@ public void addAndRemoveUser() { public void aclUsers() { List users = jedis.aclUsers(); assertEquals(2, users.size()); - assertThat(users, hasItem("default")); + assertThat(users, Matchers.hasItem("default")); assertEquals(2, jedis.aclUsersBinary().size()); // Test binary } @@ -97,15 +98,15 @@ public void aclGetUser() { // get default user information AccessControlUser userInfo = jedis.aclGetUser("default"); - assertThat(userInfo.getFlags().size(), greaterThanOrEqualTo(1)); + assertFalse(userInfo.getFlags().isEmpty()); assertEquals(1, userInfo.getPassword().size()); assertEquals("+@all", userInfo.getCommands()); - assertEquals("~*", userInfo.getKeys().get(0)); + assertEquals("~*", userInfo.getKeys()); // create new user jedis.aclSetUser(USER_NAME); userInfo = jedis.aclGetUser(USER_NAME); - assertThat(userInfo.getFlags().size(), greaterThanOrEqualTo(1)); + assertFalse(userInfo.getFlags().isEmpty()); assertEquals("off", userInfo.getFlags().get(0)); assertTrue(userInfo.getPassword().isEmpty()); assertTrue(userInfo.getKeys().isEmpty()); @@ -285,11 +286,14 @@ public void basicPermissionsTest() { jedis2.close(); jedis2.auth(USER_NAME, USER_PASSWORD); + final List nopermKeys = Arrays.asList("NOPERM No permissions to access a key", + "NOPERM this user has no permissions to access one of the keys used as arguments"); + try { jedis2.set("foo", "bar"); fail("Should throw a NOPERM exception"); } catch (JedisAccessControlException e) { - assertEquals("NOPERM No permissions to access a key", e.getMessage()); + assertThat(e.getMessage(), Matchers.isIn(nopermKeys)); } // allow user to access a subset of the key @@ -304,7 +308,7 @@ public void basicPermissionsTest() { jedis2.set("zap:3", "c"); fail("Should throw a NOPERM exception"); } catch (JedisAccessControlException e) { - assertEquals("NOPERM No permissions to access a key", e.getMessage()); + assertThat(e.getMessage(), Matchers.isIn(nopermKeys)); } } @@ -349,12 +353,13 @@ public void aclLogTest() { // test the ACL Log jedis.auth("default", "foobared"); - assertEquals("Number of log messages ", 1, jedis.aclLog().size()); - assertEquals(1, jedis.aclLog().get(0).getCount()); - assertEquals("antirez", jedis.aclLog().get(0).getUsername()); - assertEquals("toplevel", jedis.aclLog().get(0).getContext()); - assertEquals("command", jedis.aclLog().get(0).getReason()); - assertEquals("get", jedis.aclLog().get(0).getObject()); + List aclEntries = jedis.aclLog(); + assertEquals("Number of log messages ", 1, aclEntries.size()); + assertEquals(1, aclEntries.get(0).getCount()); + assertEquals("antirez", aclEntries.get(0).getUsername()); + assertEquals("toplevel", aclEntries.get(0).getContext()); + assertEquals("command", aclEntries.get(0).getReason()); + assertEquals("get", aclEntries.get(0).getObject()); // Capture similar event jedis.aclLogReset(); @@ -441,6 +446,30 @@ public void aclLogTest() { jedis.aclDelUser("antirez"); } + @Test + public void aclLogWithEntryID() { + try { + jedis.auth("wronguser", "wrongpass"); + fail("wrong user should not passed"); + } catch (JedisAccessControlException e) { + } + + List aclEntries = jedis.aclLog(); + assertEquals("Number of log messages ", 1, aclEntries.size()); + assertEquals(1, aclEntries.get(0).getCount()); + assertEquals("wronguser", aclEntries.get(0).getUsername()); + assertEquals("toplevel", aclEntries.get(0).getContext()); + assertEquals("auth", aclEntries.get(0).getReason()); + assertEquals("AUTH", aclEntries.get(0).getObject()); + assertTrue(aclEntries.get(0).getEntryId() >= 0); + assertTrue(aclEntries.get(0).getTimestampCreated() > 0); + assertEquals(aclEntries.get(0).getTimestampCreated(), aclEntries.get(0).getTimestampLastUpdated()); + + // RESET + String status = jedis.aclLogReset(); + assertEquals(status, "OK"); + } + @Test public void aclGenPass() { assertNotNull(jedis.aclGenPass()); @@ -475,7 +504,7 @@ public void aclBinaryCommandsTest() { assertThat(userInfo.getCommands(), containsString("+@all")); assertThat(userInfo.getCommands(), containsString("-@string")); assertThat(userInfo.getCommands(), containsString("+debug|digest")); - assertEquals("&testchannel:*", userInfo.getChannels().get(0)); + assertEquals("&testchannel:*", userInfo.getChannels()); jedis.aclDelUser(USER_NAME.getBytes()); diff --git a/src/test/java/redis/clients/jedis/commands/jedis/AllKindOfValuesCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/AllKindOfValuesCommandsTest.java index 5c7ef5d39c..a681d4f4d8 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/AllKindOfValuesCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/AllKindOfValuesCommandsTest.java @@ -1,6 +1,8 @@ package redis.clients.jedis.commands.jedis; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.*; + import static redis.clients.jedis.Protocol.Command.BLPOP; import static redis.clients.jedis.Protocol.Command.HGETALL; import static redis.clients.jedis.Protocol.Command.GET; @@ -11,30 +13,29 @@ import static redis.clients.jedis.Protocol.Command.XINFO; import static redis.clients.jedis.params.ScanParams.SCAN_POINTER_START; import static redis.clients.jedis.params.ScanParams.SCAN_POINTER_START_BINARY; -import static redis.clients.jedis.params.SetParams.setParams; -import static redis.clients.jedis.util.AssertUtil.assertByteArrayListEquals; -import static redis.clients.jedis.util.AssertUtil.assertCollectionContains; import java.util.*; +import org.hamcrest.Matchers; +import org.junit.Assume; import org.junit.Test; import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; +import redis.clients.jedis.Transaction; import redis.clients.jedis.args.ExpiryOption; -import redis.clients.jedis.exceptions.JedisException; -import redis.clients.jedis.params.CommandListFilterByParams; -import redis.clients.jedis.params.LolwutParams; import redis.clients.jedis.params.ScanParams; -import redis.clients.jedis.resps.CommandDocument; -import redis.clients.jedis.resps.CommandInfo; import redis.clients.jedis.resps.ScanResult; import redis.clients.jedis.StreamEntryID; import redis.clients.jedis.args.FlushMode; import redis.clients.jedis.params.RestoreParams; import redis.clients.jedis.HostAndPorts; -import redis.clients.jedis.util.KeyValue; +import redis.clients.jedis.RedisProtocol; import redis.clients.jedis.util.SafeEncoder; import redis.clients.jedis.exceptions.JedisDataException; +import redis.clients.jedis.params.SetParams; +import redis.clients.jedis.util.AssertUtil; +import redis.clients.jedis.util.KeyValue; +import redis.clients.jedis.util.RedisProtocolUtil; public class AllKindOfValuesCommandsTest extends JedisCommandsTestBase { final byte[] bfoo = { 0x01, 0x02, 0x03, 0x04 }; @@ -53,6 +54,7 @@ public class AllKindOfValuesCommandsTest extends JedisCommandsTestBase { final byte[] bnx = { 0x6E, 0x78 }; final byte[] bex = { 0x65, 0x78 }; final int expireSeconds = 2; + private static final HostAndPort lfuHnp = HostAndPorts.getRedisServers().get(7); @Test @@ -69,21 +71,6 @@ public void pingWithMessage() { assertArrayEquals(bfoobar, jedis.ping(bfoobar)); } - @Test - public void lolwut() { - String lolwut = jedis.lolwut(); - assertNotNull(lolwut); - - String lolwutVersion = jedis.lolwut(new LolwutParams().version(5)); - assertNotNull(lolwutVersion); - } - - @Test - public void latencyDoctor() { - String report = jedis.latencyDoctor(); - assertNotNull(report); - } - @Test public void exists() { String status = jedis.set("foo", "bar"); @@ -212,28 +199,20 @@ public void keys() { jedis.set("foobar", "bar"); Set keys = jedis.keys("foo*"); - Set expected = new HashSet<>(); - expected.add("foo"); - expected.add("foobar"); - assertEquals(expected, keys); - - expected = new HashSet<>(); - keys = jedis.keys("bar*"); + AssertUtil.assertCollectionContains(keys, "foo"); + AssertUtil.assertCollectionContains(keys, "foobar"); - assertEquals(expected, keys); + assertEquals(Collections.emptySet(), jedis.keys("bar*")); // Binary jedis.set(bfoo, bbar); jedis.set(bfoobar, bbar); Set bkeys = jedis.keys(bfoostar); - assertEquals(2, bkeys.size()); - assertCollectionContains(bkeys, bfoo); - assertCollectionContains(bkeys, bfoobar); - - bkeys = jedis.keys(bbarstar); + AssertUtil.assertByteArrayCollectionContains(bkeys, bfoo); + AssertUtil.assertByteArrayCollectionContains(bkeys, bfoobar); - assertEquals(0, bkeys.size()); + assertEquals(Collections.emptySet(), jedis.keys(bbarstar)); } @Test @@ -876,11 +855,11 @@ public void scanType() { assertEquals(4, page1Count + page2Count); binaryResult = jedis.scan(SCAN_POINTER_START_BINARY, noParams, hash); - assertByteArrayListEquals(Collections.singletonList(new byte[]{98}), binaryResult.getResult()); + AssertUtil.assertByteArrayListEquals(Collections.singletonList(new byte[]{98}), binaryResult.getResult()); binaryResult = jedis.scan(SCAN_POINTER_START_BINARY, noParams, set); - assertByteArrayListEquals(Collections.singletonList(new byte[]{100}), binaryResult.getResult()); + AssertUtil.assertByteArrayListEquals(Collections.singletonList(new byte[]{100}), binaryResult.getResult()); binaryResult = jedis.scan(SCAN_POINTER_START_BINARY, noParams, zset); - assertByteArrayListEquals(Collections.singletonList(new byte[]{102}), binaryResult.getResult()); + AssertUtil.assertByteArrayListEquals(Collections.singletonList(new byte[]{102}), binaryResult.getResult()); } @Test @@ -913,10 +892,10 @@ private ScanResult scanCompletely(String cursor) { @Test public void setNxExAndGet() { - assertEquals("OK", jedis.set("hello", "world", setParams().nx().ex(expireSeconds))); + assertEquals("OK", jedis.set("hello", "world", SetParams.setParams().nx().ex(expireSeconds))); assertEquals("world", jedis.get("hello")); - assertNull(jedis.set("hello", "bar", setParams().nx().ex(expireSeconds))); + assertNull(jedis.set("hello", "bar", SetParams.setParams().nx().ex(expireSeconds))); assertEquals("world", jedis.get("hello")); long ttl = jedis.ttl("hello"); @@ -926,10 +905,10 @@ public void setNxExAndGet() { byte[] bworld = { 0x77, 0x6F, 0x72, 0x6C, 0x64 }; byte[] bhello = { 0x68, 0x65, 0x6C, 0x6C, 0x6F }; - assertEquals("OK", jedis.set(bworld, bhello, setParams().nx().ex(expireSeconds))); + assertEquals("OK", jedis.set(bworld, bhello, SetParams.setParams().nx().ex(expireSeconds))); assertArrayEquals(bhello, jedis.get(bworld)); - assertNull(jedis.set(bworld, bbar, setParams().nx().ex(expireSeconds))); + assertNull(jedis.set(bworld, bbar, SetParams.setParams().nx().ex(expireSeconds))); assertArrayEquals(bhello, jedis.get(bworld)); long bttl = jedis.ttl(bworld); @@ -941,12 +920,12 @@ public void setGetOptionTest() { assertEquals("OK", jedis.set("hello", "world")); // GET old value - assertEquals("world", jedis.set("hello", "jedis", setParams().get())); + assertEquals("world", jedis.setGet("hello", "jedis")); assertEquals("jedis", jedis.get("hello")); // GET null value - assertNull(jedis.set("key", "value", setParams().get())); + assertNull(jedis.setGet("key", "value")); } @Test @@ -954,12 +933,12 @@ public void setGet() { assertEquals("OK", jedis.set("hello", "world")); // GET old value - assertEquals("world", jedis.setGet("hello", "jedis", setParams())); + assertEquals("world", jedis.setGet("hello", "jedis", SetParams.setParams())); assertEquals("jedis", jedis.get("hello")); // GET null value - assertNull(jedis.setGet("key", "value", setParams())); + assertNull(jedis.setGet("key", "value", SetParams.setParams())); } @Test @@ -999,17 +978,60 @@ public void sendBlockingCommandTest() { } @Test - public void encodeCompleteResponse() { + public void encodeCompleteResponsePing() { + assertEquals("PONG", SafeEncoder.encodeObject(jedis.sendCommand(PING))); + } + + @Test + public void encodeCompleteResponseHgetall() { + Assume.assumeFalse(RedisProtocolUtil.getRedisProtocol() == RedisProtocol.RESP3); + + HashMap entries = new HashMap<>(); + entries.put("foo", "bar"); + entries.put("foo2", "bar2"); + jedis.hset("hash:test:encode", entries); + + List encodeObj = (List) SafeEncoder.encodeObject(jedis.sendCommand(HGETALL, "hash:test:encode")); + + assertEquals(4, encodeObj.size()); + entries.forEach((k, v) -> { + assertThat((Iterable) encodeObj, Matchers.hasItem(k)); + assertEquals(v, findValueFromMapAsList(encodeObj, k)); + }); + } + + @Test + public void encodeCompleteResponseHgetallResp3() { + Assume.assumeTrue(RedisProtocolUtil.getRedisProtocol() == RedisProtocol.RESP3); + + HashMap entries = new HashMap<>(); + entries.put("foo", "bar"); + entries.put("foo2", "bar2"); + jedis.hset("hash:test:encode", entries); + + List encodeObj = (List) SafeEncoder.encodeObject(jedis.sendCommand(HGETALL, "hash:test:encode")); + + assertEquals(2, encodeObj.size()); + encodeObj.forEach(kv -> { + assertThat(entries, Matchers.hasEntry(kv.getKey(), kv.getValue())); + }); + } + + @Test + public void encodeCompleteResponseXinfoStream() { + Assume.assumeFalse(RedisProtocolUtil.getRedisProtocol() == RedisProtocol.RESP3); + HashMap entry = new HashMap<>(); entry.put("foo", "bar"); StreamEntryID entryID = jedis.xadd("mystream", StreamEntryID.NEW_ENTRY, entry); jedis.xgroupCreate("mystream", "mygroup", null, false); Object obj = jedis.sendCommand(XINFO, "STREAM", "mystream"); + List encodeObj = (List) SafeEncoder.encodeObject(obj); - assertTrue(encodeObj.size() >= 14); - assertEquals(0, encodeObj.size() % 2); // must be even + assertThat(encodeObj.size(), Matchers.greaterThanOrEqualTo(14)); + assertEquals("must have even number of elements", 0, encodeObj.size() % 2); // must be even assertEquals(1L, findValueFromMapAsList(encodeObj, "length")); assertEquals(entryID.toString(), findValueFromMapAsList(encodeObj, "last-generated-id")); @@ -1020,16 +1042,32 @@ public void encodeCompleteResponse() { assertEquals(entryAsList, ((List) findValueFromMapAsList(encodeObj, "first-entry")).get(1)); assertEquals(entryAsList, ((List) findValueFromMapAsList(encodeObj, "last-entry")).get(1)); + } - assertEquals("PONG", SafeEncoder.encodeObject(jedis.sendCommand(PING))); + @Test + public void encodeCompleteResponseXinfoStreamResp3() { + Assume.assumeTrue(RedisProtocolUtil.getRedisProtocol() == RedisProtocol.RESP3); + + HashMap entry = new HashMap<>(); + entry.put("foo", "bar"); + StreamEntryID entryID = jedis.xadd("mystream", StreamEntryID.NEW_ENTRY, entry); + jedis.xgroupCreate("mystream", "mygroup", null, false); - entry.put("foo2", "bar2"); - jedis.hset("hash:test:encode", entry); - encodeObj = (List) SafeEncoder.encodeObject(jedis.sendCommand(HGETALL, "hash:test:encode")); + Object obj = jedis.sendCommand(XINFO, "STREAM", "mystream"); - assertEquals(4, encodeObj.size()); - assertTrue(encodeObj.contains("foo")); - assertTrue(encodeObj.contains("foo2")); + List encodeObj = (List) SafeEncoder.encodeObject(obj); + + assertThat(encodeObj.size(), Matchers.greaterThanOrEqualTo(7)); + + assertEquals(1L, findValueFromMapAsKeyValueList(encodeObj, "length")); + assertEquals(entryID.toString(), findValueFromMapAsKeyValueList(encodeObj, "last-generated-id")); + + List entryAsList = new ArrayList<>(2); + entryAsList.add("foo"); + entryAsList.add("bar"); + + assertEquals(entryAsList, ((List) findValueFromMapAsKeyValueList(encodeObj, "first-entry")).get(1)); + assertEquals(entryAsList, ((List) findValueFromMapAsKeyValueList(encodeObj, "last-entry")).get(1)); } private Object findValueFromMapAsList(List list, Object key) { @@ -1041,6 +1079,15 @@ private Object findValueFromMapAsList(List list, Object key) { return null; } + private Object findValueFromMapAsKeyValueList(List list, Object key) { + for (KeyValue kv : list) { + if (key.equals(kv.getKey())) { + return kv.getValue(); + } + } + return null; + } + @Test public void copy() { assertFalse(jedis.copy("unknown", "foo", false)); @@ -1080,74 +1127,30 @@ public void copy() { } @Test - public void commandCount() { - assertTrue(jedis.commandCount() > 100); + public void reset() { + // response test + String status = jedis.reset(); + assertEquals("RESET", status); + + // auth reset + String counter = "counter"; + Exception ex1 = assertThrows(JedisDataException.class, () -> { + jedis.set(counter, "1"); + }); + assertEquals("NOAUTH Authentication required.", ex1.getMessage()); + + // multi reset + jedis.auth("foobared"); + jedis.set(counter, "1"); + + Transaction trans = jedis.multi(); + trans.incr(counter); + jedis.reset(); + + Exception ex2 = assertThrows(JedisDataException.class, trans::exec); + assertEquals("EXECABORT Transaction discarded because of: NOAUTH Authentication required.", ex2.getMessage()); + + jedis.auth("foobared"); + assertEquals("1", jedis.get(counter)); } - - @Test - public void commandDocs() { - Map docs = jedis.commandDocs("SORT", "SET"); - - CommandDocument sortDoc = docs.get("sort"); - assertEquals("generic", sortDoc.getGroup()); - assertEquals("Sort the elements in a list, set or sorted set", sortDoc.getSummary()); - assertNull(sortDoc.getHistory()); - - CommandDocument setDoc = docs.get("set"); - assertEquals("1.0.0", setDoc.getSince()); - assertEquals("O(1)", setDoc.getComplexity()); - assertEquals("2.6.12: Added the `EX`, `PX`, `NX` and `XX` options.", setDoc.getHistory().get(0)); - } - - @Test - public void commandGetKeys() { - List keys = jedis.commandGetKeys("SORT", "mylist", "ALPHA", "STORE", "outlist"); - assertEquals(2, keys.size()); - - List>> keySandFlags = jedis.commandGetKeysAndFlags("SET", "k1", "v1"); - assertEquals("k1", keySandFlags.get(0).getKey()); - assertEquals(2, keySandFlags.get(0).getValue().size()); - } - - @Test - public void commandInfo() { - Map infos = jedis.commandInfo("GET", "foo", "SET"); - - CommandInfo getInfo = infos.get("get"); - assertEquals(2, getInfo.getArity()); - assertEquals(2, getInfo.getFlags().size()); - assertEquals(1, getInfo.getFirstKey()); - assertEquals(1, getInfo.getLastKey()); - assertEquals(1, getInfo.getStep()); - - assertNull(infos.get("foo")); // non-existing command - - CommandInfo setInfo = infos.get("set"); - assertEquals(3, setInfo.getAclCategories().size()); - assertEquals(0, setInfo.getTips().size()); - assertEquals(0, setInfo.getSubcommands().size()); - } - - @Test - public void commandList() { - List commands = jedis.commandList(); - assertTrue(commands.size() > 100); - - commands = jedis.commandListFilterBy(CommandListFilterByParams.commandListFilterByParams().filterByModule("JSON")); - assertEquals(0, commands.size()); // json module was not loaded - - commands = jedis.commandListFilterBy(CommandListFilterByParams.commandListFilterByParams().filterByAclCat("admin")); - assertTrue(commands.size() > 10); - - commands = jedis.commandListFilterBy(CommandListFilterByParams.commandListFilterByParams().filterByPattern("a*")); - assertTrue(commands.size() > 10); - - try { - jedis.commandListFilterBy(CommandListFilterByParams.commandListFilterByParams()); - fail(); - } catch (JedisException e) { - assertTrue(true); - } - } - } diff --git a/src/test/java/redis/clients/jedis/commands/jedis/BinaryValuesCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/BinaryValuesCommandsTest.java index 02ed41187d..00c6def7c2 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/BinaryValuesCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/BinaryValuesCommandsTest.java @@ -110,6 +110,7 @@ public void setAndExpire() { public void setAndKeepttl() { assertEquals("OK", jedis.set(bfoo, binaryValue, setParams().nx().ex(expireSeconds))); assertEquals("OK", jedis.set(bfoo, binaryValue, setParams().keepttl())); + assertEquals("OK", jedis.set(bfoo, binaryValue, setParams().keepTtl())); long ttl = jedis.ttl(bfoo); assertTrue(0 < ttl && ttl <= expireSeconds); jedis.set(bfoo, binaryValue); @@ -328,12 +329,12 @@ public void setGet() { assertEquals("OK", jedis.set(bfoo, bbar)); // GET old value - assertArrayEquals(bbar, jedis.setGet(bfoo, binaryValue, setParams())); + assertArrayEquals(bbar, jedis.setGet(bfoo, binaryValue)); assertArrayEquals(binaryValue, jedis.get(bfoo)); // GET null value - assertNull(jedis.setGet(bbar, bfoo, setParams())); + assertNull(jedis.setGet(bbar, bfoo)); } @Test diff --git a/src/test/java/redis/clients/jedis/commands/jedis/BitCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/BitCommandsTest.java index c8f7f0e67c..ab137c7edc 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/BitCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/BitCommandsTest.java @@ -35,6 +35,7 @@ public void bitpos() { String foo = "foo"; jedis.set(foo, String.valueOf(0)); + // string "0" with bits: 0011 0000 jedis.setbit(foo, 3, true); jedis.setbit(foo, 7, true); @@ -42,7 +43,8 @@ public void bitpos() { jedis.setbit(foo, 39, true); /* - * byte: 0 1 2 3 4 bit: 00010001 / 00000100 / 00000000 / 00000000 / 00000001 + * bit: 00110001 / 00000100 / 00000000 / 00000000 / 00000001 + * byte: 0 1 2 3 4 */ long offset = jedis.bitpos(foo, true); assertEquals(2, offset); @@ -69,6 +71,7 @@ public void bitposBinary() { byte[] bfoo = { 0x01, 0x02, 0x03, 0x04 }; jedis.set(bfoo, Protocol.toByteArray(0)); + // bits: 0011 0000 jedis.setbit(bfoo, 3, true); jedis.setbit(bfoo, 7, true); @@ -76,7 +79,8 @@ public void bitposBinary() { jedis.setbit(bfoo, 39, true); /* - * byte: 0 1 2 3 4 bit: 00010001 / 00000100 / 00000000 / 00000000 / 00000001 + * bit: 00110001 / 00000100 / 00000000 / 00000000 / 00000001 + * byte: 0 1 2 3 4 */ long offset = jedis.bitpos(bfoo, true); assertEquals(2, offset); @@ -107,7 +111,8 @@ public void bitposWithNoMatchingBitExist() { } /* - * byte: 0 bit: 11111111 + * bit: 11111111 + * byte: 0 */ long offset = jedis.bitpos(foo, false); // offset should be last index + 1 @@ -124,7 +129,8 @@ public void bitposWithNoMatchingBitExistWithinRange() { } /* - * byte: 0 1 2 3 4 bit: 11111111 / 11111111 / 11111111 / 11111111 / 11111111 + * bit: 11111111 / 11111111 / 11111111 / 11111111 / 11111111 + * byte: 0 1 2 3 4 */ long offset = jedis.bitpos(foo, false, new BitPosParams(2, 3)); // offset should be -1 diff --git a/src/test/java/redis/clients/jedis/commands/jedis/ClientCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/ClientCommandsTest.java index fd10eaaa7e..8c3f35db49 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/ClientCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/ClientCommandsTest.java @@ -20,6 +20,7 @@ import org.junit.Test; import redis.clients.jedis.Jedis; +import redis.clients.jedis.args.ClientAttributeOption; import redis.clients.jedis.args.ClientType; import redis.clients.jedis.args.UnblockType; import redis.clients.jedis.exceptions.JedisConnectionException; @@ -62,6 +63,17 @@ public void nameBinary() { assertArrayEquals(name, client.clientGetnameBinary()); } + @Test + public void clientSetInfoCommand() { + String libName = "Jedis::A-Redis-Java-library"; + String libVersion = "999.999.999"; + assertEquals("OK", client.clientSetInfo(ClientAttributeOption.LIB_NAME, libName)); + assertEquals("OK", client.clientSetInfo(ClientAttributeOption.LIB_VER, libVersion)); + String info = client.clientInfo(); + assertTrue(info.contains("lib-name=" + libName)); + assertTrue(info.contains("lib-ver=" + libVersion)); + } + @Test public void clientId() { long clientId = client.clientId(); diff --git a/src/test/java/redis/clients/jedis/commands/jedis/ClusterCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/ClusterCommandsTest.java index f0bf0bd310..7e5c5db875 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/ClusterCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/ClusterCommandsTest.java @@ -3,13 +3,18 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.util.List; import java.util.Map; + +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import redis.clients.jedis.HostAndPort; @@ -17,6 +22,8 @@ import redis.clients.jedis.args.ClusterResetType; import redis.clients.jedis.HostAndPorts; import redis.clients.jedis.exceptions.JedisDataException; +import redis.clients.jedis.resps.ClusterShardInfo; +import redis.clients.jedis.resps.ClusterShardNodeInfo; import redis.clients.jedis.util.JedisClusterCRC16; import redis.clients.jedis.util.JedisClusterTestUtil; @@ -45,8 +52,17 @@ public void tearDown() { node2.disconnect(); } + @BeforeClass + public static void resetRedisBefore() { + removeSlots(); + } + @AfterClass - public static void removeSlots() throws InterruptedException { + public static void resetRedisAfter() { + removeSlots(); + } + + public static void removeSlots() { try (Jedis node = new Jedis(nodeInfo1)) { node.auth("cluster"); node.clusterReset(ClusterResetType.SOFT); @@ -186,6 +202,37 @@ public void clusterSlots() { node1.clusterDelSlots(3000, 3001, 3002); } + @Test + public void clusterShards() { + assertEquals("OK", node1.clusterAddSlots(3100, 3101, 3102, 3105)); + + List shards = node1.clusterShards(); + assertNotNull(shards); + assertTrue(shards.size() > 0); + + for (ClusterShardInfo shardInfo : shards) { + assertNotNull(shardInfo); + + assertTrue(shardInfo.getSlots().size() > 1); + for (List slotRange : shardInfo.getSlots()) { + assertEquals(2, slotRange.size()); + } + + for (ClusterShardNodeInfo nodeInfo : shardInfo.getNodes()) { + assertNotNull(nodeInfo.getId()); + assertNotNull(nodeInfo.getEndpoint()); + assertNotNull(nodeInfo.getIp()); + assertNull(nodeInfo.getHostname()); + assertNotNull(nodeInfo.getPort()); + assertNull(nodeInfo.getTlsPort()); + assertNotNull(nodeInfo.getRole()); + assertNotNull(nodeInfo.getReplicationOffset()); + assertNotNull(nodeInfo.getHealth()); + } + } + node1.clusterDelSlots(3100, 3101, 3102, 3105); + } + @Test public void clusterLinks() throws InterruptedException { List> links = node1.clusterLinks(); @@ -211,6 +258,16 @@ public void clusterCountFailureReports() { assertEquals(0, node1.clusterCountFailureReports(node1.clusterMyId())); } + @Test + public void clusterMyId() { + MatcherAssert.assertThat(node1.clusterMyId(), Matchers.not(Matchers.isEmptyOrNullString())); + } + + @Test + public void clusterMyShardId() { + MatcherAssert.assertThat(node1.clusterMyShardId(), Matchers.not(Matchers.isEmptyOrNullString())); + } + @Test public void testClusterEpoch() { try { @@ -222,7 +279,7 @@ public void testClusterEpoch() { @Test public void ClusterBumpEpoch() { - node1.clusterBumpEpoch(); + MatcherAssert.assertThat(node1.clusterBumpEpoch(), Matchers.matchesPattern("^BUMPED|STILL [0-9]+$")); } -} \ No newline at end of file +} diff --git a/src/test/java/redis/clients/jedis/commands/jedis/ClusterScriptingCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/ClusterScriptingCommandsTest.java index 4b6b6fd142..503337683e 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/ClusterScriptingCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/ClusterScriptingCommandsTest.java @@ -1,6 +1,8 @@ package redis.clients.jedis.commands.jedis; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import java.util.ArrayList; @@ -8,11 +10,11 @@ import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.function.Supplier; import org.junit.Test; -import redis.clients.jedis.JedisBroadcast; +import redis.clients.jedis.HostAndPort; import redis.clients.jedis.args.FlushMode; +import redis.clients.jedis.exceptions.JedisBroadcastException; import redis.clients.jedis.exceptions.JedisClusterOperationException; import redis.clients.jedis.exceptions.JedisDataException; @@ -98,29 +100,30 @@ public void testBinaryScriptExists() { @Test public void broadcast() { - Map> stringReplies; - String script_1 = "return 'jedis'", script_2 = "return 79", sha1_1, sha1_2; - JedisBroadcast broadcast = new JedisBroadcast(cluster); - - stringReplies = broadcast.scriptLoad(script_1); - assertEquals(3, stringReplies.size()); - sha1_1 = stringReplies.values().stream().findAny().get().get(); - stringReplies.values().forEach(reply -> assertEquals(sha1_1, reply.get())); - - stringReplies = broadcast.scriptLoad(script_2); - assertEquals(3, stringReplies.size()); - sha1_2 = stringReplies.values().stream().findAny().get().get(); - stringReplies.values().forEach(reply -> assertEquals(sha1_2, reply.get())); - - Map>> booleanListReplies; - booleanListReplies = broadcast.scriptExists(sha1_1, sha1_2); - assertEquals(3, booleanListReplies.size()); - booleanListReplies.values().forEach(reply -> assertEquals(Arrays.asList(true, true), reply.get())); - - broadcast.scriptFlush(); - - booleanListReplies = broadcast.scriptExists(sha1_1, sha1_2); - assertEquals(3, booleanListReplies.size()); - booleanListReplies.values().forEach(reply -> assertEquals(Arrays.asList(false, false), reply.get())); + + String script_1 = "return 'jedis'"; + String sha1_1 = cluster.scriptLoad(script_1); + + String script_2 = "return 79"; + String sha1_2 = cluster.scriptLoad(script_2); + + assertEquals(Arrays.asList(true, true), cluster.scriptExists(Arrays.asList(sha1_1, sha1_2))); + + cluster.scriptFlush(); + + assertEquals(Arrays.asList(false, false), cluster.scriptExists(Arrays.asList(sha1_1, sha1_2))); + } + + @Test + public void broadcastWithError() { + + JedisBroadcastException error = assertThrows(JedisBroadcastException.class, () -> cluster.functionDelete("xyz")); + + Map replies = error.getReplies(); + assertEquals(3, replies.size()); + replies.values().forEach(r -> { + assertSame(JedisDataException.class, r.getClass()); + assertEquals("ERR Library not found", ((JedisDataException) r).getMessage()); + }); } } diff --git a/src/test/java/redis/clients/jedis/commands/jedis/ClusterShardedPublishSubscribeCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/ClusterShardedPublishSubscribeCommandsTest.java new file mode 100644 index 0000000000..65d36fd5df --- /dev/null +++ b/src/test/java/redis/clients/jedis/commands/jedis/ClusterShardedPublishSubscribeCommandsTest.java @@ -0,0 +1,162 @@ +package redis.clients.jedis.commands.jedis; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasItems; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; + +import redis.clients.jedis.BinaryJedisShardedPubSub; +import redis.clients.jedis.Connection; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisShardedPubSub; +import redis.clients.jedis.util.JedisClusterCRC16; +import redis.clients.jedis.util.SafeEncoder; + +public class ClusterShardedPublishSubscribeCommandsTest extends ClusterJedisCommandsTestBase { + + private void publishOne(final String channel, final String message) { + Thread t = new Thread(() -> cluster.spublish(channel, message)); + t.start(); + } + + @Test + public void subscribe() throws InterruptedException { + cluster.ssubscribe(new JedisShardedPubSub() { + @Override public void onSMessage(String channel, String message) { + assertEquals("foo", channel); + assertEquals("exit", message); + sunsubscribe(); + } + + @Override public void onSSubscribe(String channel, int subscribedChannels) { + assertEquals("foo", channel); + assertEquals(1, subscribedChannels); + + // now that I'm subscribed... publish + publishOne("foo", "exit"); + } + + @Override public void onSUnsubscribe(String channel, int subscribedChannels) { + assertEquals("foo", channel); + assertEquals(0, subscribedChannels); + } + }, "foo"); + } + + @Test + public void subscribeMany() { + cluster.ssubscribe(new JedisShardedPubSub() { + @Override public void onSMessage(String channel, String message) { + sunsubscribe(channel); + } + + @Override public void onSSubscribe(String channel, int subscribedChannels) { + publishOne(channel, "exit"); + } + + }, "{foo}", "{foo}bar"); + } + + @Test + public void pubSubChannels() { + cluster.ssubscribe(new JedisShardedPubSub() { + private int count = 0; + + @Override public void onSSubscribe(String channel, int subscribedChannels) { + count++; + // All channels are subscribed + if (count == 3) { + try (Connection conn = cluster.getConnectionFromSlot(JedisClusterCRC16.getSlot("testchan")); + Jedis jedis = new Jedis(conn)) { + assertThat(jedis.pubsubShardChannels(), + hasItems("{testchan}1", "{testchan}2", "{testchan}3")); + } + sunsubscribe(); + } + } + }, "{testchan}1", "{testchan}2", "{testchan}3"); + } + + @Test + public void pubSubChannelsWithPattern() { + cluster.ssubscribe(new JedisShardedPubSub() { + private int count = 0; + + @Override public void onSSubscribe(String channel, int subscribedChannels) { + count++; + // All channels are subscribed + if (count == 3) { + try (Connection conn = cluster.getConnectionFromSlot(JedisClusterCRC16.getSlot("testchan")); + Jedis otherJedis = new Jedis(conn)) { + assertThat(otherJedis.pubsubShardChannels("*testchan*"), + hasItems("{testchan}1", "{testchan}2", "{testchan}3")); + } + sunsubscribe(); + } + } + }, "{testchan}1", "{testchan}2", "{testchan}3"); + } + + @Test + public void pubSubNumSub() { + final Map expectedNumSub = new HashMap<>(); + expectedNumSub.put("{testchannel}1", 1L); + expectedNumSub.put("{testchannel}2", 1L); + + cluster.ssubscribe(new JedisShardedPubSub() { + private int count = 0; + + @Override public void onSSubscribe(String channel, int subscribedChannels) { + count++; + if (count == 2) { + try (Connection conn = cluster.getConnectionFromSlot(JedisClusterCRC16.getSlot("testchannel")); + Jedis otherJedis = new Jedis(conn)) { + Map numSub = otherJedis.pubsubShardNumSub("{testchannel}1", "{testchannel}2"); + assertEquals(expectedNumSub, numSub); + } + sunsubscribe(); + } + } + }, "{testchannel}1", "{testchannel}2"); + } + + @Test + public void binarySubscribe() { + cluster.ssubscribe(new BinaryJedisShardedPubSub() { + @Override public void onSMessage(byte[] channel, byte[] message) { + assertArrayEquals(SafeEncoder.encode("foo"), channel); + assertArrayEquals(SafeEncoder.encode("exit"), message); + sunsubscribe(); + } + + @Override public void onSSubscribe(byte[] channel, int subscribedChannels) { + assertArrayEquals(SafeEncoder.encode("foo"), channel); + assertEquals(1, subscribedChannels); + publishOne(SafeEncoder.encode(channel), "exit"); + } + + @Override public void onSUnsubscribe(byte[] channel, int subscribedChannels) { + assertArrayEquals(SafeEncoder.encode("foo"), channel); + assertEquals(0, subscribedChannels); + } + }, SafeEncoder.encode("foo")); + } + + @Test + public void binarySubscribeMany() { + cluster.ssubscribe(new BinaryJedisShardedPubSub() { + @Override public void onSMessage(byte[] channel, byte[] message) { + sunsubscribe(channel); + } + + @Override public void onSSubscribe(byte[] channel, int subscribedChannels) { + publishOne(SafeEncoder.encode(channel), "exit"); + } + }, SafeEncoder.encode("{foo}"), SafeEncoder.encode("{foo}bar")); + } + +} diff --git a/src/test/java/redis/clients/jedis/commands/jedis/ClusterValuesCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/ClusterValuesCommandsTest.java index 1f7be1b8bb..7168a186d1 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/ClusterValuesCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/ClusterValuesCommandsTest.java @@ -6,9 +6,10 @@ import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.function.Supplier; +import java.util.Set; import org.junit.Test; import redis.clients.jedis.BuilderFactory; @@ -17,9 +18,11 @@ import redis.clients.jedis.GeoCoordinate; import redis.clients.jedis.JedisPubSub; import redis.clients.jedis.Protocol; +import redis.clients.jedis.ScanIteration; import redis.clients.jedis.args.GeoUnit; import redis.clients.jedis.params.GeoRadiusParam; import redis.clients.jedis.params.GeoRadiusStoreParam; +import redis.clients.jedis.resps.ScanResult; public class ClusterValuesCommandsTest extends ClusterJedisCommandsTestBase { @@ -114,26 +117,71 @@ public void onUnsubscribe(String channel, int subscribedChannels) { } @Test - public void broadcastRawPing() { - Map> replies = cluster.broadcast().broadcastCommand( + public void rawPingBroadcast() { + String reply = cluster.broadcastCommand( new CommandObject<>(new CommandArguments(Protocol.Command.PING), BuilderFactory.STRING)); - assertEquals(3, replies.size()); - replies.values().forEach(reply -> assertEquals("PONG", reply.get())); + assertEquals("PONG", reply); } @Test - public void broadcastPing() { - Map> replies = cluster.broadcast().ping(); - assertEquals(3, replies.size()); - replies.values().forEach(reply -> assertEquals("PONG", reply.get())); + public void pingBroadcast() { + assertEquals("PONG", cluster.ping()); } @Test - public void broadcastFlushAll() { + public void flushAllBroadcast() { assertNull(cluster.get("foo")); assertEquals("OK", cluster.set("foo", "bar")); assertEquals("bar", cluster.get("foo")); - cluster.broadcast().flushAll(); + cluster.flushAll(); assertNull(cluster.get("foo")); } + + @Test + public void scanIteration() { + Set allIn = new HashSet<>(26 * 26); + char[] arr = new char[2]; + for (int i = 0; i < 26; i++) { + arr[0] = (char) ('a' + i); + for (int j = 0; j < 26; j++) { + arr[1] = (char) ('a' + j); + String str = new String(arr); + cluster.incr(str); + allIn.add(str); + } + } + + Set allScan = new HashSet<>(); + ScanIteration scan = cluster.scanIteration(10, "*"); + while (!scan.isIterationCompleted()) { + ScanResult batch = scan.nextBatch(); + allScan.addAll(batch.getResult()); + } + assertEquals(allIn, allScan); + + Set allTypeScan = new HashSet<>(); + ScanIteration typeScan = cluster.scanIteration(10, "*", "string"); + while (!typeScan.isIterationCompleted()) { + ScanResult batch = typeScan.nextBatch(); + allTypeScan.addAll(batch.getResult()); + } + assertEquals(allIn, allTypeScan); + } + + @Test + public void scanIterationCollect() { + Set allIn = new HashSet<>(26 * 26); + char[] arr = new char[2]; + for (int i = 0; i < 26; i++) { + arr[0] = (char) ('a' + i); + for (int j = 0; j < 26; j++) { + arr[1] = (char) ('a' + j); + String str = new String(arr); + cluster.incr(str); + allIn.add(str); + } + } + + assertEquals(allIn, cluster.scanIteration(100, "*").collect(new HashSet<>(26 * 26))); + } } diff --git a/src/test/java/redis/clients/jedis/commands/jedis/ConnectionHandlingCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/ConnectionHandlingCommandsTest.java deleted file mode 100644 index 7e2ab209db..0000000000 --- a/src/test/java/redis/clients/jedis/commands/jedis/ConnectionHandlingCommandsTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package redis.clients.jedis.commands.jedis; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - -import redis.clients.jedis.HostAndPort; -import redis.clients.jedis.Jedis; -import redis.clients.jedis.HostAndPorts; - -public class ConnectionHandlingCommandsTest { - - private static HostAndPort hnp = HostAndPorts.getRedisServers().get(0); - - @Test - public void quit() { - Jedis jedis = new Jedis(hnp); - assertEquals("OK", jedis.quit()); - } -} diff --git a/src/test/java/redis/clients/jedis/commands/jedis/ControlCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/ControlCommandsTest.java index 1220c29266..df3fef6886 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/ControlCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/ControlCommandsTest.java @@ -1,13 +1,13 @@ package redis.clients.jedis.commands.jedis; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.lessThan; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import java.util.HashSet; @@ -21,6 +21,8 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; import org.junit.Test; import redis.clients.jedis.DefaultJedisClientConfig; @@ -30,7 +32,12 @@ import redis.clients.jedis.args.ClientPauseMode; import redis.clients.jedis.exceptions.JedisDataException; import redis.clients.jedis.HostAndPorts; +import redis.clients.jedis.params.CommandListFilterByParams; +import redis.clients.jedis.params.LolwutParams; +import redis.clients.jedis.resps.CommandDocument; +import redis.clients.jedis.resps.CommandInfo; import redis.clients.jedis.util.AssertUtil; +import redis.clients.jedis.util.KeyValue; import redis.clients.jedis.util.SafeEncoder; public class ControlCommandsTest extends JedisCommandsTestBase { @@ -154,13 +161,13 @@ public void roleSentinel() { List role = sentinel.role(); assertEquals("sentinel", role.get(0)); assertTrue(role.get(1) instanceof List); - assertTrue(((List) role.get(1)).contains("mymaster")); + AssertUtil.assertCollectionContains((List) role.get(1), "mymaster"); // binary List brole = sentinel.roleBinary(); assertArrayEquals("sentinel".getBytes(), (byte[]) brole.get(0)); assertTrue(brole.get(1) instanceof List); - AssertUtil.assertCollectionContains((List) brole.get(1), "mymaster".getBytes()); + AssertUtil.assertByteArrayCollectionContains((List) brole.get(1), "mymaster".getBytes()); } } @@ -200,21 +207,23 @@ public void onCommand(String command) { @Test public void configGet() { - List info = jedis.configGet("m*"); + Map info = jedis.configGet("m*"); assertNotNull(info); assertFalse(info.isEmpty()); - assertTrue(info.size() % 2 == 0); - List infoBinary = jedis.configGet("m*".getBytes()); +// assertTrue(info.size() % 2 == 0); + Map infoBinary = jedis.configGet("m*".getBytes()); assertNotNull(infoBinary); assertFalse(infoBinary.isEmpty()); - assertTrue(infoBinary.size() % 2 == 0); +// assertTrue(infoBinary.size() % 2 == 0); } @Test public void configSet() { - List info = jedis.configGet("maxmemory"); - assertEquals("maxmemory", info.get(0)); - String memory = info.get(1); + Map info = jedis.configGet("maxmemory"); +// assertEquals("maxmemory", info.get(0)); +// String memory = info.get(1); + String memory = info.get("maxmemory"); + assertNotNull(memory); assertEquals("OK", jedis.configSet("maxmemory", "200")); assertEquals("OK", jedis.configSet("maxmemory", memory)); } @@ -222,9 +231,11 @@ public void configSet() { @Test public void configSetBinary() { byte[] maxmemory = SafeEncoder.encode("maxmemory"); - List info = jedis.configGet(maxmemory); - assertArrayEquals(maxmemory, info.get(0)); - byte[] memory = info.get(1); + Map info = jedis.configGet(maxmemory); +// assertArrayEquals(maxmemory, info.get(0)); +// byte[] memory = info.get(1); + byte[] memory = info.get(maxmemory); + assertNotNull(memory); assertEquals("OK", jedis.configSet(maxmemory, Protocol.toByteArray(200))); assertEquals("OK", jedis.configSet(maxmemory, memory)); } @@ -232,15 +243,15 @@ public void configSetBinary() { @Test public void configGetSetMulti() { String[] params = new String[]{"hash-max-listpack-entries", "set-max-intset-entries", "zset-max-listpack-entries"}; - List info = jedis.configGet(params); - assertEquals(6, info.size()); - assertEquals("OK", jedis.configSet(info.toArray(new String[6]))); + Map info = jedis.configGet(params); + assertEquals(3, info.size()); + assertEquals("OK", jedis.configSet(info)); byte[][] bparams = new byte[][]{SafeEncoder.encode("hash-max-listpack-entries"), SafeEncoder.encode("set-max-intset-entries"), SafeEncoder.encode("zset-max-listpack-entries")}; - List binfo = jedis.configGet(bparams); - assertEquals(6, binfo.size()); - assertEquals("OK", jedis.configSet(binfo.toArray(new byte[6][]))); + Map binfo = jedis.configGet(bparams); + assertEquals(3, binfo.size()); + assertEquals("OK", jedis.configSetBinary(binfo)); } @Test @@ -248,6 +259,11 @@ public void waitReplicas() { assertEquals(1, jedis.waitReplicas(1, 100)); } + @Test + public void waitAof() { + assertEquals(KeyValue.of(0L, 0L), jedis.waitAOF(0L, 0L, 100L)); + } + @Test public void clientPause() throws InterruptedException, ExecutionException { ExecutorService executorService = Executors.newFixedThreadPool(2); @@ -333,9 +349,9 @@ public Long call() throws Exception { } }); - assertThat(latencyRead.get(), lessThan(100L)); + assertThat(latencyRead.get(), Matchers.lessThan(100L)); - assertThat(latencyWrite.get(), greaterThan(100L)); + assertThat(latencyWrite.get(), Matchers.greaterThan(100L)); } finally { executorService.shutdown(); @@ -356,6 +372,12 @@ public void clientNoEvict() { assertEquals("OK", jedis.clientNoEvictOff()); } + @Test + public void clientNoTouch() { + assertEquals("OK", jedis.clientNoTouchOn()); + assertEquals("OK", jedis.clientNoTouchOff()); + } + @Test public void memoryDoctorString() { String memoryInfo = jedis.memoryDoctor(); @@ -411,4 +433,88 @@ public void memoryStats() { Map stats = jedis.memoryStats(); assertNotNull(stats); } + + @Test + public void latencyDoctor() { + String report = jedis.latencyDoctor(); + assertNotNull(report); + } + + @Test + public void commandCount() { + assertTrue(jedis.commandCount() > 100); + } + + @Test + public void commandDocs() { + Map docs = jedis.commandDocs("SORT", "SET"); + + CommandDocument sortDoc = docs.get("sort"); + assertEquals("generic", sortDoc.getGroup()); + MatcherAssert.assertThat(sortDoc.getSummary(), Matchers.isOneOf( + "Sort the elements in a list, set or sorted set", + "Sorts the elements in a list, a set, or a sorted set, optionally storing the result.")); + assertNull(sortDoc.getHistory()); + + CommandDocument setDoc = docs.get("set"); + assertEquals("1.0.0", setDoc.getSince()); + assertEquals("O(1)", setDoc.getComplexity()); + assertEquals("2.6.12: Added the `EX`, `PX`, `NX` and `XX` options.", setDoc.getHistory().get(0)); + } + + @Test + public void commandGetKeys() { + List keys = jedis.commandGetKeys("SORT", "mylist", "ALPHA", "STORE", "outlist"); + assertEquals(2, keys.size()); + + List>> keySandFlags = jedis.commandGetKeysAndFlags("SET", "k1", "v1"); + assertEquals("k1", keySandFlags.get(0).getKey()); + assertEquals(2, keySandFlags.get(0).getValue().size()); + } + + @Test + public void commandInfo() { + Map infos = jedis.commandInfo("GET", "foo", "SET"); + + CommandInfo getInfo = infos.get("get"); + assertEquals(2, getInfo.getArity()); + assertEquals(2, getInfo.getFlags().size()); + assertEquals(1, getInfo.getFirstKey()); + assertEquals(1, getInfo.getLastKey()); + assertEquals(1, getInfo.getStep()); + + assertNull(infos.get("foo")); // non-existing command + + CommandInfo setInfo = infos.get("set"); + assertEquals(3, setInfo.getAclCategories().size()); + assertEquals(0, setInfo.getTips().size()); + assertEquals(0, setInfo.getSubcommands().size()); + } + + @Test + public void commandList() { + List commands = jedis.commandList(); + assertTrue(commands.size() > 100); + + commands = jedis.commandListFilterBy(CommandListFilterByParams.commandListFilterByParams().filterByModule("JSON")); + assertEquals(0, commands.size()); // json module was not loaded + + commands = jedis.commandListFilterBy(CommandListFilterByParams.commandListFilterByParams().filterByAclCat("admin")); + assertTrue(commands.size() > 10); + + commands = jedis.commandListFilterBy(CommandListFilterByParams.commandListFilterByParams().filterByPattern("a*")); + assertTrue(commands.size() > 10); + + assertThrows(IllegalArgumentException.class, () -> + jedis.commandListFilterBy(CommandListFilterByParams.commandListFilterByParams())); + } + + @Test + public void lolwut() { + assertNotNull(jedis.lolwut()); + + assertNotNull(jedis.lolwut(new LolwutParams().version(5))); + + assertNotNull(jedis.lolwut(new LolwutParams().version(5).optionalArguments())); + } } diff --git a/src/test/java/redis/clients/jedis/commands/jedis/FailoverCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/FailoverCommandsTest.java index 26dba74925..20ec8009cd 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/FailoverCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/FailoverCommandsTest.java @@ -68,7 +68,7 @@ public void failoverReplica() { } } - @Test(expected = IllegalStateException.class) + @Test(expected = IllegalArgumentException.class) public void failoverForceWithoutToFailFast() { try (Jedis master = new Jedis(masterAddress)) { assertEquals("OK", master.failover(FailoverParams.failoverParams() @@ -76,7 +76,7 @@ public void failoverForceWithoutToFailFast() { } } - @Test(expected = IllegalStateException.class) + @Test(expected = IllegalArgumentException.class) public void failoverForceWithoutTimeoutFailFast() { try (Jedis master = new Jedis(masterAddress)) { assertEquals("OK", master.failover(FailoverParams.failoverParams() diff --git a/src/test/java/redis/clients/jedis/commands/jedis/HashesCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/HashesCommandsTest.java index 4a0e207222..c592d65afa 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/HashesCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/HashesCommandsTest.java @@ -3,15 +3,11 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertNull; import static redis.clients.jedis.params.ScanParams.SCAN_POINTER_START; import static redis.clients.jedis.params.ScanParams.SCAN_POINTER_START_BINARY; -import static redis.clients.jedis.util.AssertUtil.assertByteArrayListEquals; -import static redis.clients.jedis.util.AssertUtil.assertByteArraySetEquals; -import static redis.clients.jedis.util.AssertUtil.assertCollectionContains; import java.util.ArrayList; import java.util.Collections; @@ -28,6 +24,7 @@ import redis.clients.jedis.Response; import redis.clients.jedis.params.ScanParams; import redis.clients.jedis.resps.ScanResult; +import redis.clients.jedis.util.AssertUtil; import redis.clients.jedis.util.JedisByteHashMap; public class HashesCommandsTest extends JedisCommandsTestBase { @@ -149,7 +146,7 @@ public void hmget() { bexpected.add(bbar); bexpected.add(null); - assertByteArrayListEquals(bexpected, bvalues); + AssertUtil.assertByteArrayListEquals(bexpected, bvalues); } @Test @@ -272,7 +269,7 @@ public void hkeys() { Set bexpected = new LinkedHashSet(); bexpected.add(bbar); bexpected.add(bcar); - assertByteArraySetEquals(bexpected, bkeys); + AssertUtil.assertByteArraySetEquals(bexpected, bkeys); } @Test @@ -284,8 +281,8 @@ public void hvals() { List vals = jedis.hvals("foo"); assertEquals(2, vals.size()); - assertTrue(vals.contains("bar")); - assertTrue(vals.contains("car")); + AssertUtil.assertCollectionContains(vals, "bar"); + AssertUtil.assertCollectionContains(vals, "car"); // Binary Map bhash = new LinkedHashMap(); @@ -296,8 +293,8 @@ public void hvals() { List bvals = jedis.hvals(bfoo); assertEquals(2, bvals.size()); - assertCollectionContains(bvals, bbar); - assertCollectionContains(bvals, bcar); + AssertUtil.assertByteArrayCollectionContains(bvals, bbar); + AssertUtil.assertByteArrayCollectionContains(bvals, bcar); } @Test @@ -445,7 +442,8 @@ public void testBinaryHstrLen() { public void hrandfield() { assertNull(jedis.hrandfield("foo")); assertEquals(Collections.emptyList(), jedis.hrandfield("foo", 1)); - assertEquals(Collections.emptyMap(), jedis.hrandfieldWithValues("foo", 1)); + assertEquals(Collections.emptyList(), jedis.hrandfieldWithValues("foo", 1)); + assertEquals(Collections.emptyList(), jedis.hrandfieldWithValues("foo", -1)); Map hash = new LinkedHashMap<>(); hash.put("bar", "bar"); @@ -457,16 +455,23 @@ public void hrandfield() { assertTrue(hash.containsKey(jedis.hrandfield("foo"))); assertEquals(2, jedis.hrandfield("foo", 2).size()); - Map actual = jedis.hrandfieldWithValues("foo", 2); - assertNotNull(actual); + List> actual = jedis.hrandfieldWithValues("foo", 2); assertEquals(2, actual.size()); - Map.Entry entry = actual.entrySet().iterator().next(); - assertEquals(hash.get(entry.getKey()), entry.getValue()); + actual.forEach(e -> assertEquals(hash.get(e.getKey()), e.getValue())); + + actual = jedis.hrandfieldWithValues("foo", 5); + assertEquals(3, actual.size()); + actual.forEach(e -> assertEquals(hash.get(e.getKey()), e.getValue())); + + actual = jedis.hrandfieldWithValues("foo", -5); + assertEquals(5, actual.size()); + actual.forEach(e -> assertEquals(hash.get(e.getKey()), e.getValue())); // binary assertNull(jedis.hrandfield(bfoo)); assertEquals(Collections.emptyList(), jedis.hrandfield(bfoo, 1)); - assertEquals(Collections.emptyMap(), jedis.hrandfieldWithValues(bfoo, 1)); + assertEquals(Collections.emptyList(), jedis.hrandfieldWithValues(bfoo, 1)); + assertEquals(Collections.emptyList(), jedis.hrandfieldWithValues(bfoo, -1)); Map bhash = new JedisByteHashMap(); bhash.put(bbar, bbar); @@ -478,10 +483,16 @@ public void hrandfield() { assertTrue(bhash.containsKey(jedis.hrandfield(bfoo))); assertEquals(2, jedis.hrandfield(bfoo, 2).size()); - Map bactual = jedis.hrandfieldWithValues(bfoo, 2); - assertNotNull(bactual); + List> bactual = jedis.hrandfieldWithValues(bfoo, 2); assertEquals(2, bactual.size()); - Map.Entry bentry = bactual.entrySet().iterator().next(); - assertArrayEquals(bhash.get(bentry.getKey()), (byte[]) bentry.getValue()); + bactual.forEach(e -> assertArrayEquals(bhash.get(e.getKey()), e.getValue())); + + bactual = jedis.hrandfieldWithValues(bfoo, 5); + assertEquals(3, bactual.size()); + bactual.forEach(e -> assertArrayEquals(bhash.get(e.getKey()), e.getValue())); + + bactual = jedis.hrandfieldWithValues(bfoo, -5); + assertEquals(5, bactual.size()); + bactual.forEach(e -> assertArrayEquals(bhash.get(e.getKey()), e.getValue())); } } diff --git a/src/test/java/redis/clients/jedis/commands/jedis/JedisCommandsTestBase.java b/src/test/java/redis/clients/jedis/commands/jedis/JedisCommandsTestBase.java index 994a058880..c69302d3c5 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/JedisCommandsTestBase.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/JedisCommandsTestBase.java @@ -7,6 +7,7 @@ import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; import redis.clients.jedis.HostAndPorts; +import redis.clients.jedis.util.RedisProtocolUtil; public abstract class JedisCommandsTestBase { @@ -20,7 +21,9 @@ public JedisCommandsTestBase() { @Before public void setUp() throws Exception { - jedis = new Jedis(hnp, DefaultJedisClientConfig.builder().timeoutMillis(500).password("foobared").build()); +// jedis = new Jedis(hnp, DefaultJedisClientConfig.builder().timeoutMillis(500).password("foobared").build()); + jedis = new Jedis(hnp, DefaultJedisClientConfig.builder() + .protocol(RedisProtocolUtil.getRedisProtocol()).timeoutMillis(500).password("foobared").build()); jedis.flushAll(); } @@ -30,6 +33,8 @@ public void tearDown() throws Exception { } protected Jedis createJedis() { - return new Jedis(hnp, DefaultJedisClientConfig.builder().password("foobared").build()); +// return new Jedis(hnp, DefaultJedisClientConfig.builder().password("foobared").build()); + return new Jedis(hnp, DefaultJedisClientConfig.builder() + .protocol(RedisProtocolUtil.getRedisProtocol()).password("foobared").build()); } } diff --git a/src/test/java/redis/clients/jedis/commands/jedis/ListCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/ListCommandsTest.java index 06d1bf63ba..6f6fa80749 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/ListCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/ListCommandsTest.java @@ -22,7 +22,6 @@ import redis.clients.jedis.args.ListDirection; import redis.clients.jedis.exceptions.JedisDataException; import redis.clients.jedis.params.LPosParams; -import redis.clients.jedis.resps.KeyedListElement; import redis.clients.jedis.util.KeyValue; public class ListCommandsTest extends JedisCommandsTestBase { @@ -445,7 +444,7 @@ public void blpop() throws InterruptedException { @Test public void blpopDouble() throws InterruptedException { - KeyedListElement result = jedis.blpop(0.1, "foo"); + KeyValue result = jedis.blpop(0.1, "foo"); assertNull(result); jedis.lpush("foo", "bar"); @@ -453,7 +452,7 @@ public void blpopDouble() throws InterruptedException { assertNotNull(result); assertEquals("foo", result.getKey()); - assertEquals("bar", result.getElement()); + assertEquals("bar", result.getValue()); // Multi keys result = jedis.blpop(0.18, "foo", "foo1"); @@ -465,16 +464,15 @@ public void blpopDouble() throws InterruptedException { assertNotNull(result); assertEquals("foo1", result.getKey()); - assertEquals("bar1", result.getElement()); + assertEquals("bar1", result.getValue()); // Binary jedis.lpush(bfoo, bbar); - List bresult = jedis.blpop(3.12, bfoo); + KeyValue bresult = jedis.blpop(3.12, bfoo); assertNotNull(bresult); - assertEquals(2, bresult.size()); - assertArrayEquals(bfoo, bresult.get(0)); - assertArrayEquals(bbar, bresult.get(1)); + assertArrayEquals(bfoo, bresult.getKey()); + assertArrayEquals(bbar, bresult.getValue()); // Binary Multi keys bresult = jedis.blpop(0.11, bfoo, bfoo1); @@ -485,9 +483,8 @@ public void blpopDouble() throws InterruptedException { bresult = jedis.blpop(1d, bfoo, bfoo1); assertNotNull(bresult); - assertEquals(2, bresult.size()); - assertArrayEquals(bfoo, bresult.get(0)); - assertArrayEquals(bbar, bresult.get(1)); + assertArrayEquals(bfoo, bresult.getKey()); + assertArrayEquals(bbar, bresult.getValue()); } @Test @@ -495,7 +492,7 @@ public void blpopDoubleWithSleep() { long startMillis, totalMillis; startMillis = System.currentTimeMillis(); - KeyedListElement result = jedis.blpop(0.04, "foo"); + KeyValue result = jedis.blpop(0.04, "foo"); totalMillis = System.currentTimeMillis() - startMillis; assertTrue("TotalMillis=" + totalMillis, totalMillis < 200); assertNull(result); @@ -517,7 +514,7 @@ public void blpopDoubleWithSleep() { assertNotNull(result); assertEquals("foo", result.getKey()); - assertEquals("bar", result.getElement()); + assertEquals("bar", result.getValue()); } @Test @@ -569,7 +566,7 @@ public void brpop() throws InterruptedException { @Test public void brpopDouble() throws InterruptedException { - KeyedListElement result = jedis.brpop(0.1, "foo"); + KeyValue result = jedis.brpop(0.1, "foo"); assertNull(result); jedis.lpush("foo", "bar"); @@ -577,7 +574,7 @@ public void brpopDouble() throws InterruptedException { assertNotNull(result); assertEquals("foo", result.getKey()); - assertEquals("bar", result.getElement()); + assertEquals("bar", result.getValue()); // Multi keys result = jedis.brpop(0.18, "foo", "foo1"); @@ -589,16 +586,15 @@ public void brpopDouble() throws InterruptedException { assertNotNull(result); assertEquals("foo1", result.getKey()); - assertEquals("bar1", result.getElement()); + assertEquals("bar1", result.getValue()); // Binary jedis.lpush(bfoo, bbar); - List bresult = jedis.brpop(3.12, bfoo); + KeyValue bresult = jedis.brpop(3.12, bfoo); assertNotNull(bresult); - assertEquals(2, bresult.size()); - assertArrayEquals(bfoo, bresult.get(0)); - assertArrayEquals(bbar, bresult.get(1)); + assertArrayEquals(bfoo, bresult.getKey()); + assertArrayEquals(bbar, bresult.getValue()); // Binary Multi keys bresult = jedis.brpop(0.11, bfoo, bfoo1); @@ -609,9 +605,8 @@ public void brpopDouble() throws InterruptedException { bresult = jedis.brpop(1d, bfoo, bfoo1); assertNotNull(bresult); - assertEquals(2, bresult.size()); - assertArrayEquals(bfoo, bresult.get(0)); - assertArrayEquals(bbar, bresult.get(1)); + assertArrayEquals(bfoo, bresult.getKey()); + assertArrayEquals(bbar, bresult.getValue()); } @Test @@ -619,7 +614,7 @@ public void brpopDoubleWithSleep() { long startMillis, totalMillis; startMillis = System.currentTimeMillis(); - KeyedListElement result = jedis.brpop(0.04, "foo"); + KeyValue result = jedis.brpop(0.04, "foo"); totalMillis = System.currentTimeMillis() - startMillis; assertTrue("TotalMillis=" + totalMillis, totalMillis < 200); assertNull(result); @@ -641,7 +636,7 @@ public void brpopDoubleWithSleep() { assertNotNull(result); assertEquals("foo", result.getKey()); - assertEquals("bar", result.getElement()); + assertEquals("bar", result.getValue()); } @Test diff --git a/src/test/java/redis/clients/jedis/commands/jedis/ModuleTest.java b/src/test/java/redis/clients/jedis/commands/jedis/ModuleTest.java index 8159f45d4a..1d4a9d981b 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/ModuleTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/ModuleTest.java @@ -3,6 +3,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import java.util.Collections; import java.util.List; import org.junit.Test; @@ -30,16 +31,20 @@ public byte[] getRaw() { @Test public void testModules() { - assertEquals("OK", jedis.moduleLoad("/tmp/testmodule.so")); + try { + assertEquals("OK", jedis.moduleLoad("/tmp/testmodule.so")); - List modules = jedis.moduleList(); + List modules = jedis.moduleList(); - assertEquals("testmodule", modules.get(0).getName()); + assertEquals("testmodule", modules.get(0).getName()); - Object output = jedis.sendCommand(ModuleCommand.SIMPLE); - assertTrue((Long) output > 0); + Object output = jedis.sendCommand(ModuleCommand.SIMPLE); + assertTrue((Long) output > 0); - assertEquals("OK", jedis.moduleUnload("testmodule")); - assertEquals(0, jedis.moduleList().size()); + } finally { + + assertEquals("OK", jedis.moduleUnload("testmodule")); + assertEquals(Collections.emptyList(), jedis.moduleList()); + } } } diff --git a/src/test/java/redis/clients/jedis/commands/jedis/ObjectCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/ObjectCommandsTest.java index a021d96045..79b30ced9c 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/ObjectCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/ObjectCommandsTest.java @@ -1,13 +1,12 @@ package redis.clients.jedis.commands.jedis; -import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import java.util.List; +import org.junit.Assert; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -18,8 +17,6 @@ import redis.clients.jedis.HostAndPorts; import redis.clients.jedis.util.SafeEncoder; -import java.util.List; - public class ObjectCommandsTest extends JedisCommandsTestBase { private final String key = "mylist"; @@ -90,11 +87,11 @@ public void objectIdletime() throws InterruptedException { public void objectHelp() { // String List helpTexts = jedis.objectHelp(); - assertNotNull(helpTexts); + Assert.assertNotNull(helpTexts); // Binary List helpBinaryTexts = jedis.objectHelpBinary(); - assertNotNull(helpBinaryTexts); + Assert.assertNotNull(helpBinaryTexts); } @Test @@ -102,20 +99,13 @@ public void objectFreq() { lfuJedis.set(key, "test1"); lfuJedis.get(key); // String - Long count = lfuJedis.objectFreq(key); - assertTrue(count > 0); - + assertThat(lfuJedis.objectFreq(key), greaterThanOrEqualTo(1L)); // Binary - count = lfuJedis.objectFreq(binaryKey); - assertTrue(count > 0); + assertThat(lfuJedis.objectFreq(binaryKey), greaterThanOrEqualTo(1L)); - assertNull(lfuJedis.objectFreq("no_such_key")); + Assert.assertNull(lfuJedis.objectFreq("no_such_key")); - try { - jedis.set(key, "test2"); - jedis.objectFreq(key); - fail("Freq is only allowed with LFU policy"); - } catch (JedisDataException e) { - } + jedis.set(key, "test2"); + Assert.assertThrows("Freq is only allowed with LFU policy", JedisDataException.class, () -> jedis.objectFreq(key)); } } diff --git a/src/test/java/redis/clients/jedis/commands/jedis/PublishSubscribeCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/PublishSubscribeCommandsTest.java index 6e4b2b22b3..7b11d323ca 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/PublishSubscribeCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/PublishSubscribeCommandsTest.java @@ -1,14 +1,14 @@ package redis.clients.jedis.commands.jedis; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasItems; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.IOException; import java.net.UnknownHostException; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -21,7 +21,7 @@ import redis.clients.jedis.BinaryJedisPubSub; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPubSub; -import redis.clients.jedis.exceptions.JedisConnectionException; +import redis.clients.jedis.exceptions.JedisException; import redis.clients.jedis.util.SafeEncoder; public class PublishSubscribeCommandsTest extends JedisCommandsTestBase { @@ -65,8 +65,6 @@ public void onUnsubscribe(String channel, int subscribedChannels) { @Test public void pubSubChannels() { - final List expectedActiveChannels = Arrays - .asList("testchan1", "testchan2", "testchan3"); jedis.subscribe(new JedisPubSub() { private int count = 0; @@ -78,9 +76,9 @@ public void onSubscribe(String channel, int subscribedChannels) { Jedis otherJedis = createJedis(); List activeChannels = otherJedis.pubsubChannels(); // Since we are utilizing sentinel for the tests, there is an additional - // '__sentinel__:hello' channel that has subscribers and will be returned from PUBSUB - // CHANNELS. - assertTrue(activeChannels.containsAll(expectedActiveChannels)); + // '__sentinel__:hello' channel that has subscribers and will be returned + // from PUBSUB CHANNELS. + assertThat(activeChannels, hasItems("testchan1", "testchan2", "testchan3")); unsubscribe(); } } @@ -89,8 +87,6 @@ public void onSubscribe(String channel, int subscribedChannels) { @Test public void pubSubChannelsWithPattern() { - final List expectedActiveChannels = Arrays - .asList("testchan1", "testchan2", "testchan3"); jedis.subscribe(new JedisPubSub() { private int count = 0; @@ -101,7 +97,7 @@ public void onSubscribe(String channel, int subscribedChannels) { if (count == 3) { Jedis otherJedis = createJedis(); List activeChannels = otherJedis.pubsubChannels("test*"); - assertTrue(expectedActiveChannels.containsAll(activeChannels)); + assertThat(activeChannels, hasItems("testchan1", "testchan2", "testchan3")); unsubscribe(); } } @@ -296,19 +292,19 @@ public void onPMessage(String pattern, String channel, String message) { public void binarySubscribe() throws UnknownHostException, IOException, InterruptedException { jedis.subscribe(new BinaryJedisPubSub() { public void onMessage(byte[] channel, byte[] message) { - assertTrue(Arrays.equals(SafeEncoder.encode("foo"), channel)); - assertTrue(Arrays.equals(SafeEncoder.encode("exit"), message)); + assertArrayEquals(SafeEncoder.encode("foo"), channel); + assertArrayEquals(SafeEncoder.encode("exit"), message); unsubscribe(); } public void onSubscribe(byte[] channel, int subscribedChannels) { - assertTrue(Arrays.equals(SafeEncoder.encode("foo"), channel)); + assertArrayEquals(SafeEncoder.encode("foo"), channel); assertEquals(1, subscribedChannels); publishOne(SafeEncoder.encode(channel), "exit"); } public void onUnsubscribe(byte[] channel, int subscribedChannels) { - assertTrue(Arrays.equals(SafeEncoder.encode("foo"), channel)); + assertArrayEquals(SafeEncoder.encode("foo"), channel); assertEquals(0, subscribedChannels); } }, SafeEncoder.encode("foo")); @@ -331,20 +327,20 @@ public void onSubscribe(byte[] channel, int subscribedChannels) { public void binaryPsubscribe() throws UnknownHostException, IOException, InterruptedException { jedis.psubscribe(new BinaryJedisPubSub() { public void onPSubscribe(byte[] pattern, int subscribedChannels) { - assertTrue(Arrays.equals(SafeEncoder.encode("foo.*"), pattern)); + assertArrayEquals(SafeEncoder.encode("foo.*"), pattern); assertEquals(1, subscribedChannels); publishOne(SafeEncoder.encode(pattern).replace("*", "bar"), "exit"); } public void onPUnsubscribe(byte[] pattern, int subscribedChannels) { - assertTrue(Arrays.equals(SafeEncoder.encode("foo.*"), pattern)); + assertArrayEquals(SafeEncoder.encode("foo.*"), pattern); assertEquals(0, subscribedChannels); } public void onPMessage(byte[] pattern, byte[] channel, byte[] message) { - assertTrue(Arrays.equals(SafeEncoder.encode("foo.*"), pattern)); - assertTrue(Arrays.equals(SafeEncoder.encode("foo.bar"), channel)); - assertTrue(Arrays.equals(SafeEncoder.encode("exit"), message)); + assertArrayEquals(SafeEncoder.encode("foo.*"), pattern); + assertArrayEquals(SafeEncoder.encode("foo.bar"), channel); + assertArrayEquals(SafeEncoder.encode("exit"), message); punsubscribe(); } }, SafeEncoder.encode("foo.*")); @@ -461,14 +457,14 @@ public void onPMessage(byte[] pattern, byte[] channel, byte[] message) { jedis.subscribe(pubsub, SafeEncoder.encode("foo")); } - @Test(expected = JedisConnectionException.class) + @Test(expected = JedisException.class) public void unsubscribeWhenNotSusbscribed() throws InterruptedException { JedisPubSub pubsub = new JedisPubSub() { }; pubsub.unsubscribe(); } - @Test(expected = JedisConnectionException.class) + @Test(expected = JedisException.class) public void handleClientOutputBufferLimitForSubscribeTooSlow() throws InterruptedException { final Jedis j = createJedis(); final AtomicBoolean exit = new AtomicBoolean(false); diff --git a/src/test/java/redis/clients/jedis/commands/jedis/ScriptingCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/ScriptingCommandsTest.java index e1c2692c01..1e258dbad3 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/ScriptingCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/ScriptingCommandsTest.java @@ -1,6 +1,5 @@ package redis.clients.jedis.commands.jedis; -import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.*; import java.util.ArrayList; @@ -9,12 +8,13 @@ import java.util.List; import java.util.Map; -import org.hamcrest.CoreMatchers; -import org.hamcrest.Matcher; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import redis.clients.jedis.Jedis; +import redis.clients.jedis.RedisProtocol; import redis.clients.jedis.args.FlushMode; import redis.clients.jedis.args.FunctionRestorePolicy; import redis.clients.jedis.exceptions.JedisConnectionException; @@ -23,6 +23,8 @@ import redis.clients.jedis.resps.FunctionStats; import redis.clients.jedis.resps.LibraryInfo; import redis.clients.jedis.util.ClientKillerUtil; +import redis.clients.jedis.util.KeyValue; +import redis.clients.jedis.util.RedisProtocolUtil; import redis.clients.jedis.util.SafeEncoder; public class ScriptingCommandsTest extends JedisCommandsTestBase { @@ -119,8 +121,8 @@ public void evalNestedLists() { String script = "return { {KEYS[1]} , {2} }"; List results = (List) jedis.eval(script, 1, "key1"); - assertThat((List) results.get(0), listWithItem("key1")); - assertThat((List) results.get(1), listWithItem(2L)); + MatcherAssert.assertThat((List) results.get(0), Matchers.hasItem("key1")); + MatcherAssert.assertThat((List) results.get(1), Matchers.hasItem(2L)); } @Test @@ -388,19 +390,37 @@ public void functionList() { assertEquals(functionCode, response.getLibraryCode()); // Binary - List bresponse = (List) jedis.functionListBinary().get(0); - assertArrayEquals(library.getBytes(), (byte[]) bresponse.get(1)); + if (RedisProtocolUtil.getRedisProtocol() != RedisProtocol.RESP3) { - bresponse = (List) jedis.functionListWithCodeBinary().get(0); - assertArrayEquals(library.getBytes(), (byte[]) bresponse.get(1)); - assertNotNull(bresponse.get(7)); + List bresponse = (List) jedis.functionListBinary().get(0); + assertArrayEquals(library.getBytes(), (byte[]) bresponse.get(1)); - bresponse = (List) jedis.functionList(library.getBytes()).get(0); - assertArrayEquals(library.getBytes(), (byte[]) bresponse.get(1)); + bresponse = (List) jedis.functionListWithCodeBinary().get(0); + assertArrayEquals(library.getBytes(), (byte[]) bresponse.get(1)); + assertNotNull(bresponse.get(7)); - bresponse = (List) jedis.functionListWithCode(library.getBytes()).get(0); - assertArrayEquals(library.getBytes(), (byte[]) bresponse.get(1)); - assertNotNull(bresponse.get(7)); + bresponse = (List) jedis.functionList(library.getBytes()).get(0); + assertArrayEquals(library.getBytes(), (byte[]) bresponse.get(1)); + + bresponse = (List) jedis.functionListWithCode(library.getBytes()).get(0); + assertArrayEquals(library.getBytes(), (byte[]) bresponse.get(1)); + assertNotNull(bresponse.get(7)); + } else { + + List bresponse = (List) jedis.functionListBinary().get(0); + assertArrayEquals(library.getBytes(), (byte[]) bresponse.get(0).getValue()); + + bresponse = (List) jedis.functionListWithCodeBinary().get(0); + assertArrayEquals(library.getBytes(), (byte[]) bresponse.get(0).getValue()); + assertNotNull(bresponse.get(3)); + + bresponse = (List) jedis.functionList(library.getBytes()).get(0); + assertArrayEquals(library.getBytes(), (byte[]) bresponse.get(0).getValue()); + + bresponse = (List) jedis.functionListWithCode(library.getBytes()).get(0); + assertArrayEquals(library.getBytes(), (byte[]) bresponse.get(0).getValue()); + assertNotNull(bresponse.get(3)); + } } @Test @@ -506,8 +526,4 @@ public void fcallReadonly() { // Binary assertEquals(Long.valueOf(1), jedis.fcallReadonly("noop".getBytes(), Collections.emptyList(), Collections.emptyList())); } - - private Matcher> listWithItem(T expected) { - return CoreMatchers. hasItem(equalTo(expected)); - } } diff --git a/src/test/java/redis/clients/jedis/commands/jedis/SentinelCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/SentinelCommandsTest.java index 1a5443c64e..babaf28a10 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/SentinelCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/SentinelCommandsTest.java @@ -1,9 +1,16 @@ package redis.clients.jedis.commands.jedis; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import org.hamcrest.Matchers; import org.junit.Test; import redis.clients.jedis.HostAndPort; @@ -12,47 +19,63 @@ public class SentinelCommandsTest { - protected static HostAndPort master2 = HostAndPorts.getRedisServers().get(2); - protected static HostAndPort replica2 = HostAndPorts.getRedisServers().get(3); + protected static final String MASTER_NAME = "mymaster"; + + protected static final List nodes = + Arrays.asList(HostAndPorts.getRedisServers().get(2), HostAndPorts.getRedisServers().get(3)); + protected static final Set nodesPorts = nodes.stream() + .map(HostAndPort::getPort).map(String::valueOf).collect(Collectors.toSet()); - protected static HostAndPort sentinel2_1 = HostAndPorts.getSentinelServers().get(1); - protected static HostAndPort sentinel2_2 = HostAndPorts.getSentinelServers().get(3); + protected static final List sentinels2 = + Arrays.asList(HostAndPorts.getSentinelServers().get(1), HostAndPorts.getSentinelServers().get(3)); @Test - public void myIdSentinels() { - String id1; - try (Jedis sentinel = new Jedis(sentinel2_1)) { - id1 = sentinel.sentinelMyId(); - assertTrue(id1.matches("[0-9a-f]+")); - } + public void myIdAndSentinels() { + Map idToPort = new HashMap<>(); + sentinels2.forEach((hap) -> { + try (Jedis sentinel = new Jedis(hap)) { + String id = sentinel.sentinelMyId(); + assertThat(id, Matchers.not(Matchers.emptyOrNullString())); + idToPort.put(id, hap.getPort()); + } + }); + assertEquals(2, idToPort.size()); - try (Jedis sentinel2 = new Jedis(sentinel2_2)) { - Map details1 = sentinel2.sentinelSentinels("mymaster").get(0); - assertEquals(id1, details1.get("runid")); + try (Jedis sentinel = new Jedis(sentinels2.stream().findAny().get())) { + List> detailsList = sentinel.sentinelSentinels(MASTER_NAME); + assertThat(detailsList, Matchers.not(Matchers.empty())); + detailsList.forEach((details) + -> assertEquals(idToPort.get(details.get("runid")), + Integer.valueOf(details.get("port")))); } } @Test - public void masterMasters() { - String runId; - try (Jedis sentinel = new Jedis(sentinel2_1)) { - Map details = sentinel.sentinelMaster("mymaster"); - assertEquals("mymaster", details.get("name")); + public void masterAndMasters() { + String runId, port; + try (Jedis sentinel = new Jedis(sentinels2.get(0))) { + Map details = sentinel.sentinelMaster(MASTER_NAME); + assertEquals(MASTER_NAME, details.get("name")); runId = details.get("runid"); + port = details.get("port"); + assertThat(port, Matchers.in(nodesPorts)); } - try (Jedis sentinel2 = new Jedis(sentinel2_2)) { + try (Jedis sentinel2 = new Jedis(sentinels2.get(1))) { Map details = sentinel2.sentinelMasters().get(0); - assertEquals("mymaster", details.get("name")); + assertEquals(MASTER_NAME, details.get("name")); assertEquals(runId, details.get("runid")); + assertEquals(port, details.get("port")); } } @Test public void replicas() { - try (Jedis sentinel = new Jedis(sentinel2_1)) { - Map details = sentinel.sentinelReplicas("mymaster").get(0); - assertEquals(Integer.toString(replica2.getPort()), details.get("port")); + try (Jedis sentinel = new Jedis(sentinels2.stream().findAny().get())) { + List> detailsList = sentinel.sentinelReplicas(MASTER_NAME); + assertThat(detailsList, Matchers.not(Matchers.empty())); + detailsList.forEach((details) + -> assertThat(details.get("port"), Matchers.in(nodesPorts))); } } } diff --git a/src/test/java/redis/clients/jedis/commands/jedis/SlowlogCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/SlowlogCommandsTest.java index d9b3ba70ba..66806b933a 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/SlowlogCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/SlowlogCommandsTest.java @@ -1,12 +1,13 @@ package redis.clients.jedis.commands.jedis; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; import java.util.Arrays; import java.util.List; +import org.hamcrest.Matchers; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -28,7 +29,7 @@ public class SlowlogCommandsTest extends JedisCommandsTestBase { @Override public void setUp() throws Exception { super.setUp(); - slowlogTimeValue = jedis.configGet(SLOWLOG_TIME_PARAM).get(1); + slowlogTimeValue = jedis.configGet(SLOWLOG_TIME_PARAM).get(SLOWLOG_TIME_PARAM); } @After @@ -41,6 +42,8 @@ public void tearDown() throws Exception { @Test public void slowlog() { jedis.configSet(SLOWLOG_TIME_PARAM, ZERO_STRING); + jedis.slowlogReset(); + jedis.set("foo", "bar"); jedis.set("foo2", "bar2"); @@ -48,9 +51,9 @@ public void slowlog() { assertEquals(1, reducedLog.size()); Slowlog log = reducedLog.get(0); - assertTrue(log.getId() > 0); - assertTrue(log.getTimeStamp() > 0); - assertTrue(log.getExecutionTime() >= 0); + assertThat(log.getId(), Matchers.greaterThan(0L)); + assertThat(log.getTimeStamp(), Matchers.greaterThan(0L)); + assertThat(log.getExecutionTime(), Matchers.greaterThanOrEqualTo(0L)); assertNotNull(log.getArgs()); List breducedLog = jedis.slowlogGetBinary(1); @@ -63,8 +66,9 @@ public void slowlog() { assertNotNull(blog1); // assertEquals(7, jedis.slowlogLen()); - assertTrue(jedis.slowlogLen() > 5 && jedis.slowlogLen() < 12); - assertTrue(jedis.slowlogGet().toString().contains("SLOWLOG")); + assertThat(jedis.slowlogLen(), + Matchers.allOf(Matchers.greaterThanOrEqualTo(6L), Matchers.lessThanOrEqualTo(13L))); + assertThat(jedis.slowlogGet().toString(), Matchers.containsString("SLOWLOG")); } @Test @@ -74,36 +78,37 @@ public void slowlogObjectDetails() { jedis.slowlogReset(); jedis.configSet(SLOWLOG_TIME_PARAM, ZERO_STRING); - List logs = jedis.slowlogGet(); // Get only 'CONFIG SET' - assertEquals(1, logs.size()); + List logs = jedis.slowlogGet(); // Get only 'CONFIG SET', or including 'SLOWLOG RESET' + //assertEquals(1, logs.size()); + assertThat(logs.size(), Matchers.allOf(Matchers.greaterThanOrEqualTo(1), Matchers.lessThanOrEqualTo(2))); Slowlog log = logs.get(0); - assertTrue(log.getId() > 0); - assertTrue(log.getTimeStamp() > 0); - assertTrue(log.getExecutionTime() > 0); + assertThat(log.getId(), Matchers.greaterThan(0L)); + assertThat(log.getTimeStamp(), Matchers.greaterThan(0L)); + assertThat(log.getExecutionTime(), Matchers.greaterThan(0L)); assertEquals(4, log.getArgs().size()); assertEquals(SafeEncoder.encode(Protocol.Command.CONFIG.getRaw()), log.getArgs().get(0)); assertEquals(SafeEncoder.encode(Protocol.Keyword.SET.getRaw()), log.getArgs().get(1)); assertEquals(SLOWLOG_TIME_PARAM, log.getArgs().get(2)); assertEquals(ZERO_STRING, log.getArgs().get(3)); -// assertEquals("127.0.0.1", log.getClientIpPort().getHost()); - assertTrue(LOCAL_IPS.contains(log.getClientIpPort().getHost())); - assertTrue(log.getClientIpPort().getPort() > 0); + assertThat(log.getClientIpPort().getHost(), Matchers.in(LOCAL_IPS)); + assertThat(log.getClientIpPort().getPort(), Matchers.greaterThan(0)); assertEquals(clientName, log.getClientName()); } @Test - public void slowlogBinaryDetails() { + public void slowlogBinaryObjectDetails() { final byte[] clientName = SafeEncoder.encode("slowlog-binary-client"); jedis.clientSetname(clientName); jedis.slowlogReset(); jedis.configSet(SafeEncoder.encode(SLOWLOG_TIME_PARAM), SafeEncoder.encode(ZERO_STRING)); - List logs = jedis.slowlogGetBinary(); // Get only 'CONFIG SET' - assertEquals(1, logs.size()); + List logs = jedis.slowlogGetBinary(); // Get only 'CONFIG SET', or including 'SLOWLOG RESET' + //assertEquals(1, logs.size()); + assertThat(logs.size(), Matchers.allOf(Matchers.greaterThanOrEqualTo(1), Matchers.lessThanOrEqualTo(2))); List log = (List) logs.get(0); - assertTrue((Long) log.get(0) > 0); - assertTrue((Long) log.get(1) > 0); - assertTrue((Long) log.get(2) > 0); + assertThat((Long) log.get(0), Matchers.greaterThan(0L)); + assertThat((Long) log.get(1), Matchers.greaterThan(0L)); + assertThat((Long) log.get(2), Matchers.greaterThan(0L)); List args = (List) log.get(3); assertEquals(4, args.size()); assertArrayEquals(Protocol.Command.CONFIG.getRaw(), (byte[]) args.get(0)); @@ -111,7 +116,7 @@ public void slowlogBinaryDetails() { assertArrayEquals(SafeEncoder.encode(SLOWLOG_TIME_PARAM), (byte[]) args.get(2)); assertArrayEquals(Protocol.toByteArray(0), (byte[]) args.get(3)); // assertTrue(SafeEncoder.encode((byte[]) log.get(4)).startsWith("127.0.0.1:")); - assertTrue(((byte[]) log.get(4)).length > 0); + assertThat(((byte[]) log.get(4)).length, Matchers.greaterThanOrEqualTo(10)); // 'IP:PORT' assertArrayEquals(clientName, (byte[]) log.get(5)); } } diff --git a/src/test/java/redis/clients/jedis/commands/jedis/SortedSetCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/SortedSetCommandsTest.java index 9ab789fd29..8b5711cb70 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/SortedSetCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/SortedSetCommandsTest.java @@ -1,30 +1,19 @@ package redis.clients.jedis.commands.jedis; +import static java.util.Collections.singletonList; import static org.junit.Assert.*; import static redis.clients.jedis.params.ScanParams.SCAN_POINTER_START; import static redis.clients.jedis.params.ScanParams.SCAN_POINTER_START_BINARY; import static redis.clients.jedis.util.AssertUtil.assertByteArrayListEquals; -import static redis.clients.jedis.util.AssertUtil.assertByteArraySetEquals; -import static redis.clients.jedis.util.AssertUtil.assertCollectionContains; - -import java.util.Arrays; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import org.junit.Test; -import redis.clients.jedis.BuilderFactory; import redis.clients.jedis.args.SortedSetOption; import redis.clients.jedis.params.*; -import redis.clients.jedis.resps.KeyedZSetElement; import redis.clients.jedis.resps.ScanResult; import redis.clients.jedis.resps.Tuple; +import redis.clients.jedis.util.AssertUtil; import redis.clients.jedis.util.KeyValue; import redis.clients.jedis.util.SafeEncoder; @@ -402,6 +391,36 @@ public void zrank() { assertNull(jedis.zrank(bcar, bb)); } + @Test + public void zrankWithScore() { + jedis.zadd("foo", 1d, "a"); + jedis.zadd("foo", 2d, "b"); + + KeyValue keyValue = jedis.zrankWithScore("foo", "a"); + assertEquals(Long.valueOf(0), keyValue.getKey()); + assertEquals(Double.valueOf(1d), keyValue.getValue()); + + keyValue = jedis.zrankWithScore("foo", "b"); + assertEquals(Long.valueOf(1), keyValue.getKey()); + assertEquals(Double.valueOf(2d), keyValue.getValue()); + + assertNull(jedis.zrankWithScore("car", "b")); + + // Binary + jedis.zadd(bfoo, 1d, ba); + jedis.zadd(bfoo, 2d, bb); + + keyValue = jedis.zrankWithScore(bfoo, ba); + assertEquals(Long.valueOf(0), keyValue.getKey()); + assertEquals(Double.valueOf(1d), keyValue.getValue()); + + keyValue = jedis.zrankWithScore(bfoo, bb); + assertEquals(Long.valueOf(1), keyValue.getKey()); + assertEquals(Double.valueOf(2d), keyValue.getValue()); + + assertNull(jedis.zrankWithScore(bcar, bb)); + } + @Test public void zrevrank() { jedis.zadd("foo", 1d, "a"); @@ -1204,14 +1223,15 @@ public void zunion() { ZParams params = new ZParams(); params.weights(2, 2.5); params.aggregate(ZParams.Aggregate.SUM); - Set expected = new LinkedHashSet<>(); + + List expected = new ArrayList<>(); expected.add("a"); expected.add("b"); assertEquals(expected, jedis.zunion(params, "foo", "bar")); - Set expectedTuple = new LinkedHashSet<>(); - expectedTuple.add(new Tuple("b", new Double(9))); + List expectedTuple = new ArrayList<>(); expectedTuple.add(new Tuple("a", new Double(7))); + expectedTuple.add(new Tuple("b", new Double(9))); assertEquals(expectedTuple, jedis.zunionWithScores(params, "foo", "bar")); // Binary @@ -1220,18 +1240,15 @@ public void zunion() { jedis.zadd(bbar, 2, ba); jedis.zadd(bbar, 2, bb); - ZParams bparams = new ZParams(); - bparams.weights(2, 2.5); - bparams.aggregate(ZParams.Aggregate.SUM); - Set bexpected = new LinkedHashSet<>(); - bexpected.add(bb); + List bexpected = new ArrayList<>(); bexpected.add(ba); - assertByteArraySetEquals(bexpected, jedis.zunion(params, bfoo, bbar)); + bexpected.add(bb); + AssertUtil.assertByteArrayListEquals(bexpected, jedis.zunion(params, bfoo, bbar)); - Set bexpectedTuple = new LinkedHashSet<>(); - bexpectedTuple.add(new Tuple(bb, new Double(9))); + List bexpectedTuple = new ArrayList<>(); bexpectedTuple.add(new Tuple(ba, new Double(7))); - assertEquals(bexpectedTuple, jedis.zunionWithScores(bparams, bfoo, bbar)); + bexpectedTuple.add(new Tuple(bb, new Double(9))); + assertEquals(bexpectedTuple, jedis.zunionWithScores(params, bfoo, bbar)); } @Test @@ -1311,9 +1328,9 @@ public void zinter() { ZParams params = new ZParams(); params.weights(2, 2.5); params.aggregate(ZParams.Aggregate.SUM); - assertEquals(Collections.singleton("a"), jedis.zinter(params, "foo", "bar")); + assertEquals(singletonList("a"), jedis.zinter(params, "foo", "bar")); - assertEquals(Collections.singleton(new Tuple("a", new Double(7))), + assertEquals(singletonList(new Tuple("a", new Double(7))), jedis.zinterWithScores(params, "foo", "bar")); // Binary @@ -1324,9 +1341,9 @@ public void zinter() { ZParams bparams = new ZParams(); bparams.weights(2, 2.5); bparams.aggregate(ZParams.Aggregate.SUM); - assertByteArraySetEquals(Collections.singleton(ba), jedis.zinter(params, bfoo, bbar)); + AssertUtil.assertByteArrayListEquals(singletonList(ba), jedis.zinter(params, bfoo, bbar)); - assertEquals(Collections.singleton(new Tuple(ba, new Double(7))), + assertEquals(singletonList(new Tuple(ba, new Double(7))), jedis.zinterWithScores(bparams, bfoo, bbar)); } @@ -1505,17 +1522,15 @@ public void bzpopmax() { jedis.zadd("foo", 1d, "a", ZAddParams.zAddParams().nx()); jedis.zadd("foo", 10d, "b", ZAddParams.zAddParams().nx()); jedis.zadd("bar", 0.1d, "c", ZAddParams.zAddParams().nx()); - assertEquals(new KeyedZSetElement("foo", "b", 10d), jedis.bzpopmax(0, "foo", "bar")); + assertEquals(new KeyValue<>("foo", new Tuple("b", 10d)), jedis.bzpopmax(0, "foo", "bar")); // Binary jedis.zadd(bfoo, 1d, ba); jedis.zadd(bfoo, 10d, bb); jedis.zadd(bbar, 0.1d, bc); - List actual = jedis.bzpopmax(0, bfoo, bbar); - assertEquals(3, actual.size()); - assertArrayEquals(bfoo, actual.get(0)); - assertArrayEquals(bb, actual.get(1)); - assertEquals(10d, BuilderFactory.DOUBLE.build(actual.get(2)), 1e-10); + KeyValue actual = jedis.bzpopmax(0, bfoo, bbar); + assertArrayEquals(bfoo, actual.getKey()); + assertEquals(new Tuple(bb, 10d), actual.getValue()); } @Test @@ -1523,17 +1538,15 @@ public void bzpopmin() { jedis.zadd("foo", 1d, "a", ZAddParams.zAddParams().nx()); jedis.zadd("foo", 10d, "b", ZAddParams.zAddParams().nx()); jedis.zadd("bar", 0.1d, "c", ZAddParams.zAddParams().nx()); - assertEquals(new KeyedZSetElement("bar", "c", 0.1d), jedis.bzpopmin(0, "bar", "foo")); + assertEquals(new KeyValue<>("bar", new Tuple("c", 0.1)), jedis.bzpopmin(0, "bar", "foo")); // Binary jedis.zadd(bfoo, 1d, ba); jedis.zadd(bfoo, 10d, bb); jedis.zadd(bbar, 0.1d, bc); - List actual = jedis.bzpopmin(0, bbar, bfoo); - assertEquals(3, actual.size()); - assertArrayEquals(bbar, actual.get(0)); - assertArrayEquals(bc, actual.get(1)); - assertEquals(0.1d, BuilderFactory.DOUBLE.build(actual.get(2)), 1e-10); + KeyValue actual = jedis.bzpopmin(0, bbar, bfoo); + assertArrayEquals(bbar, (byte[]) actual.getKey()); + assertEquals(new Tuple(bc, 0.1), actual.getValue()); } @Test @@ -1543,8 +1556,8 @@ public void zdiff() { jedis.zadd("bar", 1.0, "a"); assertEquals(0, jedis.zdiff("bar1", "bar2").size()); - assertEquals(Collections.singleton("b"), jedis.zdiff("foo", "bar")); - assertEquals(Collections.singleton(new Tuple("b", 2.0d)), jedis.zdiffWithScores("foo", "bar")); + assertEquals(singletonList("b"), jedis.zdiff("foo", "bar")); + assertEquals(singletonList(new Tuple("b", 2.0d)), jedis.zdiffWithScores("foo", "bar")); // binary @@ -1553,21 +1566,21 @@ public void zdiff() { jedis.zadd(bbar, 1.0, ba); assertEquals(0, jedis.zdiff(bbar1, bbar2).size()); - Set bactual = jedis.zdiff(bfoo, bbar); + List bactual = jedis.zdiff(bfoo, bbar); assertEquals(1, bactual.size()); assertArrayEquals(bb, bactual.iterator().next()); - assertEquals(Collections.singleton(new Tuple(bb, 2.0d)), jedis.zdiffWithScores(bfoo, bbar)); + assertEquals(singletonList(new Tuple(bb, 2.0d)), jedis.zdiffWithScores(bfoo, bbar)); } @Test - public void zdiffStore() { + public void zdiffstore() { jedis.zadd("foo", 1.0, "a"); jedis.zadd("foo", 2.0, "b"); jedis.zadd("bar", 1.0, "a"); - assertEquals(0, jedis.zdiffStore("bar3", "bar1", "bar2")); - assertEquals(1, jedis.zdiffStore("bar3", "foo", "bar")); - assertEquals(Collections.singletonList("b"), jedis.zrange("bar3", 0, -1)); + assertEquals(0, jedis.zdiffstore("bar3", "bar1", "bar2")); + assertEquals(1, jedis.zdiffstore("bar3", "foo", "bar")); + assertEquals(singletonList("b"), jedis.zrange("bar3", 0, -1)); // binary @@ -1575,8 +1588,8 @@ public void zdiffStore() { jedis.zadd(bfoo, 2.0, bb); jedis.zadd(bbar, 1.0, ba); - assertEquals(0, jedis.zdiffStore(bbar3, bbar1, bbar2)); - assertEquals(1, jedis.zdiffStore(bbar3, bfoo, bbar)); + assertEquals(0, jedis.zdiffstore(bbar3, bbar1, bbar2)); + assertEquals(1, jedis.zdiffstore(bbar3, bfoo, bbar)); List bactual = jedis.zrange(bbar3, 0, -1); assertArrayEquals(bb, bactual.iterator().next()); } @@ -1593,14 +1606,12 @@ public void zrandmember() { hash.put("bar3", 0.1d); jedis.zadd("foo", hash); - assertTrue(hash.containsKey(jedis.zrandmember("foo"))); + AssertUtil.assertCollectionContains(hash.keySet(), jedis.zrandmember("foo")); assertEquals(2, jedis.zrandmember("foo", 2).size()); List actual = jedis.zrandmemberWithScores("foo", 2); - assertNotNull(actual); assertEquals(2, actual.size()); - Tuple tuple = actual.iterator().next(); - assertEquals(hash.get(tuple.getElement()), Double.valueOf(tuple.getScore())); + actual.forEach(t -> assertEquals(hash.get(t.getElement()), t.getScore(), 0d)); // Binary assertNull(jedis.zrandmember(bfoo)); @@ -1613,14 +1624,12 @@ public void zrandmember() { bhash.put(bbar3, 0.1d); jedis.zadd(bfoo, bhash); - assertCollectionContains(bhash.keySet(), jedis.zrandmember(bfoo)); + AssertUtil.assertByteArrayCollectionContains(bhash.keySet(), jedis.zrandmember(bfoo)); assertEquals(2, jedis.zrandmember(bfoo, 2).size()); List bactual = jedis.zrandmemberWithScores(bfoo, 2); - assertNotNull(bactual); assertEquals(2, bactual.size()); - tuple = bactual.iterator().next(); - assertEquals(getScoreFromByteMap(bhash, tuple.getBinaryElement()), Double.valueOf(tuple.getScore())); + bactual.forEach(t -> assertEquals(getScoreFromByteMap(bhash, t.getBinaryElement()), t.getScore(), 0d)); } private Double getScoreFromByteMap(Map bhash, byte[] key) { diff --git a/src/test/java/redis/clients/jedis/commands/jedis/StreamsCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/StreamsCommandsTest.java index e42c55a4f7..6b28f9ed19 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/StreamsCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/StreamsCommandsTest.java @@ -7,9 +7,6 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import static redis.clients.jedis.resps.StreamGroupInfo.*; -import static redis.clients.jedis.resps.StreamInfo.*; -import static redis.clients.jedis.resps.StreamConsumersInfo.IDLE; import java.time.Duration; import java.util.HashMap; @@ -18,6 +15,8 @@ import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.atomic.AtomicReference; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; import org.junit.Test; import redis.clients.jedis.BuilderFactory; @@ -501,7 +500,7 @@ public void xreadGroupWithParamsWhenPendingMessageIsDiscarded() { @Test public void xack() { - Map map = new HashMap(); + Map map = new HashMap<>(); map.put("f1", "v1"); jedis.xadd("xack-stream", (StreamEntryID) null, map); @@ -604,7 +603,8 @@ public void xclaimWithParams() { // Get the pending event List pendingRange = jedis.xpending("xpendeing-stream", "xpendeing-group", - null, null, 3, "xpendeing-consumer"); + XPendingParams.xPendingParams().count(3).consumer("xpendeing-consumer")); + // Sleep for 100ms so we can claim events pending for more than 50ms try { Thread.sleep(100); @@ -634,7 +634,7 @@ public void xclaimJustId() { // Get the pending event List pendingRange = jedis.xpending("xpendeing-stream", "xpendeing-group", - null, null, 3, "xpendeing-consumer"); + XPendingParams.xPendingParams().count(3).consumer("xpendeing-consumer")); // Sleep for 100ms so we can claim events pending for more than 50ms try { Thread.sleep(100); @@ -663,7 +663,7 @@ public void xautoclaim() { // Get the pending event List pendingRange = jedis.xpending("xpending-stream", "xpending-group", - null, null, 3, "xpending-consumer"); + XPendingParams.xPendingParams().count(3).consumer("xpending-consumer")); // Sleep for 100ms so we can auto claim events pending for more than 50ms try { Thread.sleep(100); @@ -693,7 +693,7 @@ public void xautoclaimBinary() { // Get the pending event List pendingRange = jedis.xpending("xpending-stream", "xpending-group", - null, null, 3, "xpending-consumer"); + XPendingParams.xPendingParams().count(3).consumer("xpending-consumer")); // Sleep for 100ms so we can auto claim events pending for more than 50ms try { Thread.sleep(100); @@ -725,7 +725,7 @@ public void xautoclaimJustId() { // Get the pending event List pendingRange = jedis.xpending("xpending-stream", "xpending-group", - null, null, 3, "xpending-consumer"); + XPendingParams.xPendingParams().count(3).consumer("xpending-consumer")); // Sleep for 100ms so we can auto claim events pending for more than 50ms try { Thread.sleep(100); @@ -755,7 +755,7 @@ public void xautoclaimJustIdBinary() { // Get the pending event List pendingRange = jedis.xpending("xpending-stream", "xpending-group", - null, null, 3, "xpending-consumer"); + XPendingParams.xPendingParams().count(3).consumer("xpending-consumer")); // Sleep for 100ms so we can auto claim events pending for more than 50ms try { Thread.sleep(100); @@ -767,7 +767,7 @@ public void xautoclaimJustIdBinary() { List streamEntrys = jedis.xautoclaimJustId(SafeEncoder.encode("xpending-stream"), SafeEncoder.encode("xpending-group"), SafeEncoder.encode("xpending-consumer2"), 50, SafeEncoder.encode(new StreamEntryID().toString()), new XAutoClaimParams().count(1)); - Map.Entry> res = BuilderFactory.STREAM_AUTO_CLAIM_ID_RESPONSE.build(streamEntrys); + Map.Entry> res = BuilderFactory.STREAM_AUTO_CLAIM_JUSTID_RESPONSE.build(streamEntrys); assertEquals(1, res.getValue().size()); assertEquals(pendingRange.get(0).getID().getTime(), res.getValue().get(0).getTime()); assertEquals(pendingRange.get(0).getID().getSequence(), res.getValue().get(0).getSequence()); @@ -803,16 +803,16 @@ public void xinfo() throws InterruptedException { List groupInfo = jedis.xinfoGroups(STREAM_NAME); List consumersInfo = jedis.xinfoConsumers(STREAM_NAME, G1); + List consumerInfo = jedis.xinfoConsumers2(STREAM_NAME, G1); // Stream info test - assertEquals(2L, streamInfo.getStreamInfo().get(LENGTH)); - assertEquals(1L, streamInfo.getStreamInfo().get(RADIX_TREE_KEYS)); - assertEquals(2L, streamInfo.getStreamInfo().get(RADIX_TREE_NODES)); - assertEquals(0L, streamInfo.getStreamInfo().get(GROUPS)); - assertEquals(V1, ((StreamEntry) streamInfo.getStreamInfo().get(FIRST_ENTRY)).getFields() - .get(F1)); - assertEquals(V2, ((StreamEntry) streamInfo.getStreamInfo().get(LAST_ENTRY)).getFields().get(F1)); - assertEquals(id2, streamInfo.getStreamInfo().get(LAST_GENERATED_ID)); + assertEquals(2L, streamInfo.getStreamInfo().get(StreamInfo.LENGTH)); + assertEquals(1L, streamInfo.getStreamInfo().get(StreamInfo.RADIX_TREE_KEYS)); + assertEquals(2L, streamInfo.getStreamInfo().get(StreamInfo.RADIX_TREE_NODES)); + assertEquals(0L, streamInfo.getStreamInfo().get(StreamInfo.GROUPS)); + assertEquals(V1, ((StreamEntry) streamInfo.getStreamInfo().get(StreamInfo.FIRST_ENTRY)).getFields().get(F1)); + assertEquals(V2, ((StreamEntry) streamInfo.getStreamInfo().get(StreamInfo.LAST_ENTRY)).getFields().get(F1)); + assertEquals(id2, streamInfo.getStreamInfo().get(StreamInfo.LAST_GENERATED_ID)); // Using getters assertEquals(2, streamInfo.getLength()); @@ -825,10 +825,10 @@ public void xinfo() throws InterruptedException { // Group info test assertEquals(1, groupInfo.size()); - assertEquals(G1, groupInfo.get(0).getGroupInfo().get(NAME)); - assertEquals(1L, groupInfo.get(0).getGroupInfo().get(CONSUMERS)); - assertEquals(0L, groupInfo.get(0).getGroupInfo().get(PENDING)); - assertEquals(id2, groupInfo.get(0).getGroupInfo().get(LAST_DELIVERED)); + assertEquals(G1, groupInfo.get(0).getGroupInfo().get(StreamGroupInfo.NAME)); + assertEquals(1L, groupInfo.get(0).getGroupInfo().get(StreamGroupInfo.CONSUMERS)); + assertEquals(0L, groupInfo.get(0).getGroupInfo().get(StreamGroupInfo.PENDING)); + assertEquals(id2, groupInfo.get(0).getGroupInfo().get(StreamGroupInfo.LAST_DELIVERED)); // Using getters assertEquals(1, groupInfo.size()); @@ -837,16 +837,29 @@ public void xinfo() throws InterruptedException { assertEquals(0, groupInfo.get(0).getPending()); assertEquals(id2, groupInfo.get(0).getLastDeliveredId()); - // Consumer info test + // Consumers info test assertEquals(MY_CONSUMER, - consumersInfo.get(0).getConsumerInfo().get(redis.clients.jedis.resps.StreamConsumersInfo.NAME)); + consumersInfo.get(0).getConsumerInfo().get(StreamConsumersInfo.NAME)); assertEquals(0L, consumersInfo.get(0).getConsumerInfo().get(StreamConsumersInfo.PENDING)); - assertTrue((Long) consumersInfo.get(0).getConsumerInfo().get(IDLE) > 0); + assertTrue((Long) consumersInfo.get(0).getConsumerInfo().get(StreamConsumersInfo.IDLE) > 0); // Using getters assertEquals(MY_CONSUMER, consumersInfo.get(0).getName()); assertEquals(0L, consumersInfo.get(0).getPending()); - assertTrue(consumersInfo.get(0).getIdle() > 0); + MatcherAssert.assertThat(consumersInfo.get(0).getIdle(), Matchers.greaterThanOrEqualTo(0L)); + MatcherAssert.assertThat(consumersInfo.get(0).getInactive(), Matchers.any(Long.class)); + + // Consumer info test + assertEquals(MY_CONSUMER, + consumerInfo.get(0).getConsumerInfo().get(StreamConsumerInfo.NAME)); + assertEquals(0L, consumerInfo.get(0).getConsumerInfo().get(StreamConsumerInfo.PENDING)); + assertTrue((Long) consumerInfo.get(0).getConsumerInfo().get(StreamConsumerInfo.IDLE) > 0); + + // Using getters + assertEquals(MY_CONSUMER, consumerInfo.get(0).getName()); + assertEquals(0L, consumerInfo.get(0).getPending()); + MatcherAssert.assertThat(consumerInfo.get(0).getIdle(), Matchers.greaterThanOrEqualTo(0L)); + MatcherAssert.assertThat(consumerInfo.get(0).getInactive(), Matchers.any(Long.class)); // test with more groups and consumers jedis.xgroupCreate(STREAM_NAME, G2, StreamEntryID.LAST_ENTRY, false); @@ -856,9 +869,11 @@ public void xinfo() throws InterruptedException { List manyGroupsInfo = jedis.xinfoGroups(STREAM_NAME); List manyConsumersInfo = jedis.xinfoConsumers(STREAM_NAME, G2); + List manyConsumerInfo = jedis.xinfoConsumers2(STREAM_NAME, G2); assertEquals(2, manyGroupsInfo.size()); assertEquals(2, manyConsumersInfo.size()); + assertEquals(2, manyConsumerInfo.size()); StreamFullInfo streamInfoFull = jedis.xinfoStreamFull(STREAM_NAME); @@ -917,6 +932,8 @@ public void xinfoStreamFullWithPending() { assertEquals(1, group.getConsumers().size()); StreamConsumerFullInfo consumer = group.getConsumers().get(0); assertEquals("xreadGroup-consumer", consumer.getName()); + MatcherAssert.assertThat(consumer.getSeenTime(), Matchers.greaterThanOrEqualTo(0L)); + MatcherAssert.assertThat(consumer.getActiveTime(), Matchers.greaterThanOrEqualTo(0L)); assertEquals(1, consumer.getPending().size()); List consumerPendingEntry = consumer.getPending().get(0); assertEquals(id1, consumerPendingEntry.get(0)); diff --git a/src/test/java/redis/clients/jedis/commands/jedis/StringValuesCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/StringValuesCommandsTest.java index bf203be0ac..fb58569e82 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/StringValuesCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/StringValuesCommandsTest.java @@ -3,20 +3,15 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertNull; -import static org.junit.Assume.assumeFalse; -import static redis.clients.jedis.util.RedisVersionUtil.checkRedisMajorVersionNumber; import java.util.ArrayList; import java.util.List; - import org.junit.Test; import redis.clients.jedis.params.LCSParams; import redis.clients.jedis.resps.LCSMatchResult; -import redis.clients.jedis.resps.LCSMatchResult.MatchedPosition; import redis.clients.jedis.exceptions.JedisDataException; import redis.clients.jedis.params.GetExParams; -import redis.clients.jedis.params.StrAlgoLCSParams; public class StringValuesCommandsTest extends JedisCommandsTestBase { @Test @@ -242,80 +237,6 @@ public void psetex() { assertTrue(ttl > 0 && ttl <= 20000); } - @Test - public void strAlgoLcsWithLen() { - assumeFalse(checkRedisMajorVersionNumber(7)); - LCSMatchResult stringMatchResult = jedis.strAlgoLCSStrings("ohmytext", "mynewtext", - StrAlgoLCSParams.StrAlgoLCSParams().len()); - assertEquals(stringMatchResult.getLen(), 6); - } - - @Test - public void strAlgoLcs() { - assumeFalse(checkRedisMajorVersionNumber(7)); - LCSMatchResult stringMatchResult = jedis.strAlgoLCSStrings("ohmytext", "mynewtext", - StrAlgoLCSParams.StrAlgoLCSParams()); - assertEquals(stringMatchResult.getMatchString(), "mytext"); - } - - @Test - public void strAlgoLcsWithIdx() { - assumeFalse(checkRedisMajorVersionNumber(7)); - LCSMatchResult stringMatchResult = jedis.strAlgoLCSStrings("ohmytext", "mynewtext", - StrAlgoLCSParams.StrAlgoLCSParams().idx().withMatchLen()); - assertEquals(stringMatchResult.getLen(), 6); - assertEquals(2, stringMatchResult.getMatches().size()); - - MatchedPosition position0 = stringMatchResult.getMatches().get(0); - assertEquals(position0.getA().getStart(), 4); - assertEquals(position0.getA().getEnd(), 7); - assertEquals(position0.getB().getStart(), 5); - assertEquals(position0.getB().getEnd(), 8); - assertEquals(position0.getMatchLen(), 4); - - MatchedPosition position1 = stringMatchResult.getMatches().get(1); - assertEquals(position1.getA().getStart(), 2); - assertEquals(position1.getA().getEnd(), 3); - assertEquals(position1.getB().getStart(), 0); - assertEquals(position1.getB().getEnd(), 1); - assertEquals(position1.getMatchLen(), 2); - } - - @Test - public void strAlgoLcsWithKey() { - assumeFalse(checkRedisMajorVersionNumber(7)); - jedis.mset("key1", "ohmytext", "key2", "mynewtext"); - - LCSMatchResult stringMatchResult = jedis.strAlgoLCSKeys("key1", "key2", - StrAlgoLCSParams.StrAlgoLCSParams()); - assertEquals("mytext", stringMatchResult.getMatchString()); - } - - @Test - public void strAlgoLcsWithKeyAndIdx() { - assumeFalse(checkRedisMajorVersionNumber(7)); - jedis.mset("key1", "ohmytext", "key2", "mynewtext"); - - LCSMatchResult stringMatchResult = jedis.strAlgoLCSKeys( "key1", "key2", - StrAlgoLCSParams.StrAlgoLCSParams().idx().withMatchLen()); - assertEquals(stringMatchResult.getLen(), 6); - assertEquals(2, stringMatchResult.getMatches().size()); - - MatchedPosition position0 = stringMatchResult.getMatches().get(0); - assertEquals(position0.getA().getStart(), 4); - assertEquals(position0.getA().getEnd(), 7); - assertEquals(position0.getB().getStart(), 5); - assertEquals(position0.getB().getEnd(), 8); - assertEquals(position0.getMatchLen(), 4); - - MatchedPosition position1 = stringMatchResult.getMatches().get(1); - assertEquals(position1.getA().getStart(), 2); - assertEquals(position1.getA().getEnd(), 3); - assertEquals(position1.getB().getStart(), 0); - assertEquals(position1.getB().getEnd(), 1); - assertEquals(position1.getMatchLen(), 2); - } - @Test public void lcs() { jedis.mset("key1", "ohmytext", "key2", "mynewtext"); diff --git a/src/test/java/redis/clients/jedis/commands/unified/AllKindOfValuesCommandsTestBase.java b/src/test/java/redis/clients/jedis/commands/unified/AllKindOfValuesCommandsTestBase.java index 13a4a7b558..25ecad1eea 100644 --- a/src/test/java/redis/clients/jedis/commands/unified/AllKindOfValuesCommandsTestBase.java +++ b/src/test/java/redis/clients/jedis/commands/unified/AllKindOfValuesCommandsTestBase.java @@ -1,5 +1,6 @@ package redis.clients.jedis.commands.unified; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -20,9 +21,6 @@ import static redis.clients.jedis.util.SafeEncoder.encodeObject; import static redis.clients.jedis.params.ScanParams.SCAN_POINTER_START; import static redis.clients.jedis.params.ScanParams.SCAN_POINTER_START_BINARY; -import static redis.clients.jedis.params.SetParams.setParams; -import static redis.clients.jedis.util.AssertUtil.assertByteArrayListEquals; -import static redis.clients.jedis.util.AssertUtil.assertCollectionContains; import java.util.ArrayList; import java.util.Arrays; @@ -31,14 +29,23 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import org.hamcrest.Matchers; +import org.junit.Assume; import org.junit.Test; +import redis.clients.jedis.RedisProtocol; +import redis.clients.jedis.ScanIteration; import redis.clients.jedis.StreamEntryID; import redis.clients.jedis.args.ExpiryOption; import redis.clients.jedis.params.ScanParams; import redis.clients.jedis.resps.ScanResult; import redis.clients.jedis.params.RestoreParams; import redis.clients.jedis.exceptions.JedisDataException; +import redis.clients.jedis.params.SetParams; +import redis.clients.jedis.util.AssertUtil; +import redis.clients.jedis.util.KeyValue; +import redis.clients.jedis.util.RedisProtocolUtil; +import redis.clients.jedis.util.SafeEncoder; public abstract class AllKindOfValuesCommandsTestBase extends UnifiedJedisCommandsTestBase { @@ -187,28 +194,20 @@ public void keys() { jedis.set("foobar", "bar"); Set keys = jedis.keys("foo*"); - Set expected = new HashSet<>(); - expected.add("foo"); - expected.add("foobar"); - assertEquals(expected, keys); + AssertUtil.assertCollectionContains(keys, "foo"); + AssertUtil.assertCollectionContains(keys, "foobar"); - expected = new HashSet<>(); - keys = jedis.keys("bar*"); - - assertEquals(expected, keys); + assertEquals(Collections.emptySet(), jedis.keys("bar*")); // Binary jedis.set(bfoo, bbar); jedis.set(bfoobar, bbar); Set bkeys = jedis.keys(bfoostar); - assertEquals(2, bkeys.size()); - assertCollectionContains(bkeys, bfoo); - assertCollectionContains(bkeys, bfoobar); - - bkeys = jedis.keys(bbarstar); + AssertUtil.assertByteArrayCollectionContains(bkeys, bfoo); + AssertUtil.assertByteArrayCollectionContains(bkeys, bfoobar); - assertEquals(0, bkeys.size()); + assertEquals(Collections.emptySet(), jedis.keys(bbarstar)); } @Test @@ -673,11 +672,11 @@ public void scanType() { assertEquals(4, page1Count + page2Count); binaryResult = jedis.scan(SCAN_POINTER_START_BINARY, noParams, hash); - assertByteArrayListEquals(Collections.singletonList(new byte[]{98}), binaryResult.getResult()); + AssertUtil.assertByteArrayListEquals(Collections.singletonList(new byte[]{98}), binaryResult.getResult()); binaryResult = jedis.scan(SCAN_POINTER_START_BINARY, noParams, set); - assertByteArrayListEquals(Collections.singletonList(new byte[]{100}), binaryResult.getResult()); + AssertUtil.assertByteArrayListEquals(Collections.singletonList(new byte[]{100}), binaryResult.getResult()); binaryResult = jedis.scan(SCAN_POINTER_START_BINARY, noParams, zset); - assertByteArrayListEquals(Collections.singletonList(new byte[]{102}), binaryResult.getResult()); + AssertUtil.assertByteArrayListEquals(Collections.singletonList(new byte[]{102}), binaryResult.getResult()); } @Test @@ -710,10 +709,10 @@ private ScanResult scanCompletely(String cursor) { @Test public void setNxExAndGet() { - assertEquals("OK", jedis.set("hello", "world", setParams().nx().ex(expireSeconds))); + assertEquals("OK", jedis.set("hello", "world", SetParams.setParams().nx().ex(expireSeconds))); assertEquals("world", jedis.get("hello")); - assertNull(jedis.set("hello", "bar", setParams().nx().ex(expireSeconds))); + assertNull(jedis.set("hello", "bar", SetParams.setParams().nx().ex(expireSeconds))); assertEquals("world", jedis.get("hello")); long ttl = jedis.ttl("hello"); @@ -723,10 +722,10 @@ public void setNxExAndGet() { byte[] bworld = { 0x77, 0x6F, 0x72, 0x6C, 0x64 }; byte[] bhello = { 0x68, 0x65, 0x6C, 0x6C, 0x6F }; - assertEquals("OK", jedis.set(bworld, bhello, setParams().nx().ex(expireSeconds))); + assertEquals("OK", jedis.set(bworld, bhello, SetParams.setParams().nx().ex(expireSeconds))); assertArrayEquals(bhello, jedis.get(bworld)); - assertNull(jedis.set(bworld, bbar, setParams().nx().ex(expireSeconds))); + assertNull(jedis.set(bworld, bbar, SetParams.setParams().nx().ex(expireSeconds))); assertArrayEquals(bhello, jedis.get(bworld)); long bttl = jedis.ttl(bworld); @@ -738,12 +737,12 @@ public void setGetOptionTest() { assertEquals("OK", jedis.set("hello", "world")); // GET old value - assertEquals("world", jedis.set("hello", "jedis", setParams().get())); + assertEquals("world", jedis.setGet("hello", "jedis")); assertEquals("jedis", jedis.get("hello")); // GET null value - assertNull(jedis.set("key", "value", setParams().get())); + assertNull(jedis.setGet("key", "value")); } @Test @@ -751,12 +750,12 @@ public void setGet() { assertEquals("OK", jedis.set("hello", "world")); // GET old value - assertEquals("world", jedis.setGet("hello", "jedis", setParams())); + assertEquals("world", jedis.setGet("hello", "jedis", SetParams.setParams())); assertEquals("jedis", jedis.get("hello")); // GET null value - assertNull(jedis.setGet("key", "value", setParams())); + assertNull(jedis.setGet("key", "value", SetParams.setParams())); } @Test @@ -796,17 +795,60 @@ public void sendBlockingCommandTest() { } @Test - public void encodeCompleteResponse() { + public void encodeCompleteResponsePing() { + assertEquals("PONG", SafeEncoder.encodeObject(jedis.sendCommand(PING))); + } + + @Test + public void encodeCompleteResponseHgetall() { + Assume.assumeFalse(RedisProtocolUtil.getRedisProtocol() == RedisProtocol.RESP3); + + HashMap entries = new HashMap<>(); + entries.put("foo", "bar"); + entries.put("foo2", "bar2"); + jedis.hset("hash:test:encode", entries); + + List encodeObj = (List) SafeEncoder.encodeObject(jedis.sendCommand(HGETALL, "hash:test:encode")); + + assertEquals(4, encodeObj.size()); + entries.forEach((k, v) -> { + assertThat((Iterable) encodeObj, Matchers.hasItem(k)); + assertEquals(v, findValueFromMapAsList(encodeObj, k)); + }); + } + + @Test + public void encodeCompleteResponseHgetallResp3() { + Assume.assumeTrue(RedisProtocolUtil.getRedisProtocol() == RedisProtocol.RESP3); + + HashMap entries = new HashMap<>(); + entries.put("foo", "bar"); + entries.put("foo2", "bar2"); + jedis.hset("hash:test:encode", entries); + + List encodeObj = (List) SafeEncoder.encodeObject(jedis.sendCommand(HGETALL, "hash:test:encode")); + + assertEquals(2, encodeObj.size()); + encodeObj.forEach(kv -> { + assertThat(entries, Matchers.hasEntry(kv.getKey(), kv.getValue())); + }); + } + + @Test + public void encodeCompleteResponseXinfoStream() { + Assume.assumeFalse(RedisProtocolUtil.getRedisProtocol() == RedisProtocol.RESP3); + HashMap entry = new HashMap<>(); entry.put("foo", "bar"); StreamEntryID entryID = jedis.xadd("mystream", StreamEntryID.NEW_ENTRY, entry); jedis.xgroupCreate("mystream", "mygroup", null, false); Object obj = jedis.sendCommand(XINFO, "STREAM", "mystream"); - List encodeObj = (List) encodeObject(obj); - assertTrue(encodeObj.size() >= 14); - assertEquals(0, encodeObj.size() % 2); // must be even + List encodeObj = (List) SafeEncoder.encodeObject(obj); + + assertThat(encodeObj.size(), Matchers.greaterThanOrEqualTo(14)); + assertEquals("must have even number of elements", 0, encodeObj.size() % 2); // must be even assertEquals(1L, findValueFromMapAsList(encodeObj, "length")); assertEquals(entryID.toString(), findValueFromMapAsList(encodeObj, "last-generated-id")); @@ -817,16 +859,32 @@ public void encodeCompleteResponse() { assertEquals(entryAsList, ((List) findValueFromMapAsList(encodeObj, "first-entry")).get(1)); assertEquals(entryAsList, ((List) findValueFromMapAsList(encodeObj, "last-entry")).get(1)); + } + + @Test + public void encodeCompleteResponseXinfoStreamResp3() { + Assume.assumeTrue(RedisProtocolUtil.getRedisProtocol() == RedisProtocol.RESP3); + + HashMap entry = new HashMap<>(); + entry.put("foo", "bar"); + StreamEntryID entryID = jedis.xadd("mystream", StreamEntryID.NEW_ENTRY, entry); + jedis.xgroupCreate("mystream", "mygroup", null, false); - assertEquals("PONG", encodeObject(jedis.sendCommand(PING))); + Object obj = jedis.sendCommand(XINFO, "STREAM", "mystream"); - entry.put("foo2", "bar2"); - jedis.hset("hash:test:encode", entry); - encodeObj = (List) encodeObject(jedis.sendCommand(HGETALL, "hash:test:encode")); + List encodeObj = (List) SafeEncoder.encodeObject(obj); - assertEquals(4, encodeObj.size()); - assertTrue(encodeObj.contains("foo")); - assertTrue(encodeObj.contains("foo2")); + assertThat(encodeObj.size(), Matchers.greaterThanOrEqualTo(7)); + + assertEquals(1L, findValueFromMapAsKeyValueList(encodeObj, "length")); + assertEquals(entryID.toString(), findValueFromMapAsKeyValueList(encodeObj, "last-generated-id")); + + List entryAsList = new ArrayList<>(2); + entryAsList.add("foo"); + entryAsList.add("bar"); + + assertEquals(entryAsList, ((List) findValueFromMapAsKeyValueList(encodeObj, "first-entry")).get(1)); + assertEquals(entryAsList, ((List) findValueFromMapAsKeyValueList(encodeObj, "last-entry")).get(1)); } private Object findValueFromMapAsList(List list, Object key) { @@ -838,6 +896,15 @@ private Object findValueFromMapAsList(List list, Object key) { return null; } + private Object findValueFromMapAsKeyValueList(List list, Object key) { + for (KeyValue kv : list) { + if (key.equals(kv.getKey())) { + return kv.getValue(); + } + } + return null; + } + @Test public void copy() { assertFalse(jedis.copy("unknown", "foo", false)); @@ -863,4 +930,27 @@ public void copy() { assertTrue(jedis.copy(bfoo1, bfoo2, true)); assertArrayEquals(bbar1, jedis.get(bfoo2)); } + + @Test + public void scanIteration() { + Set allIn = new HashSet<>(26 * 26); + char[] arr = new char[2]; + for (int i = 0; i < 26; i++) { + arr[0] = (char) ('a' + i); + for (int j = 0; j < 26; j++) { + arr[1] = (char) ('a' + j); + String str = new String(arr); + jedis.incr(str); + allIn.add(str); + } + } + + Set allScan = new HashSet<>(); + ScanIteration scan = jedis.scanIteration(10, "*"); + while (!scan.isIterationCompleted()) { + ScanResult batch = scan.nextBatch(); + allScan.addAll(batch.getResult()); + } + assertEquals(allIn, allScan); + } } diff --git a/src/test/java/redis/clients/jedis/commands/unified/BinaryValuesCommandsTestBase.java b/src/test/java/redis/clients/jedis/commands/unified/BinaryValuesCommandsTestBase.java index 2735c31845..941d70c383 100644 --- a/src/test/java/redis/clients/jedis/commands/unified/BinaryValuesCommandsTestBase.java +++ b/src/test/java/redis/clients/jedis/commands/unified/BinaryValuesCommandsTestBase.java @@ -111,6 +111,7 @@ public void setAndExpire() { public void setAndKeepttl() { assertEquals("OK", jedis.set(bfoo, binaryValue, setParams().nx().ex(expireSeconds))); assertEquals("OK", jedis.set(bfoo, binaryValue, setParams().keepttl())); + assertEquals("OK", jedis.set(bfoo, binaryValue, setParams().keepTtl())); long ttl = jedis.ttl(bfoo); assertTrue(0 < ttl && ttl <= expireSeconds); jedis.set(bfoo, binaryValue); @@ -329,12 +330,12 @@ public void setGet() { assertEquals("OK", jedis.set(bfoo, bbar)); // GET old value - assertArrayEquals(bbar, jedis.setGet(bfoo, binaryValue, setParams())); + assertArrayEquals(bbar, jedis.setGet(bfoo, binaryValue)); assertArrayEquals(binaryValue, jedis.get(bfoo)); // GET null value - assertNull(jedis.setGet(bbar, bfoo, setParams())); + assertNull(jedis.setGet(bbar, bfoo)); } @Test diff --git a/src/test/java/redis/clients/jedis/commands/unified/BitCommandsTestBase.java b/src/test/java/redis/clients/jedis/commands/unified/BitCommandsTestBase.java index 4803a0d0f0..8cf5caf3f0 100644 --- a/src/test/java/redis/clients/jedis/commands/unified/BitCommandsTestBase.java +++ b/src/test/java/redis/clients/jedis/commands/unified/BitCommandsTestBase.java @@ -35,6 +35,7 @@ public void bitpos() { String foo = "foo"; jedis.set(foo, String.valueOf(0)); + // string "0" with bits: 0011 0000 jedis.setbit(foo, 3, true); jedis.setbit(foo, 7, true); @@ -42,7 +43,8 @@ public void bitpos() { jedis.setbit(foo, 39, true); /* - * byte: 0 1 2 3 4 bit: 00010001 / 00000100 / 00000000 / 00000000 / 00000001 + * bit: 00110001 / 00000100 / 00000000 / 00000000 / 00000001 + * byte: 0 1 2 3 4 */ long offset = jedis.bitpos(foo, true); assertEquals(2, offset); @@ -69,6 +71,7 @@ public void bitposBinary() { byte[] bfoo = { 0x01, 0x02, 0x03, 0x04 }; jedis.set(bfoo, Protocol.toByteArray(0)); + // bits: 0011 0000 jedis.setbit(bfoo, 3, true); jedis.setbit(bfoo, 7, true); @@ -76,7 +79,8 @@ public void bitposBinary() { jedis.setbit(bfoo, 39, true); /* - * byte: 0 1 2 3 4 bit: 00010001 / 00000100 / 00000000 / 00000000 / 00000001 + * bit: 00110001 / 00000100 / 00000000 / 00000000 / 00000001 + * byte: 0 1 2 3 4 */ long offset = jedis.bitpos(bfoo, true); assertEquals(2, offset); @@ -107,7 +111,8 @@ public void bitposWithNoMatchingBitExist() { } /* - * byte: 0 bit: 11111111 + * bit: 11111111 + * byte: 0 */ long offset = jedis.bitpos(foo, false); // offset should be last index + 1 @@ -124,7 +129,8 @@ public void bitposWithNoMatchingBitExistWithinRange() { } /* - * byte: 0 1 2 3 4 bit: 11111111 / 11111111 / 11111111 / 11111111 / 11111111 + * bit: 11111111 / 11111111 / 11111111 / 11111111 / 11111111 + * byte: 0 1 2 3 4 */ long offset = jedis.bitpos(foo, false, new BitPosParams(2, 3)); // offset should be -1 diff --git a/src/test/java/redis/clients/jedis/commands/unified/HashesCommandsTestBase.java b/src/test/java/redis/clients/jedis/commands/unified/HashesCommandsTestBase.java index d6c6036c5c..cac2606984 100644 --- a/src/test/java/redis/clients/jedis/commands/unified/HashesCommandsTestBase.java +++ b/src/test/java/redis/clients/jedis/commands/unified/HashesCommandsTestBase.java @@ -9,9 +9,6 @@ import static redis.clients.jedis.params.ScanParams.SCAN_POINTER_START; import static redis.clients.jedis.params.ScanParams.SCAN_POINTER_START_BINARY; -import static redis.clients.jedis.util.AssertUtil.assertByteArrayListEquals; -import static redis.clients.jedis.util.AssertUtil.assertByteArraySetEquals; -import static redis.clients.jedis.util.AssertUtil.assertCollectionContains; import java.util.ArrayList; import java.util.Collections; @@ -26,6 +23,7 @@ import redis.clients.jedis.params.ScanParams; import redis.clients.jedis.resps.ScanResult; +import redis.clients.jedis.util.AssertUtil; import redis.clients.jedis.util.JedisByteHashMap; public abstract class HashesCommandsTestBase extends UnifiedJedisCommandsTestBase { @@ -148,7 +146,7 @@ public void hmget() { bexpected.add(bbar); bexpected.add(null); - assertByteArrayListEquals(bexpected, bvalues); + AssertUtil.assertByteArrayListEquals(bexpected, bvalues); } @Test @@ -264,7 +262,7 @@ public void hkeys() { Set bexpected = new LinkedHashSet(); bexpected.add(bbar); bexpected.add(bcar); - assertByteArraySetEquals(bexpected, bkeys); + AssertUtil.assertByteArraySetEquals(bexpected, bkeys); } @Test @@ -276,8 +274,8 @@ public void hvals() { List vals = jedis.hvals("foo"); assertEquals(2, vals.size()); - assertTrue(vals.contains("bar")); - assertTrue(vals.contains("car")); + AssertUtil.assertCollectionContains(vals, "bar"); + AssertUtil.assertCollectionContains(vals, "car"); // Binary Map bhash = new LinkedHashMap(); @@ -288,8 +286,8 @@ public void hvals() { List bvals = jedis.hvals(bfoo); assertEquals(2, bvals.size()); - assertCollectionContains(bvals, bbar); - assertCollectionContains(bvals, bcar); + AssertUtil.assertByteArrayCollectionContains(bvals, bbar); + AssertUtil.assertByteArrayCollectionContains(bvals, bcar); } @Test @@ -421,7 +419,8 @@ public void testBinaryHstrLen() { public void hrandfield() { assertNull(jedis.hrandfield("foo")); assertEquals(Collections.emptyList(), jedis.hrandfield("foo", 1)); - assertEquals(Collections.emptyMap(), jedis.hrandfieldWithValues("foo", 1)); + assertEquals(Collections.emptyList(), jedis.hrandfieldWithValues("foo", 1)); + assertEquals(Collections.emptyList(), jedis.hrandfieldWithValues("foo", -1)); Map hash = new LinkedHashMap<>(); hash.put("bar", "bar"); @@ -433,16 +432,23 @@ public void hrandfield() { assertTrue(hash.containsKey(jedis.hrandfield("foo"))); assertEquals(2, jedis.hrandfield("foo", 2).size()); - Map actual = jedis.hrandfieldWithValues("foo", 2); - assertNotNull(actual); + List> actual = jedis.hrandfieldWithValues("foo", 2); assertEquals(2, actual.size()); - Map.Entry entry = actual.entrySet().iterator().next(); - assertEquals(hash.get(entry.getKey()), entry.getValue()); + actual.forEach(e -> assertEquals(hash.get(e.getKey()), e.getValue())); + + actual = jedis.hrandfieldWithValues("foo", 5); + assertEquals(3, actual.size()); + actual.forEach(e -> assertEquals(hash.get(e.getKey()), e.getValue())); + + actual = jedis.hrandfieldWithValues("foo", -5); + assertEquals(5, actual.size()); + actual.forEach(e -> assertEquals(hash.get(e.getKey()), e.getValue())); // binary assertNull(jedis.hrandfield(bfoo)); assertEquals(Collections.emptyList(), jedis.hrandfield(bfoo, 1)); - assertEquals(Collections.emptyMap(), jedis.hrandfieldWithValues(bfoo, 1)); + assertEquals(Collections.emptyList(), jedis.hrandfieldWithValues(bfoo, 1)); + assertEquals(Collections.emptyList(), jedis.hrandfieldWithValues(bfoo, -1)); Map bhash = new JedisByteHashMap(); bhash.put(bbar, bbar); @@ -454,10 +460,16 @@ public void hrandfield() { assertTrue(bhash.containsKey(jedis.hrandfield(bfoo))); assertEquals(2, jedis.hrandfield(bfoo, 2).size()); - Map bactual = jedis.hrandfieldWithValues(bfoo, 2); - assertNotNull(bactual); + List> bactual = jedis.hrandfieldWithValues(bfoo, 2); assertEquals(2, bactual.size()); - Map.Entry bentry = bactual.entrySet().iterator().next(); - assertArrayEquals(bhash.get(bentry.getKey()), (byte[]) bentry.getValue()); + bactual.forEach(e -> assertArrayEquals(bhash.get(e.getKey()), e.getValue())); + + bactual = jedis.hrandfieldWithValues(bfoo, 5); + assertEquals(3, bactual.size()); + bactual.forEach(e -> assertArrayEquals(bhash.get(e.getKey()), e.getValue())); + + bactual = jedis.hrandfieldWithValues(bfoo, -5); + assertEquals(5, bactual.size()); + bactual.forEach(e -> assertArrayEquals(bhash.get(e.getKey()), e.getValue())); } } diff --git a/src/test/java/redis/clients/jedis/commands/unified/ListCommandsTestBase.java b/src/test/java/redis/clients/jedis/commands/unified/ListCommandsTestBase.java index b444a5722f..ddbe7f779a 100644 --- a/src/test/java/redis/clients/jedis/commands/unified/ListCommandsTestBase.java +++ b/src/test/java/redis/clients/jedis/commands/unified/ListCommandsTestBase.java @@ -21,7 +21,6 @@ import redis.clients.jedis.args.ListDirection; import redis.clients.jedis.exceptions.JedisDataException; import redis.clients.jedis.params.LPosParams; -import redis.clients.jedis.resps.KeyedListElement; import redis.clients.jedis.util.KeyValue; public abstract class ListCommandsTestBase extends UnifiedJedisCommandsTestBase { @@ -444,7 +443,7 @@ public void blpop() throws InterruptedException { @Test public void blpopDouble() throws InterruptedException { - KeyedListElement result = jedis.blpop(0.1, "foo"); + KeyValue result = jedis.blpop(0.1, "foo"); assertNull(result); jedis.lpush("foo", "bar"); @@ -452,7 +451,7 @@ public void blpopDouble() throws InterruptedException { assertNotNull(result); assertEquals("foo", result.getKey()); - assertEquals("bar", result.getElement()); + assertEquals("bar", result.getValue()); // Multi keys result = jedis.blpop(0.18, "foo", "foo1"); @@ -464,16 +463,15 @@ public void blpopDouble() throws InterruptedException { assertNotNull(result); assertEquals("foo1", result.getKey()); - assertEquals("bar1", result.getElement()); + assertEquals("bar1", result.getValue()); // Binary jedis.lpush(bfoo, bbar); - List bresult = jedis.blpop(3.12, bfoo); + KeyValue bresult = jedis.blpop(3.12, bfoo); assertNotNull(bresult); - assertEquals(2, bresult.size()); - assertArrayEquals(bfoo, bresult.get(0)); - assertArrayEquals(bbar, bresult.get(1)); + assertArrayEquals(bfoo, bresult.getKey()); + assertArrayEquals(bbar, bresult.getValue()); // Binary Multi keys bresult = jedis.blpop(0.11, bfoo, bfoo1); @@ -484,9 +482,8 @@ public void blpopDouble() throws InterruptedException { bresult = jedis.blpop(1d, bfoo, bfoo1); assertNotNull(bresult); - assertEquals(2, bresult.size()); - assertArrayEquals(bfoo, bresult.get(0)); - assertArrayEquals(bbar, bresult.get(1)); + assertArrayEquals(bfoo, bresult.getKey()); + assertArrayEquals(bbar, bresult.getValue()); } @Test @@ -494,7 +491,7 @@ public void blpopDoubleWithSleep() { long startMillis, totalMillis; startMillis = System.currentTimeMillis(); - KeyedListElement result = jedis.blpop(0.04, "foo"); + KeyValue result = jedis.blpop(0.04, "foo"); totalMillis = System.currentTimeMillis() - startMillis; assertTrue("TotalMillis=" + totalMillis, totalMillis < 200); assertNull(result); @@ -514,7 +511,7 @@ public void blpopDoubleWithSleep() { assertNotNull(result); assertEquals("foo", result.getKey()); - assertEquals("bar", result.getElement()); + assertEquals("bar", result.getValue()); } @Test @@ -566,7 +563,7 @@ public void brpop() throws InterruptedException { @Test public void brpopDouble() throws InterruptedException { - KeyedListElement result = jedis.brpop(0.1, "foo"); + KeyValue result = jedis.brpop(0.1, "foo"); assertNull(result); jedis.lpush("foo", "bar"); @@ -574,7 +571,7 @@ public void brpopDouble() throws InterruptedException { assertNotNull(result); assertEquals("foo", result.getKey()); - assertEquals("bar", result.getElement()); + assertEquals("bar", result.getValue()); // Multi keys result = jedis.brpop(0.18, "foo", "foo1"); @@ -586,16 +583,15 @@ public void brpopDouble() throws InterruptedException { assertNotNull(result); assertEquals("foo1", result.getKey()); - assertEquals("bar1", result.getElement()); + assertEquals("bar1", result.getValue()); // Binary jedis.lpush(bfoo, bbar); - List bresult = jedis.brpop(3.12, bfoo); + KeyValue bresult = jedis.brpop(3.12, bfoo); assertNotNull(bresult); - assertEquals(2, bresult.size()); - assertArrayEquals(bfoo, bresult.get(0)); - assertArrayEquals(bbar, bresult.get(1)); + assertArrayEquals(bfoo, bresult.getKey()); + assertArrayEquals(bbar, bresult.getValue()); // Binary Multi keys bresult = jedis.brpop(0.11, bfoo, bfoo1); @@ -606,9 +602,8 @@ public void brpopDouble() throws InterruptedException { bresult = jedis.brpop(1d, bfoo, bfoo1); assertNotNull(bresult); - assertEquals(2, bresult.size()); - assertArrayEquals(bfoo, bresult.get(0)); - assertArrayEquals(bbar, bresult.get(1)); + assertArrayEquals(bfoo, bresult.getKey()); + assertArrayEquals(bbar, bresult.getValue()); } @Test @@ -616,7 +611,7 @@ public void brpopDoubleWithSleep() { long startMillis, totalMillis; startMillis = System.currentTimeMillis(); - KeyedListElement result = jedis.brpop(0.04, "foo"); + KeyValue result = jedis.brpop(0.04, "foo"); totalMillis = System.currentTimeMillis() - startMillis; assertTrue("TotalMillis=" + totalMillis, totalMillis < 200); assertNull(result); @@ -636,7 +631,7 @@ public void brpopDoubleWithSleep() { assertNotNull(result); assertEquals("foo", result.getKey()); - assertEquals("bar", result.getElement()); + assertEquals("bar", result.getValue()); } @Test diff --git a/src/test/java/redis/clients/jedis/commands/unified/SortedSetCommandsTestBase.java b/src/test/java/redis/clients/jedis/commands/unified/SortedSetCommandsTestBase.java index c02b712cac..fed8fb2603 100644 --- a/src/test/java/redis/clients/jedis/commands/unified/SortedSetCommandsTestBase.java +++ b/src/test/java/redis/clients/jedis/commands/unified/SortedSetCommandsTestBase.java @@ -1,30 +1,19 @@ package redis.clients.jedis.commands.unified; +import static java.util.Collections.singletonList; import static org.junit.Assert.*; import static redis.clients.jedis.params.ScanParams.SCAN_POINTER_START; import static redis.clients.jedis.params.ScanParams.SCAN_POINTER_START_BINARY; import static redis.clients.jedis.util.AssertUtil.assertByteArrayListEquals; -import static redis.clients.jedis.util.AssertUtil.assertByteArraySetEquals; -import static redis.clients.jedis.util.AssertUtil.assertCollectionContains; - -import java.util.Arrays; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import org.junit.Test; -import redis.clients.jedis.BuilderFactory; import redis.clients.jedis.args.SortedSetOption; import redis.clients.jedis.params.*; -import redis.clients.jedis.resps.KeyedZSetElement; import redis.clients.jedis.resps.ScanResult; import redis.clients.jedis.resps.Tuple; +import redis.clients.jedis.util.AssertUtil; import redis.clients.jedis.util.KeyValue; import redis.clients.jedis.util.SafeEncoder; @@ -459,6 +448,36 @@ public void zrank() { assertNull(jedis.zrank(bcar, bb)); } + @Test + public void zrankWithScore() { + jedis.zadd("foo", 1d, "a"); + jedis.zadd("foo", 2d, "b"); + + KeyValue keyValue = jedis.zrankWithScore("foo", "a"); + assertEquals(Long.valueOf(0), keyValue.getKey()); + assertEquals(Double.valueOf(1d), keyValue.getValue()); + + keyValue = jedis.zrankWithScore("foo", "b"); + assertEquals(Long.valueOf(1), keyValue.getKey()); + assertEquals(Double.valueOf(2d), keyValue.getValue()); + + assertNull(jedis.zrankWithScore("car", "b")); + + // Binary + jedis.zadd(bfoo, 1d, ba); + jedis.zadd(bfoo, 2d, bb); + + keyValue = jedis.zrankWithScore(bfoo, ba); + assertEquals(Long.valueOf(0), keyValue.getKey()); + assertEquals(Double.valueOf(1d), keyValue.getValue()); + + keyValue = jedis.zrankWithScore(bfoo, bb); + assertEquals(Long.valueOf(1), keyValue.getKey()); + assertEquals(Double.valueOf(2d), keyValue.getValue()); + + assertNull(jedis.zrankWithScore(bcar, bb)); + } + @Test public void zrevrank() { jedis.zadd("foo", 1d, "a"); @@ -1205,14 +1224,15 @@ public void zunion() { ZParams params = new ZParams(); params.weights(2, 2.5); params.aggregate(ZParams.Aggregate.SUM); - Set expected = new LinkedHashSet<>(); + + List expected = new ArrayList<>(); expected.add("a"); expected.add("b"); assertEquals(expected, jedis.zunion(params, "foo", "bar")); - Set expectedTuple = new LinkedHashSet<>(); - expectedTuple.add(new Tuple("b", new Double(9))); + List expectedTuple = new ArrayList<>(); expectedTuple.add(new Tuple("a", new Double(7))); + expectedTuple.add(new Tuple("b", new Double(9))); assertEquals(expectedTuple, jedis.zunionWithScores(params, "foo", "bar")); // Binary @@ -1221,18 +1241,15 @@ public void zunion() { jedis.zadd(bbar, 2, ba); jedis.zadd(bbar, 2, bb); - ZParams bparams = new ZParams(); - bparams.weights(2, 2.5); - bparams.aggregate(ZParams.Aggregate.SUM); - Set bexpected = new LinkedHashSet<>(); - bexpected.add(bb); + List bexpected = new ArrayList<>(); bexpected.add(ba); - assertByteArraySetEquals(bexpected, jedis.zunion(params, bfoo, bbar)); + bexpected.add(bb); + AssertUtil.assertByteArrayListEquals(bexpected, jedis.zunion(params, bfoo, bbar)); - Set bexpectedTuple = new LinkedHashSet<>(); - bexpectedTuple.add(new Tuple(bb, new Double(9))); + List bexpectedTuple = new ArrayList<>(); bexpectedTuple.add(new Tuple(ba, new Double(7))); - assertEquals(bexpectedTuple, jedis.zunionWithScores(bparams, bfoo, bbar)); + bexpectedTuple.add(new Tuple(bb, new Double(9))); + assertEquals(bexpectedTuple, jedis.zunionWithScores(params, bfoo, bbar)); } @Test @@ -1308,9 +1325,9 @@ public void zinter() { ZParams params = new ZParams(); params.weights(2, 2.5); params.aggregate(ZParams.Aggregate.SUM); - assertEquals(Collections.singleton("a"), jedis.zinter(params, "foo", "bar")); + assertEquals(singletonList("a"), jedis.zinter(params, "foo", "bar")); - assertEquals(Collections.singleton(new Tuple("a", new Double(7))), + assertEquals(singletonList(new Tuple("a", new Double(7))), jedis.zinterWithScores(params, "foo", "bar")); // Binary @@ -1321,9 +1338,9 @@ public void zinter() { ZParams bparams = new ZParams(); bparams.weights(2, 2.5); bparams.aggregate(ZParams.Aggregate.SUM); - assertByteArraySetEquals(Collections.singleton(ba), jedis.zinter(params, bfoo, bbar)); + AssertUtil.assertByteArrayListEquals(singletonList(ba), jedis.zinter(params, bfoo, bbar)); - assertEquals(Collections.singleton(new Tuple(ba, new Double(7))), + assertEquals(singletonList(new Tuple(ba, new Double(7))), jedis.zinterWithScores(bparams, bfoo, bbar)); } @@ -1335,7 +1352,7 @@ public void zinterstore() { assertEquals(1, jedis.zinterstore("dst", "foo", "bar")); - assertEquals(Collections.singletonList(new Tuple("a", new Double(3))), + assertEquals(singletonList(new Tuple("a", new Double(3))), jedis.zrangeWithScores("dst", 0, 100)); // Binary @@ -1345,7 +1362,7 @@ public void zinterstore() { assertEquals(1, jedis.zinterstore(SafeEncoder.encode("dst"), bfoo, bbar)); - assertEquals(Collections.singletonList(new Tuple(ba, new Double(3))), + assertEquals(singletonList(new Tuple(ba, new Double(3))), jedis.zrangeWithScores(SafeEncoder.encode("dst"), 0, 100)); } @@ -1361,7 +1378,7 @@ public void zintertoreParams() { assertEquals(1, jedis.zinterstore("dst", params, "foo", "bar")); - assertEquals(Collections.singletonList(new Tuple("a", new Double(7))), + assertEquals(singletonList(new Tuple("a", new Double(7))), jedis.zrangeWithScores("dst", 0, 100)); // Binary @@ -1375,7 +1392,7 @@ public void zintertoreParams() { assertEquals(1, jedis.zinterstore(SafeEncoder.encode("dst"), bparams, bfoo, bbar)); - assertEquals(Collections.singletonList(new Tuple(ba, new Double(7))), + assertEquals(singletonList(new Tuple(ba, new Double(7))), jedis.zrangeWithScores(SafeEncoder.encode("dst"), 0, 100)); } @@ -1494,17 +1511,15 @@ public void bzpopmax() { jedis.zadd("foo", 1d, "a", ZAddParams.zAddParams().nx()); jedis.zadd("foo", 10d, "b", ZAddParams.zAddParams().nx()); jedis.zadd("bar", 0.1d, "c", ZAddParams.zAddParams().nx()); - assertEquals(new KeyedZSetElement("foo", "b", 10d), jedis.bzpopmax(0, "foo", "bar")); + assertEquals(new KeyValue<>("foo", new Tuple("b", 10d)), jedis.bzpopmax(0, "foo", "bar")); // Binary jedis.zadd(bfoo, 1d, ba); jedis.zadd(bfoo, 10d, bb); jedis.zadd(bbar, 0.1d, bc); - List actual = jedis.bzpopmax(0, bfoo, bbar); - assertEquals(3, actual.size()); - assertArrayEquals(bfoo, actual.get(0)); - assertArrayEquals(bb, actual.get(1)); - assertEquals(10d, BuilderFactory.DOUBLE.build(actual.get(2)), 1e-10); + KeyValue actual = jedis.bzpopmax(0, bfoo, bbar); + assertArrayEquals(bfoo, actual.getKey()); + assertEquals(new Tuple(bb, 10d), actual.getValue()); } @Test @@ -1512,17 +1527,15 @@ public void bzpopmin() { jedis.zadd("foo", 1d, "a", ZAddParams.zAddParams().nx()); jedis.zadd("foo", 10d, "b", ZAddParams.zAddParams().nx()); jedis.zadd("bar", 0.1d, "c", ZAddParams.zAddParams().nx()); - assertEquals(new KeyedZSetElement("bar", "c", 0.1d), jedis.bzpopmin(0, "bar", "foo")); + assertEquals(new KeyValue<>("bar", new Tuple("c", 0.1)), jedis.bzpopmin(0, "bar", "foo")); // Binary jedis.zadd(bfoo, 1d, ba); jedis.zadd(bfoo, 10d, bb); jedis.zadd(bbar, 0.1d, bc); - List actual = jedis.bzpopmin(0, bbar, bfoo); - assertEquals(3, actual.size()); - assertArrayEquals(bbar, actual.get(0)); - assertArrayEquals(bc, actual.get(1)); - assertEquals(0.1d, BuilderFactory.DOUBLE.build(actual.get(2)), 1e-10); + KeyValue actual = jedis.bzpopmin(0, bbar, bfoo); + assertArrayEquals(bbar, (byte[]) actual.getKey()); + assertEquals(new Tuple(bc, 0.1), actual.getValue()); } @Test @@ -1532,8 +1545,8 @@ public void zdiff() { jedis.zadd("bar", 1.0, "a"); assertEquals(0, jedis.zdiff("bar1", "bar2").size()); - assertEquals(Collections.singleton("b"), jedis.zdiff("foo", "bar")); - assertEquals(Collections.singleton(new Tuple("b", 2.0d)), jedis.zdiffWithScores("foo", "bar")); + assertEquals(singletonList("b"), jedis.zdiff("foo", "bar")); + assertEquals(singletonList(new Tuple("b", 2.0d)), jedis.zdiffWithScores("foo", "bar")); // binary @@ -1542,21 +1555,21 @@ public void zdiff() { jedis.zadd(bbar, 1.0, ba); assertEquals(0, jedis.zdiff(bbar1, bbar2).size()); - Set bactual = jedis.zdiff(bfoo, bbar); + List bactual = jedis.zdiff(bfoo, bbar); assertEquals(1, bactual.size()); assertArrayEquals(bb, bactual.iterator().next()); - assertEquals(Collections.singleton(new Tuple(bb, 2.0d)), jedis.zdiffWithScores(bfoo, bbar)); + assertEquals(singletonList(new Tuple(bb, 2.0d)), jedis.zdiffWithScores(bfoo, bbar)); } @Test - public void zdiffStore() { + public void zdiffstore() { jedis.zadd("foo", 1.0, "a"); jedis.zadd("foo", 2.0, "b"); jedis.zadd("bar", 1.0, "a"); - assertEquals(0, jedis.zdiffStore("bar3", "bar1", "bar2")); - assertEquals(1, jedis.zdiffStore("bar3", "foo", "bar")); - assertEquals(Collections.singletonList("b"), jedis.zrange("bar3", 0, -1)); + assertEquals(0, jedis.zdiffstore("bar3", "bar1", "bar2")); + assertEquals(1, jedis.zdiffstore("bar3", "foo", "bar")); + assertEquals(singletonList("b"), jedis.zrange("bar3", 0, -1)); // binary @@ -1564,8 +1577,8 @@ public void zdiffStore() { jedis.zadd(bfoo, 2.0, bb); jedis.zadd(bbar, 1.0, ba); - assertEquals(0, jedis.zdiffStore(bbar3, bbar1, bbar2)); - assertEquals(1, jedis.zdiffStore(bbar3, bfoo, bbar)); + assertEquals(0, jedis.zdiffstore(bbar3, bbar1, bbar2)); + assertEquals(1, jedis.zdiffstore(bbar3, bfoo, bbar)); List bactual = jedis.zrange(bbar3, 0, -1); assertArrayEquals(bb, bactual.iterator().next()); } @@ -1582,14 +1595,12 @@ public void zrandmember() { hash.put("bar3", 0.1d); jedis.zadd("foo", hash); - assertTrue(hash.containsKey(jedis.zrandmember("foo"))); + AssertUtil.assertCollectionContains(hash.keySet(), jedis.zrandmember("foo")); assertEquals(2, jedis.zrandmember("foo", 2).size()); List actual = jedis.zrandmemberWithScores("foo", 2); - assertNotNull(actual); assertEquals(2, actual.size()); - Tuple tuple = actual.iterator().next(); - assertEquals(hash.get(tuple.getElement()), Double.valueOf(tuple.getScore())); + actual.forEach(t -> assertEquals(hash.get(t.getElement()), t.getScore(), 0d)); // Binary assertNull(jedis.zrandmember(bfoo)); @@ -1602,14 +1613,12 @@ public void zrandmember() { bhash.put(bbar3, 0.1d); jedis.zadd(bfoo, bhash); - assertCollectionContains(bhash.keySet(), jedis.zrandmember(bfoo)); + AssertUtil.assertByteArrayCollectionContains(bhash.keySet(), jedis.zrandmember(bfoo)); assertEquals(2, jedis.zrandmember(bfoo, 2).size()); List bactual = jedis.zrandmemberWithScores(bfoo, 2); - assertNotNull(bactual); assertEquals(2, bactual.size()); - tuple = bactual.iterator().next(); - assertEquals(getScoreFromByteMap(bhash, tuple.getBinaryElement()), Double.valueOf(tuple.getScore())); + bactual.forEach(t -> assertEquals(getScoreFromByteMap(bhash, t.getBinaryElement()), t.getScore(), 0d)); } private Double getScoreFromByteMap(Map bhash, byte[] key) { diff --git a/src/test/java/redis/clients/jedis/commands/unified/StringValuesCommandsTestBase.java b/src/test/java/redis/clients/jedis/commands/unified/StringValuesCommandsTestBase.java index 6f27cc03ef..a666671a15 100644 --- a/src/test/java/redis/clients/jedis/commands/unified/StringValuesCommandsTestBase.java +++ b/src/test/java/redis/clients/jedis/commands/unified/StringValuesCommandsTestBase.java @@ -3,20 +3,15 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertNull; -import static org.junit.Assume.assumeFalse; -import static redis.clients.jedis.util.RedisVersionUtil.checkRedisMajorVersionNumber; import java.util.ArrayList; import java.util.List; - import org.junit.Test; import redis.clients.jedis.params.LCSParams; import redis.clients.jedis.resps.LCSMatchResult; -import redis.clients.jedis.resps.LCSMatchResult.MatchedPosition; import redis.clients.jedis.exceptions.JedisDataException; import redis.clients.jedis.params.GetExParams; -import redis.clients.jedis.params.StrAlgoLCSParams; public abstract class StringValuesCommandsTestBase extends UnifiedJedisCommandsTestBase { @Test @@ -242,80 +237,6 @@ public void psetex() { assertTrue(ttl > 0 && ttl <= 20000); } - @Test - public void strAlgoLcsWithLen() { - assumeFalse(checkRedisMajorVersionNumber(7)); - LCSMatchResult stringMatchResult = jedis.strAlgoLCSStrings("ohmytext", "mynewtext", - StrAlgoLCSParams.StrAlgoLCSParams().len()); - assertEquals(stringMatchResult.getLen(), 6); - } - - @Test - public void strAlgoLcs() { - assumeFalse(checkRedisMajorVersionNumber(7)); - LCSMatchResult stringMatchResult = jedis.strAlgoLCSStrings("ohmytext", "mynewtext", - StrAlgoLCSParams.StrAlgoLCSParams()); - assertEquals(stringMatchResult.getMatchString(), "mytext"); - } - - @Test - public void strAlgoLcsWithIdx() { - assumeFalse(checkRedisMajorVersionNumber(7)); - LCSMatchResult stringMatchResult = jedis.strAlgoLCSStrings("ohmytext", "mynewtext", - StrAlgoLCSParams.StrAlgoLCSParams().idx().withMatchLen()); - assertEquals(stringMatchResult.getLen(), 6); - assertEquals(2, stringMatchResult.getMatches().size()); - - MatchedPosition position0 = stringMatchResult.getMatches().get(0); - assertEquals(position0.getA().getStart(), 4); - assertEquals(position0.getA().getEnd(), 7); - assertEquals(position0.getB().getStart(), 5); - assertEquals(position0.getB().getEnd(), 8); - assertEquals(position0.getMatchLen(), 4); - - MatchedPosition position1 = stringMatchResult.getMatches().get(1); - assertEquals(position1.getA().getStart(), 2); - assertEquals(position1.getA().getEnd(), 3); - assertEquals(position1.getB().getStart(), 0); - assertEquals(position1.getB().getEnd(), 1); - assertEquals(position1.getMatchLen(), 2); - } - - @Test - public void strAlgoLcsWithKey() { - assumeFalse(checkRedisMajorVersionNumber(7)); - jedis.mset("key1", "ohmytext", "key2", "mynewtext"); - - LCSMatchResult stringMatchResult = jedis.strAlgoLCSKeys("key1", "key2", - StrAlgoLCSParams.StrAlgoLCSParams()); - assertEquals("mytext", stringMatchResult.getMatchString()); - } - - @Test - public void strAlgoLcsWithKeyAndIdx() { - assumeFalse(checkRedisMajorVersionNumber(7)); - jedis.mset("key1", "ohmytext", "key2", "mynewtext"); - - LCSMatchResult stringMatchResult = jedis.strAlgoLCSKeys( "key1", "key2", - StrAlgoLCSParams.StrAlgoLCSParams().idx().withMatchLen()); - assertEquals(stringMatchResult.getLen(), 6); - assertEquals(2, stringMatchResult.getMatches().size()); - - MatchedPosition position0 = stringMatchResult.getMatches().get(0); - assertEquals(position0.getA().getStart(), 4); - assertEquals(position0.getA().getEnd(), 7); - assertEquals(position0.getB().getStart(), 5); - assertEquals(position0.getB().getEnd(), 8); - assertEquals(position0.getMatchLen(), 4); - - MatchedPosition position1 = stringMatchResult.getMatches().get(1); - assertEquals(position1.getA().getStart(), 2); - assertEquals(position1.getA().getEnd(), 3); - assertEquals(position1.getB().getStart(), 0); - assertEquals(position1.getB().getEnd(), 1); - assertEquals(position1.getMatchLen(), 2); - } - @Test public void lcs() { jedis.mset("key1", "ohmytext", "key2", "mynewtext"); diff --git a/src/test/java/redis/clients/jedis/commands/unified/cluster/ClusterSortedSetCommandsTest.java b/src/test/java/redis/clients/jedis/commands/unified/cluster/ClusterSortedSetCommandsTest.java index 8ceac12b5f..589c735959 100644 --- a/src/test/java/redis/clients/jedis/commands/unified/cluster/ClusterSortedSetCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/unified/cluster/ClusterSortedSetCommandsTest.java @@ -177,13 +177,13 @@ // // @Test // @Override -// public void zdiffStore() { +// public void zdiffstore() { // jedis.zadd("foo{:}", 1.0, "a"); // jedis.zadd("foo{:}", 2.0, "b"); // jedis.zadd("bar{:}", 1.0, "a"); // -// assertEquals(0, jedis.zdiffStore("{bar}3", "{bar}1", "{bar}2")); -// assertEquals(1, jedis.zdiffStore("bar{:}3", "foo{:}", "bar{:}")); +// assertEquals(0, jedis.zdiffstore("{bar}3", "{bar}1", "{bar}2")); +// assertEquals(1, jedis.zdiffstore("bar{:}3", "foo{:}", "bar{:}")); // assertEquals(Collections.singletonList("b"), jedis.zrange("bar{:}3", 0, -1)); // } // diff --git a/src/test/java/redis/clients/jedis/commands/unified/pooled/PooledCommandsTestHelper.java b/src/test/java/redis/clients/jedis/commands/unified/pooled/PooledCommandsTestHelper.java index 733945db5f..42a1e20b79 100644 --- a/src/test/java/redis/clients/jedis/commands/unified/pooled/PooledCommandsTestHelper.java +++ b/src/test/java/redis/clients/jedis/commands/unified/pooled/PooledCommandsTestHelper.java @@ -1,9 +1,11 @@ package redis.clients.jedis.commands.unified.pooled; +import redis.clients.jedis.DefaultJedisClientConfig; import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPooled; import redis.clients.jedis.HostAndPorts; +import redis.clients.jedis.util.RedisProtocolUtil; public class PooledCommandsTestHelper { @@ -17,7 +19,9 @@ static JedisPooled getPooled() throws InterruptedException { node.auth("foobared"); node.flushAll(); - return new JedisPooled(nodeInfo.getHost(), nodeInfo.getPort(), null, "foobared"); + //return new JedisPooled(nodeInfo.getHost(), nodeInfo.getPort(), null, "foobared"); + return new JedisPooled(nodeInfo, DefaultJedisClientConfig.builder() + .protocol(RedisProtocolUtil.getRedisProtocol()).password("foobared").build()); } static void clearData() { diff --git a/src/test/java/redis/clients/jedis/commands/unified/pooled/PooledMiscellaneousTest.java b/src/test/java/redis/clients/jedis/commands/unified/pooled/PooledMiscellaneousTest.java new file mode 100644 index 0000000000..fc917e4e47 --- /dev/null +++ b/src/test/java/redis/clients/jedis/commands/unified/pooled/PooledMiscellaneousTest.java @@ -0,0 +1,131 @@ +package redis.clients.jedis.commands.unified.pooled; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import redis.clients.jedis.JedisPooled; +import redis.clients.jedis.Pipeline; +import redis.clients.jedis.Response; +import redis.clients.jedis.AbstractTransaction; +import redis.clients.jedis.commands.unified.UnifiedJedisCommandsTestBase; +import redis.clients.jedis.exceptions.JedisDataException; + +public class PooledMiscellaneousTest extends UnifiedJedisCommandsTestBase { + + protected Pipeline pipeline; + protected AbstractTransaction transaction; + + @BeforeClass + public static void prepare() throws InterruptedException { + jedis = PooledCommandsTestHelper.getPooled(); + } + + @AfterClass + public static void cleanUp() { + jedis.close(); + } + + @Before + public void setUp() { + PooledCommandsTestHelper.clearData(); + pipeline = ((JedisPooled) jedis).pipelined(); + transaction = jedis.multi(); + } + + @After + public void tearDown() { + pipeline.close(); + transaction.close(); + } + + @Test + public void pipeline() { + final int count = 10; + int totalCount = 0; + for (int i = 0; i < count; i++) { + jedis.set("foo" + i, "bar" + i); + } + totalCount += count; + for (int i = 0; i < count; i++) { + jedis.rpush("foobar" + i, "foo" + i, "bar" + i); + } + totalCount += count; + + List> responses = new ArrayList<>(totalCount); + List expected = new ArrayList<>(totalCount); + for (int i = 0; i < count; i++) { + responses.add(pipeline.get("foo" + i)); + expected.add("bar" + i); + } + for (int i = 0; i < count; i++) { + responses.add(pipeline.lrange("foobar" + i, 0, -1)); + expected.add(Arrays.asList("foo" + i, "bar" + i)); + } + pipeline.sync(); + + for (int i = 0; i < totalCount; i++) { + assertEquals(expected.get(i), responses.get(i).get()); + } + } + + @Test + public void transaction() { + final int count = 10; + int totalCount = 0; + for (int i = 0; i < count; i++) { + jedis.set("foo" + i, "bar" + i); + } + totalCount += count; + for (int i = 0; i < count; i++) { + jedis.rpush("foobar" + i, "foo" + i, "bar" + i); + } + totalCount += count; + + List expected = new ArrayList<>(totalCount); + for (int i = 0; i < count; i++) { + transaction.get("foo" + i); + expected.add("bar" + i); + } + for (int i = 0; i < count; i++) { + transaction.lrange("foobar" + i, 0, -1); + expected.add(Arrays.asList("foo" + i, "bar" + i)); + } + + List responses = transaction.exec(); + for (int i = 0; i < totalCount; i++) { + assertEquals(expected.get(i), responses.get(i)); + } + } + + @Test + public void broadcast() { + + String script_1 = "return 'jedis'"; + String sha1_1 = jedis.scriptLoad(script_1); + + String script_2 = "return 79"; + String sha1_2 = jedis.scriptLoad(script_2); + + assertEquals(Arrays.asList(true, true), jedis.scriptExists(Arrays.asList(sha1_1, sha1_2))); + + jedis.scriptFlush(); + + assertEquals(Arrays.asList(false, false), jedis.scriptExists(Arrays.asList(sha1_1, sha1_2))); + } + + @Test + public void broadcastWithError() { + JedisDataException error = assertThrows(JedisDataException.class, + () -> jedis.functionDelete("xyz")); + assertEquals("ERR Library not found", error.getMessage()); + } +} diff --git a/src/test/java/redis/clients/jedis/commands/unified/pooled/PooledPipelinedTest.java b/src/test/java/redis/clients/jedis/commands/unified/pooled/PooledPipelinedTest.java deleted file mode 100644 index fd96efa23e..0000000000 --- a/src/test/java/redis/clients/jedis/commands/unified/pooled/PooledPipelinedTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package redis.clients.jedis.commands.unified.pooled; - -import static org.junit.Assert.assertEquals; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -import redis.clients.jedis.JedisPooled; -import redis.clients.jedis.Pipeline; -import redis.clients.jedis.Response; - -import redis.clients.jedis.commands.unified.UnifiedJedisCommandsTestBase; - -public class PooledPipelinedTest extends UnifiedJedisCommandsTestBase { - - protected Pipeline pipeline; - - @BeforeClass - public static void prepare() throws InterruptedException { - jedis = PooledCommandsTestHelper.getPooled(); - } - - @AfterClass - public static void cleanUp() { - jedis.close(); - } - - @Before - public void setUp() { - PooledCommandsTestHelper.clearData(); - pipeline = ((JedisPooled) jedis).pipelined(); - } - - @After - public void tearDown() { - pipeline.close(); - } - - @Test - public void simple() { - final int count = 10; - int totalCount = 0; - for (int i = 0; i < count; i++) { - jedis.set("foo" + i, "bar" + i); - } - totalCount += count; - for (int i = 0; i < count; i++) { - jedis.rpush("foobar" + i, "foo" + i, "bar" + i); - } - totalCount += count; - - List> responses = new ArrayList<>(totalCount); - List expected = new ArrayList<>(totalCount); - for (int i = 0; i < count; i++) { - responses.add(pipeline.get("foo" + i)); - expected.add("bar" + i); - } - for (int i = 0; i < count; i++) { - responses.add(pipeline.lrange("foobar" + i, 0, -1)); - expected.add(Arrays.asList("foo" + i, "bar" + i)); - } - pipeline.sync(); - - for (int i = 0; i < totalCount; i++) { - assertEquals(expected.get(i), responses.get(i).get()); - } - } -} diff --git a/src/test/java/redis/clients/jedis/examples/BroadcastCommandsToAllClusterNodes.java b/src/test/java/redis/clients/jedis/examples/BroadcastCommandsToAllClusterNodes.java new file mode 100644 index 0000000000..dd85f28c09 --- /dev/null +++ b/src/test/java/redis/clients/jedis/examples/BroadcastCommandsToAllClusterNodes.java @@ -0,0 +1,23 @@ +package redis.clients.jedis.examples; + +import redis.clients.jedis.HostAndPort; +import redis.clients.jedis.JedisCluster; + +/** + * When using the Open Source Redis Cluster + * API, some commands must be executed against all primary nodes. To simplify this task, Jedis + * provides an easy way to broadcast commands. + * + * For example, to update the server configuration of all nodes in the Redis Cluster, we broadcast + * the command [CONFIG SET](https://redis.io/commands/config-set/) to all nodes. + */ +public class BroadcastCommandsToAllClusterNodes { + + public static void main(String[] args) { + + HostAndPort clusterNode = new HostAndPort("127.0.0.1", 7000); + JedisCluster client = new JedisCluster(clusterNode); + + String reply = client.configSet("maxmemory", "100mb"); // reply is "OK" + } +} diff --git a/src/test/java/redis/clients/jedis/examples/GeoShapeFieldsUsageInRediSearch.java b/src/test/java/redis/clients/jedis/examples/GeoShapeFieldsUsageInRediSearch.java new file mode 100644 index 0000000000..fd309def50 --- /dev/null +++ b/src/test/java/redis/clients/jedis/examples/GeoShapeFieldsUsageInRediSearch.java @@ -0,0 +1,107 @@ +package redis.clients.jedis.examples; + +import java.util.Collections; +import org.junit.Assert; + +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.geom.GeometryFactory; +import org.locationtech.jts.geom.Polygon; +import org.locationtech.jts.io.ParseException; +import org.locationtech.jts.io.WKTReader; + +import redis.clients.jedis.HostAndPort; +import redis.clients.jedis.JedisPooled; +import redis.clients.jedis.UnifiedJedis; +import redis.clients.jedis.search.FTSearchParams; +import redis.clients.jedis.search.RediSearchUtil; +import redis.clients.jedis.search.SearchResult; +import redis.clients.jedis.search.schemafields.GeoShapeField; + +/** + * As of RediSearch 2.8.4, advanced GEO querying with GEOSHAPE fields is supported. + * + * Any object/library producing a + * well-known + * text (WKT) in {@code toString()} method can be used. + * + * This example uses the JTS library. + *
+ * {@code
+ * 
+ *   org.locationtech.jts
+ *   jts-core
+ *   1.19.0
+ * 
+ * }
+ * 
+ */ +public class GeoShapeFieldsUsageInRediSearch { + + public static void main(String[] args) { + + // We'll create geometry objects with GeometryFactory + final GeometryFactory factory = new GeometryFactory(); + + final String host = "localhost"; + final int port = 6379; + final HostAndPort address = new HostAndPort(host, port); + + UnifiedJedis client = new JedisPooled(address); + // client.setDefaultSearchDialect(3); // we can set default search dialect for the client (UnifiedJedis) object + // to avoid setting dialect in every query. + + // creating index + client.ftCreate("geometry-index", + GeoShapeField.of("geometry", GeoShapeField.CoordinateSystem.SPHERICAL) // 'SPHERICAL' is for geographic (lon, lat). + // 'FLAT' coordinate system also available for cartesian (X,Y). + ); + + // preparing data + final Polygon small = factory.createPolygon( + new Coordinate[]{new Coordinate(34.9001, 29.7001), + new Coordinate(34.9001, 29.7100), new Coordinate(34.9100, 29.7100), + new Coordinate(34.9100, 29.7001), new Coordinate(34.9001, 29.7001)} + ); + + // client.hset("small", RediSearchUtil.toStringMap(Collections.singletonMap("geometry", small))); // setting data + client.hset("small", "geometry", small.toString()); // simplified setting data + + final Polygon large = factory.createPolygon( + new Coordinate[]{new Coordinate(34.9001, 29.7001), + new Coordinate(34.9001, 29.7200), new Coordinate(34.9200, 29.7200), + new Coordinate(34.9200, 29.7001), new Coordinate(34.9001, 29.7001)} + ); + + // client.hset("large", RediSearchUtil.toStringMap(Collections.singletonMap("geometry", large))); // setting data + client.hset("large", "geometry", large.toString()); // simplified setting data + + // searching + final Polygon within = factory.createPolygon( + new Coordinate[]{new Coordinate(34.9000, 29.7000), + new Coordinate(34.9000, 29.7150), new Coordinate(34.9150, 29.7150), + new Coordinate(34.9150, 29.7000), new Coordinate(34.9000, 29.7000)} + ); + + SearchResult res = client.ftSearch("geometry-index", + "@geometry:[within $poly]", // querying 'within' condition. + // RediSearch also supports 'contains' condition. + FTSearchParams.searchParams() + .addParam("poly", within) + .dialect(3) // DIALECT '3' is required for this query + ); + Assert.assertEquals(1, res.getTotalResults()); + Assert.assertEquals(1, res.getDocuments().size()); + + // We can parse geometry objects with WKTReader + try { + final WKTReader reader = new WKTReader(); + Geometry object = reader.read(res.getDocuments().get(0).getString("geometry")); + Assert.assertEquals(small, object); + } catch (ParseException ex) { + ex.printStackTrace(System.err); + } + } + + // Note: As of RediSearch 2.8.4, only POLYGON and POINT objects are supported. +} diff --git a/src/test/java/redis/clients/jedis/examples/RedisCredentialsProviderUsage.java b/src/test/java/redis/clients/jedis/examples/RedisCredentialsProviderUsage.java new file mode 100644 index 0000000000..b0de49403a --- /dev/null +++ b/src/test/java/redis/clients/jedis/examples/RedisCredentialsProviderUsage.java @@ -0,0 +1,44 @@ +package redis.clients.jedis.examples; + +import redis.clients.jedis.DefaultJedisClientConfig; +import redis.clients.jedis.DefaultRedisCredentials; +import redis.clients.jedis.DefaultRedisCredentialsProvider; +import redis.clients.jedis.HostAndPort; +import redis.clients.jedis.JedisPooled; + +public class RedisCredentialsProviderUsage { + + public static void main(String[] args) { + + DefaultRedisCredentials initialCredentials + = new DefaultRedisCredentials("", ""); + + DefaultRedisCredentialsProvider credentialsProvider + = new DefaultRedisCredentialsProvider(initialCredentials); + + final String host = ""; + final int port = 6379; + final HostAndPort address = new HostAndPort(host, port); + final DefaultJedisClientConfig clientConfig + = DefaultJedisClientConfig.builder() + .credentialsProvider(credentialsProvider).build(); + + JedisPooled jedis = new JedisPooled(address, clientConfig); + + // ... + // do operations with jedis + // ... + + // when credentials is required to be updated + DefaultRedisCredentials updatedCredentials + = new DefaultRedisCredentials("", ""); + + credentialsProvider.setCredentials(updatedCredentials); + + // ... + // continue doing operations with jedis + // ... + + jedis.close(); + } +} diff --git a/src/test/java/redis/clients/jedis/exceptions/ExceptionsTest.java b/src/test/java/redis/clients/jedis/exceptions/ExceptionsTest.java index 9bdd77371b..4b1bef38fe 100644 --- a/src/test/java/redis/clients/jedis/exceptions/ExceptionsTest.java +++ b/src/test/java/redis/clients/jedis/exceptions/ExceptionsTest.java @@ -19,33 +19,6 @@ public static void prepare() { CAUSE = new Throwable("This is a test cause."); } - @Test - public void abortedTransaction() { - try { - throw new AbortedTransactionException(MESSAGE); - } catch (Exception e) { - assertSame(AbortedTransactionException.class, e.getClass()); - assertEquals(MESSAGE, e.getMessage()); - assertNull(e.getCause()); - } - - try { - throw new AbortedTransactionException(CAUSE); - } catch (Exception e) { - assertSame(AbortedTransactionException.class, e.getClass()); - assertEquals(CAUSE, e.getCause()); - assertEquals(CAUSE.toString(), e.getMessage()); - } - - try { - throw new AbortedTransactionException(MESSAGE, CAUSE); - } catch (Exception e) { - assertSame(AbortedTransactionException.class, e.getClass()); - assertEquals(MESSAGE, e.getMessage()); - assertEquals(CAUSE, e.getCause()); - } - } - @Test public void invalidURI() { try { diff --git a/src/test/java/redis/clients/jedis/misc/AutomaticFailoverTest.java b/src/test/java/redis/clients/jedis/misc/AutomaticFailoverTest.java new file mode 100644 index 0000000000..4f8f896afc --- /dev/null +++ b/src/test/java/redis/clients/jedis/misc/AutomaticFailoverTest.java @@ -0,0 +1,84 @@ +package redis.clients.jedis.misc; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import redis.clients.jedis.AbstractPipeline; +import redis.clients.jedis.AbstractTransaction; +import redis.clients.jedis.DefaultJedisClientConfig; +import redis.clients.jedis.HostAndPort; +import redis.clients.jedis.HostAndPorts; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisClientConfig; +import redis.clients.jedis.MultiClusterClientConfig; +import redis.clients.jedis.UnifiedJedis; +import redis.clients.jedis.providers.MultiClusterPooledConnectionProvider; + +public class AutomaticFailoverTest { + + private final HostAndPort hostAndPort1 = HostAndPorts.getRedisServers().get(0); + private final HostAndPort hostAndPort2 = HostAndPorts.getRedisServers().get(1); + + private final JedisClientConfig clientConfig = DefaultJedisClientConfig.builder().password("foobared").build(); + + private Jedis jedis1; + private Jedis jedis2; + + private MultiClusterPooledConnectionProvider provider; + + @Before + public void setUp() { + + MultiClusterClientConfig.ClusterConfig[] clusterConfigs = new MultiClusterClientConfig.ClusterConfig[2]; + clusterConfigs[0] = new MultiClusterClientConfig.ClusterConfig(hostAndPort1, clientConfig); + clusterConfigs[1] = new MultiClusterClientConfig.ClusterConfig(hostAndPort2, clientConfig); + + provider = new MultiClusterPooledConnectionProvider(new MultiClusterClientConfig.Builder(clusterConfigs).build()); + + jedis1 = new Jedis(hostAndPort1, clientConfig); + jedis1.flushAll(); + jedis2 = new Jedis(hostAndPort2, clientConfig); + jedis2.flushAll(); + } + + @After + public void cleanUp() { + + provider.close(); + + jedis1.close(); + jedis2.close(); + } + + @Test + public void pipelineWithSwitch() { + try (UnifiedJedis client = new UnifiedJedis(provider)) { + AbstractPipeline pipe = client.pipelined(); + pipe.set("pstr", "foobar"); + pipe.hset("phash", "foo", "bar"); + provider.incrementActiveMultiClusterIndex(); + pipe.sync(); + } + + assertEquals("foobar", jedis2.get("pstr")); + assertEquals("bar", jedis2.hget("phash", "foo")); + } + + @Test + public void transactionWithSwitch() { + try (UnifiedJedis client = new UnifiedJedis(provider)) { + AbstractTransaction tx = client.multi(); + tx.set("tstr", "foobar"); + tx.hset("thash", "foo", "bar"); + provider.incrementActiveMultiClusterIndex(); + assertEquals(Arrays.asList("OK", Long.valueOf(1L)), tx.exec()); + } + + assertEquals("foobar", jedis2.get("tstr")); + assertEquals("bar", jedis2.hget("thash", "foo")); + } +} diff --git a/src/test/java/redis/clients/jedis/misc/ClientSetInfoConfigTest.java b/src/test/java/redis/clients/jedis/misc/ClientSetInfoConfigTest.java new file mode 100644 index 0000000000..8b85f70252 --- /dev/null +++ b/src/test/java/redis/clients/jedis/misc/ClientSetInfoConfigTest.java @@ -0,0 +1,26 @@ +package redis.clients.jedis.misc; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; + +import java.util.Arrays; +import org.junit.Test; + +import redis.clients.jedis.ClientSetInfoConfig; +import redis.clients.jedis.exceptions.JedisValidationException; + +public class ClientSetInfoConfigTest { + + @Test + public void replaceSpacesWithHyphens() { + assertEquals("Redis-Java-client", + ClientSetInfoConfig.withLibNameSuffix("Redis Java client").getLibNameSuffix()); + } + + @Test + public void errorForBraces() { + Arrays.asList('(', ')', '[', ']', '{', '}') + .forEach(brace -> assertThrows(JedisValidationException.class, + () -> ClientSetInfoConfig.withLibNameSuffix("" + brace))); + } +} diff --git a/src/test/java/redis/clients/jedis/misc/ClusterInitErrorTest.java b/src/test/java/redis/clients/jedis/misc/ClusterInitErrorTest.java new file mode 100644 index 0000000000..619c08cead --- /dev/null +++ b/src/test/java/redis/clients/jedis/misc/ClusterInitErrorTest.java @@ -0,0 +1,40 @@ +package redis.clients.jedis.misc; + +import java.util.Collections; +import org.junit.After; +import org.junit.Assert; +import org.junit.Test; +import redis.clients.jedis.DefaultJedisClientConfig; +import redis.clients.jedis.HostAndPorts; +import redis.clients.jedis.JedisCluster; +import redis.clients.jedis.exceptions.JedisClusterOperationException; + +public class ClusterInitErrorTest { + + private static final String INIT_NO_ERROR_PROPERTY = "jedis.cluster.initNoError"; + + @After + public void cleanUp() { + System.getProperties().remove(INIT_NO_ERROR_PROPERTY); + } + + @Test(expected = JedisClusterOperationException.class) + public void initError() { + Assert.assertNull(System.getProperty(INIT_NO_ERROR_PROPERTY)); + try (JedisCluster cluster = new JedisCluster( + Collections.singleton(HostAndPorts.getRedisServers().get(0)), + DefaultJedisClientConfig.builder().password("foobared").build())) { + throw new IllegalStateException("should not reach here"); + } + } + + @Test + public void initNoError() { + System.setProperty(INIT_NO_ERROR_PROPERTY, ""); + try (JedisCluster cluster = new JedisCluster( + Collections.singleton(HostAndPorts.getRedisServers().get(0)), + DefaultJedisClientConfig.builder().password("foobared").build())) { + Assert.assertThrows(JedisClusterOperationException.class, () -> cluster.get("foo")); + } + } +} diff --git a/src/test/java/redis/clients/jedis/misc/ParamsTest.java b/src/test/java/redis/clients/jedis/misc/ParamsTest.java new file mode 100644 index 0000000000..b23e87dfd7 --- /dev/null +++ b/src/test/java/redis/clients/jedis/misc/ParamsTest.java @@ -0,0 +1,26 @@ +//package redis.clients.jedis.misc; +// +//import static org.hamcrest.CoreMatchers.containsString; +//import static org.hamcrest.MatcherAssert.assertThat; +// +//import org.junit.Test; +//import redis.clients.jedis.args.ClientType; +//import redis.clients.jedis.params.ClientKillParams; +// +//public class ParamsTest { +// +// @Test +// public void toStringTest() { +// +// ClientKillParams clientKillParams = ClientKillParams.clientKillParams() +// .addr("127.0.0.1", 6379) +// .id("12".getBytes()) +// .type(ClientType.NORMAL); +// +// String toStringResult = clientKillParams.toString(); +// assertThat(toStringResult, containsString("ID, 12")); +// assertThat(toStringResult, containsString("TYPE, NORMAL")); +// assertThat(toStringResult, containsString("127.0.0.1:6379")); +// } +// +//} diff --git a/src/test/java/redis/clients/jedis/misc/ResponsesToStringTest.java b/src/test/java/redis/clients/jedis/misc/ResponsesToStringTest.java new file mode 100644 index 0000000000..b5d072e250 --- /dev/null +++ b/src/test/java/redis/clients/jedis/misc/ResponsesToStringTest.java @@ -0,0 +1,30 @@ +package redis.clients.jedis.misc; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +import org.junit.Test; +import redis.clients.jedis.GeoCoordinate; +import redis.clients.jedis.resps.GeoRadiusResponse; + +public class ResponsesToStringTest { + + @Test + public void GeoRadiusResponse() { + byte[] member = {0x01, 0x02, 0x03, 0x04}; + + GeoRadiusResponse response = new GeoRadiusResponse(member); + response.setDistance(5); + response.setCoordinate(new GeoCoordinate(2, 3)); + response.setRawScore(10); + + GeoRadiusResponse response_copy = new GeoRadiusResponse(member); + response_copy.setDistance(5); + response_copy.setCoordinate(new GeoCoordinate(2, 3)); + response_copy.setRawScore(10); + + assertEquals(response, response); + assertEquals(response, response_copy); + assertNotEquals(response, new Object()); + } +} diff --git a/src/test/java/redis/clients/jedis/resps/TupleTest.java b/src/test/java/redis/clients/jedis/misc/TupleTest.java similarity index 56% rename from src/test/java/redis/clients/jedis/resps/TupleTest.java rename to src/test/java/redis/clients/jedis/misc/TupleTest.java index b8ed14a816..4983b8044e 100644 --- a/src/test/java/redis/clients/jedis/resps/TupleTest.java +++ b/src/test/java/redis/clients/jedis/misc/TupleTest.java @@ -1,17 +1,23 @@ -package redis.clients.jedis.resps; +package redis.clients.jedis.misc; -import java.util.HashSet; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; -import org.hamcrest.CoreMatchers; +import java.util.HashSet; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; import org.junit.Test; - import redis.clients.jedis.resps.Tuple; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.*; - public class TupleTest { + @Test + public void compareSameObject() { + Tuple t1 = new Tuple("foo", 1d); + assertTrue(t1.equals(t1)); + } + @Test public void compareEqual() { Tuple t1 = new Tuple("foo", 1d); @@ -19,8 +25,8 @@ public void compareEqual() { assertEquals(0, t1.compareTo(t2)); assertEquals(0, t2.compareTo(t1)); - assertEquals(t1, t2); // directly calling Tuple.equals() - assertEquals(t2, t1); // directly calling Tuple.equals() + assertTrue(t1.equals(t2)); + assertTrue(t2.equals(t1)); } @Test @@ -30,8 +36,8 @@ public void compareSameScore() { assertEquals(1, t1.compareTo(t2)); assertEquals(-1, t2.compareTo(t1)); - assertNotEquals(t1, t2); // directly calling Tuple.equals() - assertNotEquals(t2, t1); // directly calling Tuple.equals() + assertFalse(t1.equals(t2)); + assertFalse(t2.equals(t1)); } @Test @@ -42,8 +48,8 @@ public void compareSameScoreObject() { assertEquals(1, t1.compareTo(t2)); assertEquals(-1, t2.compareTo(t1)); - assertNotEquals(t1, t2); // directly calling Tuple.equals() - assertNotEquals(t2, t1); // directly calling Tuple.equals() + assertFalse(t1.equals(t2)); + assertFalse(t2.equals(t1)); } @Test @@ -53,30 +59,27 @@ public void compareNoMatch() { assertEquals(-1, t1.compareTo(t2)); assertEquals(1, t2.compareTo(t1)); - assertNotEquals(t1, t2); // directly calling Tuple.equals() - assertNotEquals(t2, t1); // directly calling Tuple.equals() - } - - @Test - public void compareSameObject() { - Tuple t1 = new Tuple("foo", 1d); - assertEquals(t1, t1); // directly calling Tuple.equals() + assertFalse(t1.equals(t2)); + assertFalse(t2.equals(t1)); } @Test public void compareDifferentType() { Tuple t1 = new Tuple("foo", 1d); - assertNotEquals(t1, new Object()); // directly calling Tuple.equals() - assertNotEquals(t1, null); // directly calling Tuple.equals() + + Object anyObject = new Object(); + assertFalse(t1.equals(anyObject)); + + Object nullObject = null; + assertFalse(t1.equals(nullObject)); } @Test public void testToString() { Tuple t1 = new Tuple("key-name", 1d); String toStringResult = t1.toString(); - - assertThat(toStringResult, CoreMatchers.containsString("key-name")); - assertThat(toStringResult, CoreMatchers.containsString("1")); + MatcherAssert.assertThat(toStringResult, Matchers.containsString("key-name")); + MatcherAssert.assertThat(toStringResult, Matchers.containsString("1")); } @Test @@ -85,10 +88,10 @@ public void testSameElement() { Tuple t2 = new Tuple("user1", 5.0); // Intentionally skipping compareTo. - assertNotEquals(t1, t2); // directly calling Tuple.equals() - assertNotEquals(t2, t1); // directly calling Tuple.equals() + assertFalse(t1.equals(t2)); + assertFalse(t2.equals(t1)); - HashSet hashSet = new HashSet(); + HashSet hashSet = new HashSet<>(); hashSet.add(t1); hashSet.add(t2); assertEquals(2, hashSet.size()); diff --git a/src/test/java/redis/clients/jedis/modules/RedisModuleCommandsTestBase.java b/src/test/java/redis/clients/jedis/modules/RedisModuleCommandsTestBase.java index 52c07e155e..20bbe9ae92 100644 --- a/src/test/java/redis/clients/jedis/modules/RedisModuleCommandsTestBase.java +++ b/src/test/java/redis/clients/jedis/modules/RedisModuleCommandsTestBase.java @@ -6,16 +6,20 @@ import org.junit.Before; import redis.clients.jedis.Connection; +import redis.clients.jedis.DefaultJedisClientConfig; import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; import redis.clients.jedis.Protocol; +import redis.clients.jedis.RedisProtocol; import redis.clients.jedis.UnifiedJedis; import redis.clients.jedis.exceptions.JedisConnectionException; +import redis.clients.jedis.util.RedisProtocolUtil; public abstract class RedisModuleCommandsTestBase { - protected static final String address = System.getProperty("modulesDocker", Protocol.DEFAULT_HOST + ':' + 6479); + private static final String address = System.getProperty("modulesDocker", Protocol.DEFAULT_HOST + ':' + 6479); protected static final HostAndPort hnp = HostAndPort.from(address); + protected final RedisProtocol protocol = RedisProtocolUtil.getRedisProtocol(); protected UnifiedJedis client; @@ -37,7 +41,7 @@ public void setUp() { try (Jedis jedis = new Jedis(hnp)) { jedis.flushAll(); } - client = new UnifiedJedis(hnp); + client = new UnifiedJedis(hnp, DefaultJedisClientConfig.builder().protocol(protocol).build()); } @After @@ -48,8 +52,8 @@ public void tearDown() throws Exception { // public static void tearDown() { // client.close(); // } - - protected static Connection createConnection() { - return new Connection(hnp); - } +// +// protected static Connection createConnection() { +// return new Connection(hnp); +// } } diff --git a/src/test/java/redis/clients/jedis/modules/RedisModulesPipelineTest.java b/src/test/java/redis/clients/jedis/modules/RedisModulesPipelineTest.java index 446329488e..50b48854da 100644 --- a/src/test/java/redis/clients/jedis/modules/RedisModulesPipelineTest.java +++ b/src/test/java/redis/clients/jedis/modules/RedisModulesPipelineTest.java @@ -14,17 +14,19 @@ import java.util.Collections; import org.json.JSONArray; import org.json.JSONObject; +import org.junit.Assume; import org.junit.BeforeClass; import org.junit.Test; -import redis.clients.jedis.Connection; import redis.clients.jedis.Pipeline; +import redis.clients.jedis.RedisProtocol; import redis.clients.jedis.Response; import redis.clients.jedis.json.JsonSetParams; import redis.clients.jedis.json.Path; import redis.clients.jedis.json.Path2; import redis.clients.jedis.search.*; import redis.clients.jedis.search.aggr.*; +import redis.clients.jedis.util.RedisProtocolUtil; public class RedisModulesPipelineTest extends RedisModuleCommandsTestBase { @@ -44,54 +46,44 @@ public void search() { fields.put("title", "hello world"); fields.put("body", "lorem ipsum"); - Connection c = createConnection(); - Pipeline p = new Pipeline(c); +// Connection c = createConnection(); +// Pipeline p = new Pipeline(c); + Pipeline p = (Pipeline) client.pipelined(); Response create = p.ftCreate(index, IndexOptions.defaultOptions(), sc); Response alter = p.ftAlter(index, new Schema().addTextField("foo", 1.0)); p.hset("doc1", toStringMap(fields)); p.hset("doc2", toStringMap(fields)); Response searchResult = p.ftSearch(index, new Query("hello world")); - Response searchBytesResult = p.ftSearch(index.getBytes(), new Query("hello world")); +// Response searchBytesResult = p.ftSearch(index.getBytes(), new Query("hello world")); // not RESP3 supported Response aggregateResult = p.ftAggregate(index, new AggregationBuilder().groupBy("@title")); Response explain = p.ftExplain(index, new Query("@title:title_val")); Response> explainCLI = p.ftExplainCLI(index, new Query("@title:title_val")); Response> info = p.ftInfo(index); - Response aliasAdd = p.ftAliasAdd("ALIAS1", index); - Response aliasUpdate = p.ftAliasUpdate("ALIAS2", index); - Response aliasDel = p.ftAliasDel("ALIAS2"); Response configSet = p.ftConfigSet("timeout", "100"); - Response> configGet = p.ftConfigGet("*"); + Response> configGet = p.ftConfigGet("*"); Response configSetIndex = p.ftConfigSet(index, "timeout", "100"); - Response> configGetIndex = p.ftConfigGet(index, "*"); + Response> configGetIndex = p.ftConfigGet(index, "*"); Response synUpdate = p.ftSynUpdate(index, "foo", "bar"); Response>> synDump = p.ftSynDump(index); - Response dropIndex = p.ftDropIndex(index); - p.ftCreate(index, IndexOptions.defaultOptions(), sc); - Response dropIndexDD = p.ftDropIndexDD(index); p.sync(); - c.close(); +// c.close(); assertEquals("OK", create.get()); assertEquals("OK", alter.get()); assertEquals("OK", alter.get()); assertEquals(2, searchResult.get().getTotalResults()); - assertEquals(2, searchBytesResult.get().getTotalResults()); - assertEquals(1, aggregateResult.get().totalResults); +// assertEquals(2, searchBytesResult.get().getTotalResults()); + assertEquals(1, aggregateResult.get().getTotalResults()); assertNotNull(explain.get()); assertNotNull(explainCLI.get().get(0)); assertEquals(index, info.get().get("index_name")); - assertEquals("OK", aliasAdd.get()); - assertEquals("OK", aliasUpdate.get()); - assertEquals("OK", aliasDel.get()); assertEquals("OK", configSet.get()); assertEquals("100", configGet.get().get("TIMEOUT")); assertEquals("OK", configSetIndex.get()); assertEquals("100", configGetIndex.get().get("TIMEOUT")); assertEquals("OK", synUpdate.get()); - assertEquals("OK", dropIndex.get()); - assertEquals("OK", dropIndexDD.get()); Map> expected = new HashMap<>(); expected.put("bar", Collections.singletonList("foo")); assertEquals(expected, synDump.get()); @@ -99,6 +91,8 @@ public void search() { @Test public void jsonV1() { + Assume.assumeFalse(RedisProtocolUtil.getRedisProtocol() == RedisProtocol.RESP3); + Map hm1 = new HashMap<>(); hm1.put("hello", "world"); hm1.put("oh", "snap"); @@ -112,8 +106,9 @@ public void jsonV1() { Baz baz2 = new Baz("quuz2", "grault2", "waldo2"); Baz baz3 = new Baz("quuz3", "grault3", "waldo3"); - Connection c = createConnection(); - Pipeline p = new Pipeline(c); +// Connection c = createConnection(); +// Pipeline p = new Pipeline(c); + Pipeline p = (Pipeline) client.pipelined(); Response set1 = p.jsonSet("foo", Path.ROOT_PATH, hm1); Response get = p.jsonGet("foo"); @@ -153,7 +148,7 @@ public void jsonV1() { Response popClassWithIndex = p.jsonArrPop("baz", Baz.class, Path.ROOT_PATH, 0); p.sync(); - c.close(); +// c.close(); assertEquals("OK", set1.get()); assertEquals(hm1, get.get()); @@ -201,8 +196,9 @@ public void jsonV2() { hm2.put("boolean", true); hm2.put("number", 3); - Connection c = createConnection(); - Pipeline p = new Pipeline(c); +// Connection c = createConnection(); +// Pipeline p = new Pipeline(c); + Pipeline p = (Pipeline) client.pipelined(); Response setWithEscape = p.jsonSetWithEscape("foo", Path2.ROOT_PATH, hm1); Response get = p.jsonGet("foo", Path2.ROOT_PATH); @@ -228,7 +224,7 @@ public void jsonV2() { Response clear = p.jsonClear("foo", new Path2("array")); p.sync(); - c.close(); +// c.close(); assertEquals("OK", setWithEscape.get()); assertNotNull(get.get()); diff --git a/src/test/java/redis/clients/jedis/modules/bloom/TopKTest.java b/src/test/java/redis/clients/jedis/modules/bloom/TopKTest.java index 4b54d4f7f8..706d57ef82 100644 --- a/src/test/java/redis/clients/jedis/modules/bloom/TopKTest.java +++ b/src/test/java/redis/clients/jedis/modules/bloom/TopKTest.java @@ -1,10 +1,11 @@ package redis.clients.jedis.modules.bloom; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.util.Arrays; import java.util.Collections; -import java.util.TreeSet; +import java.util.Map; import org.junit.BeforeClass; import org.junit.Test; @@ -30,14 +31,20 @@ public void createTopKFilter() { assertEquals(Arrays.asList(true, false, true), client.topkQuery("aaa", "bb", "gg", "cc")); - assertEquals(Arrays.asList(1L, 0L, 1L), client.topkCount("aaa", "bb", "gg", "cc")); + assertEquals(Arrays.asList("bb", "cc"), client.topkList("aaa")); - assertEquals(new TreeSet<>(Arrays.asList("bb", "cc")), new TreeSet<>(client.topkList("aaa"))); + Map listWithCount = client.topkListWithCount("aaa"); + assertEquals(2, listWithCount.size()); + listWithCount.forEach((item, count) -> { + assertTrue(Arrays.asList("bb", "cc").contains(item)); + assertEquals(Long.valueOf(1), count); + }); -// assertEquals(null, client.topkIncrBy("aaa", "ff", 10)); - assertEquals(Collections.singletonList(null), - client.topkIncrBy("aaa", Collections.singletonMap("ff", 10L))); + assertEquals(null, client.topkIncrBy("aaa", "ff", 5)); + assertEquals(Arrays.asList("ff", "bb", "cc"), client.topkList("aaa")); - assertEquals(new TreeSet<>(Arrays.asList("bb", "cc", "ff")), new TreeSet<>(client.topkList("aaa"))); + assertEquals(Collections.singletonList(null), + client.topkIncrBy("aaa", Collections.singletonMap("ff", 8L))); + assertEquals(Long.valueOf(13), client.topkListWithCount("aaa").get("ff")); } } diff --git a/src/test/java/redis/clients/jedis/modules/gears/GearsTest.java b/src/test/java/redis/clients/jedis/modules/gears/GearsTest.java new file mode 100644 index 0000000000..e4dc10a82d --- /dev/null +++ b/src/test/java/redis/clients/jedis/modules/gears/GearsTest.java @@ -0,0 +1,527 @@ +package redis.clients.jedis.modules.gears; + +import org.hamcrest.Matchers; +import org.junit.After; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import redis.clients.jedis.RedisProtocol; +import redis.clients.jedis.exceptions.JedisDataException; +import redis.clients.jedis.gears.TFunctionListParams; +import redis.clients.jedis.gears.TFunctionLoadParams; +import redis.clients.jedis.modules.RedisModuleCommandsTestBase; +import redis.clients.jedis.gears.resps.GearsLibraryInfo; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +public class GearsTest extends RedisModuleCommandsTestBase { + + private static final String BAD_FUNCTION = "All Your Base Are Belong to Us"; + + private static final String[] LIBRARIES_ARRAY = new String[]{ + "streamTriggers", "withFlags", "pingpong", "keyspaceTriggers", "hashitout", "withConfig"}; + + @BeforeClass + public static void prepare() { + RedisModuleCommandsTestBase.prepare(); + } + + @After + @Override + public void tearDown() throws Exception { + deleteFunctions(); // delete functions before closing connections + super.tearDown(); + } + + protected void deleteFunctions() { + List libraries = client.tFunctionList(); + libraries.stream().map(GearsLibraryInfo::getName).forEach(library -> client.tFunctionDelete(library)); + } + + @Test + public void testFunctionLoad() throws IOException { + client.tFunctionLoad(readLibrary("pingpong.js")); + + List libraries = client.tFunctionList(); + assertEquals(Collections.singletonList("pingpong"), + libraries.stream().map(GearsLibraryInfo::getName).collect(Collectors.toList())); + } + + @Test(expected = JedisDataException.class) + public void testFunctionLoadAlreadyLoadedFails() throws IOException { + client.tFunctionLoad(readLibrary("pingpong.js")); + client.tFunctionLoad(readLibrary("pingpong.js")); + } + + @Test + public void testFunctionLoadWithReplace() throws IOException { + client.tFunctionLoad(readLibrary("pingpong.js")); + client.tFunctionLoad(readLibrary("pingpong.js"), TFunctionLoadParams.loadParams().replace()); + + List libraries = client.tFunctionList(); + assertEquals(Collections.singletonList("pingpong"), + libraries.stream().map(GearsLibraryInfo::getName).collect(Collectors.toList())); + } + + @Test(expected = JedisDataException.class) + public void testBadFunctionLoad() { + client.tFunctionLoad(BAD_FUNCTION); + } + + private static void assertAllLibrariesNoCode(List libraryInfos) { + assertThat(libraryInfos, Matchers.hasSize(LIBRARIES_ARRAY.length)); + + List libraryNames = libraryInfos.stream().map(GearsLibraryInfo::getName).collect(Collectors.toList()); + assertThat(libraryNames, Matchers.containsInAnyOrder(LIBRARIES_ARRAY)); + + libraryInfos.stream().map(GearsLibraryInfo::getCode).forEach(Assert::assertNull); + } + + private static void assertAllLibrariesWithCode(List libraryInfos) { + assertThat(libraryInfos, Matchers.hasSize(LIBRARIES_ARRAY.length)); + + List libraryNames = libraryInfos.stream().map(GearsLibraryInfo::getName).collect(Collectors.toList()); + assertThat(libraryNames, Matchers.containsInAnyOrder(LIBRARIES_ARRAY)); + + libraryInfos.stream().map(GearsLibraryInfo::getCode).forEach(Assert::assertNotNull); + } + + @Test + public void tFunctionListAll() throws IOException { + loadAllLibraries(); + + List libraryInfos = client.tFunctionList(); + assertAllLibrariesNoCode(libraryInfos); + } + + @Test + public void testFunctionListNoCodeVerboseZero() throws IOException { + loadAllLibraries(); + List libraryInfos = client.tFunctionList(TFunctionListParams.listParams().verbose(0)); + assertAllLibrariesNoCode(libraryInfos); + + Map>> libraryConditions = initializeTestLibraryConditions(); + + libraryConditions.get("streamTriggers").add(lib -> lib.getStreamTriggers().stream().anyMatch(trigger -> "consumer".equalsIgnoreCase(trigger.getName()))); + libraryConditions.get("withFlags").add(lib -> lib.getFunctions().stream().anyMatch(func -> "my_set".equalsIgnoreCase(func.getName()))); + libraryConditions.get("pingpong").add(lib -> lib.getFunctions().stream().anyMatch(func -> "playPingPong".equalsIgnoreCase(func.getName()))); + libraryConditions.get("keyspaceTriggers").add(lib -> lib.getKeyspaceTriggers().stream().anyMatch(trigger -> "consumer".equalsIgnoreCase(trigger.getName()))); + libraryConditions.get("hashitout").add(lib -> lib.getFunctions().stream().anyMatch(func -> "hashy".equalsIgnoreCase(func.getName()))); + libraryConditions.get("withConfig").add(lib -> lib.getFunctions().stream().anyMatch(func -> "hset".equalsIgnoreCase(func.getName()))); + + for (GearsLibraryInfo libraryInfo : libraryInfos) { + List> conditions = libraryConditions.get(libraryInfo.getName()); + if (conditions != null && !conditions.isEmpty()) { + conditions.forEach(c -> c.test(libraryInfo)); + } + } + } + + @Test + public void testFunctionListNoCodeVerboseOne() throws IOException { + loadAllLibraries(); + List libraryInfos = client.tFunctionList(TFunctionListParams.listParams().verbose(1)); + assertAllLibrariesNoCode(libraryInfos); + + Map>> libraryConditions = initializeTestLibraryConditions(); + + libraryConditions.get("streamTriggers").add(lib -> lib.getStreamTriggers().stream().anyMatch(trigger -> "consumer".equalsIgnoreCase(trigger.getName()))); + libraryConditions.get("streamTriggers").add(lib -> lib.getStreamTriggers().stream().anyMatch(trigger -> "stream".equalsIgnoreCase(trigger.getPrefix()))); + libraryConditions.get("withFlags").add(lib -> lib.getFunctions().stream().anyMatch(func -> "my_set".equalsIgnoreCase(func.getName()))); + libraryConditions.get("withFlags").add(lib -> lib.getFunctions().stream().anyMatch(func -> func.getFlags().contains("raw-arguments"))); + libraryConditions.get("pingpong").add(lib -> lib.getFunctions().stream().anyMatch(func -> "playPingPong".equalsIgnoreCase(func.getName()))); + libraryConditions.get("keyspaceTriggers").add(lib -> lib.getKeyspaceTriggers().stream().anyMatch(trigger -> "consumer".equalsIgnoreCase(trigger.getName()))); + libraryConditions.get("hashitout").add(lib -> lib.getFunctions().stream().anyMatch(func -> "hashy".equalsIgnoreCase(func.getName()))); + libraryConditions.get("withConfig").add(lib -> lib.getFunctions().stream().anyMatch(func -> "hset".equalsIgnoreCase(func.getName()))); + + for (GearsLibraryInfo libraryInfo : libraryInfos) { + List> conditions = libraryConditions.get(libraryInfo.getName()); + if (conditions != null && !conditions.isEmpty()) { + conditions.forEach(c -> c.test(libraryInfo)); + } + } + } + + @Test + public void testFunctionListNoCodeVerboseTwo() throws IOException { + loadAllLibraries(); + List libraryInfos = client.tFunctionList(TFunctionListParams.listParams().verbose(2)); + assertAllLibrariesNoCode(libraryInfos); + + Map>> libraryConditions = initializeTestLibraryConditions(); + + libraryConditions.get("streamTriggers").add(lib -> lib.getStreamTriggers().stream().anyMatch(trigger -> "consumer".equalsIgnoreCase(trigger.getName()))); + libraryConditions.get("streamTriggers").add(lib -> lib.getStreamTriggers().stream().anyMatch(trigger -> "stream".equalsIgnoreCase(trigger.getPrefix()))); + libraryConditions.get("withFlags").add(lib -> lib.getFunctions().stream().anyMatch(func -> "my_set".equalsIgnoreCase(func.getName()))); + libraryConditions.get("withFlags").add(lib -> lib.getFunctions().stream().anyMatch(func -> func.getFlags().contains("raw-arguments"))); + libraryConditions.get("pingpong").add(lib -> lib.getFunctions().stream().anyMatch(func -> "playPingPong".equalsIgnoreCase(func.getName()))); + libraryConditions.get("keyspaceTriggers").add(lib -> lib.getKeyspaceTriggers().stream().anyMatch(trigger -> "consumer".equalsIgnoreCase(trigger.getName()))); + libraryConditions.get("hashitout").add(lib -> lib.getFunctions().stream().anyMatch(func -> "hashy".equalsIgnoreCase(func.getName()))); + libraryConditions.get("withConfig").add(lib -> lib.getFunctions().stream().anyMatch(func -> "hset".equalsIgnoreCase(func.getName()))); + + for (GearsLibraryInfo libraryInfo : libraryInfos) { + List> conditions = libraryConditions.get(libraryInfo.getName()); + if (conditions != null && !conditions.isEmpty()) { + conditions.forEach(c -> c.test(libraryInfo)); + } + } + } + + @Test + public void testFunctionListNoCodeVerboseThree() throws IOException { + loadAllLibraries(); + List libraryInfos = client.tFunctionList(TFunctionListParams.listParams().verbose(3)); + assertAllLibrariesNoCode(libraryInfos); + + Map>> libraryConditions = initializeTestLibraryConditions(); + + libraryConditions.get("streamTriggers").add(lib -> lib.getStreamTriggers().stream().anyMatch(trigger -> "consumer".equalsIgnoreCase(trigger.getName()))); + libraryConditions.get("streamTriggers").add(lib -> lib.getStreamTriggers().stream().anyMatch(trigger -> "stream".equalsIgnoreCase(trigger.getPrefix()))); + libraryConditions.get("withFlags").add(lib -> lib.getFunctions().stream().anyMatch(func -> "my_set".equalsIgnoreCase(func.getName()))); + libraryConditions.get("withFlags").add(lib -> lib.getFunctions().stream().anyMatch(func -> func.getFlags().contains("raw-arguments"))); + libraryConditions.get("pingpong").add(lib -> lib.getFunctions().stream().anyMatch(func -> "playPingPong".equalsIgnoreCase(func.getName()))); + libraryConditions.get("keyspaceTriggers").add(lib -> lib.getKeyspaceTriggers().stream().anyMatch(trigger -> "consumer".equalsIgnoreCase(trigger.getName()))); + libraryConditions.get("hashitout").add(lib -> lib.getFunctions().stream().anyMatch(func -> "hashy".equalsIgnoreCase(func.getName()))); + libraryConditions.get("withConfig").add(lib -> lib.getFunctions().stream().anyMatch(func -> "hset".equalsIgnoreCase(func.getName()))); + + for (GearsLibraryInfo libraryInfo : libraryInfos) { + List> conditions = libraryConditions.get(libraryInfo.getName()); + if (conditions != null && !conditions.isEmpty()) { + conditions.forEach(c -> c.test(libraryInfo)); + } + } + } + + @Test + public void testFunctionListWithCodeVerboseZero() throws IOException { + loadAllLibraries(); + List libraryInfos = client.tFunctionList(TFunctionListParams.listParams().withCode().verbose(0)); + assertAllLibrariesWithCode(libraryInfos); + + Map>> libraryConditions = initializeTestLibraryConditions(); + + libraryConditions.get("streamTriggers").add(lib -> lib.getStreamTriggers().stream().anyMatch(trigger -> "consumer".equalsIgnoreCase(trigger.getName()))); + libraryConditions.get("withFlags").add(lib -> lib.getFunctions().stream().anyMatch(func -> "my_set".equalsIgnoreCase(func.getName()))); + libraryConditions.get("pingpong").add(lib -> lib.getFunctions().stream().anyMatch(func -> "playPingPong".equalsIgnoreCase(func.getName()))); + libraryConditions.get("keyspaceTriggers").add(lib -> lib.getKeyspaceTriggers().stream().anyMatch(trigger -> "consumer".equalsIgnoreCase(trigger.getName()))); + libraryConditions.get("hashitout").add(lib -> lib.getFunctions().stream().anyMatch(func -> "hashy".equalsIgnoreCase(func.getName()))); + libraryConditions.get("withConfig").add(lib -> lib.getFunctions().stream().anyMatch(func -> "hset".equalsIgnoreCase(func.getName()))); + + for (GearsLibraryInfo libraryInfo : libraryInfos) { + List> conditions = libraryConditions.get(libraryInfo.getName()); + if (conditions != null && !conditions.isEmpty()) { + conditions.forEach(c -> c.test(libraryInfo)); + } + } + } + + @Test + public void testFunctionListWithCodeVerboseOne() throws IOException { + loadAllLibraries(); + List libraryInfos = client.tFunctionList(TFunctionListParams.listParams().withCode().verbose(1)); + assertAllLibrariesWithCode(libraryInfos); + + Map>> libraryConditions = initializeTestLibraryConditions(); + + libraryConditions.get("streamTriggers").add(lib -> lib.getStreamTriggers().stream().anyMatch(trigger -> "consumer".equalsIgnoreCase(trigger.getName()))); + libraryConditions.get("streamTriggers").add(lib -> lib.getStreamTriggers().stream().anyMatch(trigger -> "stream".equalsIgnoreCase(trigger.getPrefix()))); + libraryConditions.get("withFlags").add(lib -> lib.getFunctions().stream().anyMatch(func -> "my_set".equalsIgnoreCase(func.getName()))); + libraryConditions.get("withFlags").add(lib -> lib.getFunctions().stream().anyMatch(func -> func.getFlags().contains("raw-arguments"))); + libraryConditions.get("pingpong").add(lib -> lib.getFunctions().stream().anyMatch(func -> "playPingPong".equalsIgnoreCase(func.getName()))); + libraryConditions.get("keyspaceTriggers").add(lib -> lib.getKeyspaceTriggers().stream().anyMatch(trigger -> "consumer".equalsIgnoreCase(trigger.getName()))); + libraryConditions.get("hashitout").add(lib -> lib.getFunctions().stream().anyMatch(func -> "hashy".equalsIgnoreCase(func.getName()))); + libraryConditions.get("withConfig").add(lib -> lib.getFunctions().stream().anyMatch(func -> "hset".equalsIgnoreCase(func.getName()))); + + for (GearsLibraryInfo libraryInfo : libraryInfos) { + List> conditions = libraryConditions.get(libraryInfo.getName()); + if (conditions != null && !conditions.isEmpty()) { + conditions.forEach(c -> c.test(libraryInfo)); + } + } + } + + @Test + public void testFunctionListWithCodeVerboseTwo() throws IOException { + loadAllLibraries(); + List libraryInfos = client.tFunctionList(TFunctionListParams.listParams().withCode().verbose(2)); + assertAllLibrariesWithCode(libraryInfos); + + Map>> libraryConditions = initializeTestLibraryConditions(); + + libraryConditions.get("streamTriggers").add(lib -> lib.getStreamTriggers().stream().anyMatch(trigger -> "consumer".equalsIgnoreCase(trigger.getName()))); + libraryConditions.get("streamTriggers").add(lib -> lib.getStreamTriggers().stream().anyMatch(trigger -> "stream".equalsIgnoreCase(trigger.getPrefix()))); + libraryConditions.get("withFlags").add(lib -> lib.getFunctions().stream().anyMatch(func -> "my_set".equalsIgnoreCase(func.getName()))); + libraryConditions.get("withFlags").add(lib -> lib.getFunctions().stream().anyMatch(func -> func.getFlags().contains("raw-arguments"))); + libraryConditions.get("pingpong").add(lib -> lib.getFunctions().stream().anyMatch(func -> "playPingPong".equalsIgnoreCase(func.getName()))); + libraryConditions.get("keyspaceTriggers").add(lib -> lib.getKeyspaceTriggers().stream().anyMatch(trigger -> "consumer".equalsIgnoreCase(trigger.getName()))); + libraryConditions.get("hashitout").add(lib -> lib.getFunctions().stream().anyMatch(func -> "hashy".equalsIgnoreCase(func.getName()))); + libraryConditions.get("withConfig").add(lib -> lib.getFunctions().stream().anyMatch(func -> "hset".equalsIgnoreCase(func.getName()))); + + for (GearsLibraryInfo libraryInfo : libraryInfos) { + List> conditions = libraryConditions.get(libraryInfo.getName()); + if (conditions != null && !conditions.isEmpty()) { + conditions.forEach(c -> c.test(libraryInfo)); + } + } + } + + @Test + public void testFunctionListWithCodeVerboseThree() throws IOException { + loadAllLibraries(); + List libraryInfos = client.tFunctionList(TFunctionListParams.listParams().withCode().verbose(3)); + assertAllLibrariesWithCode(libraryInfos); + + Map>> libraryConditions = initializeTestLibraryConditions(); + + libraryConditions.get("streamTriggers").add(lib -> lib.getStreamTriggers().stream().anyMatch(trigger -> "consumer".equalsIgnoreCase(trigger.getName()))); + libraryConditions.get("streamTriggers").add(lib -> lib.getStreamTriggers().stream().anyMatch(trigger -> "stream".equalsIgnoreCase(trigger.getPrefix()))); + libraryConditions.get("withFlags").add(lib -> lib.getFunctions().stream().anyMatch(func -> "my_set".equalsIgnoreCase(func.getName()))); + libraryConditions.get("withFlags").add(lib -> lib.getFunctions().stream().anyMatch(func -> func.getFlags().contains("raw-arguments"))); + libraryConditions.get("pingpong").add(lib -> lib.getFunctions().stream().anyMatch(func -> "playPingPong".equalsIgnoreCase(func.getName()))); + libraryConditions.get("keyspaceTriggers").add(lib -> lib.getKeyspaceTriggers().stream().anyMatch(trigger -> "consumer".equalsIgnoreCase(trigger.getName()))); + libraryConditions.get("hashitout").add(lib -> lib.getFunctions().stream().anyMatch(func -> "hashy".equalsIgnoreCase(func.getName()))); + libraryConditions.get("withConfig").add(lib -> lib.getFunctions().stream().anyMatch(func -> "hset".equalsIgnoreCase(func.getName()))); + + for (GearsLibraryInfo libraryInfo : libraryInfos) { + List> conditions = libraryConditions.get(libraryInfo.getName()); + if (conditions != null && !conditions.isEmpty()) { + conditions.forEach(c -> c.test(libraryInfo)); + } + } + } + + @Test + public void testFunctionLibraryListNoCodeVerboseZero() throws IOException { + loadAllLibraries(); + List libraryInfos = client.tFunctionList(TFunctionListParams.listParams().library("pingpong")); + assertEquals(1, libraryInfos.size()); + assertEquals("pingpong", libraryInfos.get(0).getName()); + assertNull(libraryInfos.get(0).getFunctions().get(0).getDescription()); + assertNull(libraryInfos.get(0).getCode()); + } + + @Test + public void testFunctionLibraryListNoCodeVerboseOne() throws IOException { + loadAllLibraries(); + List libraryInfos = client.tFunctionList(TFunctionListParams.listParams().library("pingpong").verbose(1)); + + assertEquals(1, libraryInfos.size()); + assertEquals("pingpong", libraryInfos.get(0).getName()); + assertEquals("You PING, we PONG", libraryInfos.get(0).getFunctions().get(0).getDescription()); + assertNull(libraryInfos.get(0).getCode()); + } + + @Test + public void testFunctionLibraryListNoCodeVerboseTwo() throws IOException { + loadAllLibraries(); + List libraryInfos = client.tFunctionList(TFunctionListParams.listParams().library("pingpong").verbose(2)); + assertEquals(1, libraryInfos.size()); + assertEquals("pingpong", libraryInfos.get(0).getName()); + assertEquals("You PING, we PONG", libraryInfos.get(0).getFunctions().get(0).getDescription()); + assertNull(libraryInfos.get(0).getCode()); + } + + @Test + public void testFunctionLibraryListNoCodeVerboseThree() throws IOException { + loadAllLibraries(); + List libraryInfos = client.tFunctionList(TFunctionListParams.listParams().library("pingpong").verbose(3)); + assertEquals(1, libraryInfos.size()); + assertEquals("pingpong", libraryInfos.get(0).getName()); + assertEquals("You PING, we PONG", libraryInfos.get(0).getFunctions().get(0).getDescription()); + assertNull(libraryInfos.get(0).getCode()); + } + + @Test + public void testFunctionLibraryListWithCodeVerboseZero() throws IOException { + loadAllLibraries(); + List libraryInfos = client.tFunctionList(TFunctionListParams.listParams().library("pingpong").withCode()); + assertEquals(1, libraryInfos.size()); + assertEquals("pingpong", libraryInfos.get(0).getName()); + assertNull(libraryInfos.get(0).getFunctions().get(0).getDescription()); + assertNotNull(libraryInfos.get(0).getCode()); + } + + @Test + public void testFunctionLibraryListWithCodeVerboseOne() throws IOException { + loadAllLibraries(); + List libraryInfos = client.tFunctionList(TFunctionListParams.listParams().library("pingpong").withCode().verbose(1)); + assertEquals(1, libraryInfos.size()); + assertEquals("pingpong", libraryInfos.get(0).getName()); + assertEquals("You PING, we PONG", libraryInfos.get(0).getFunctions().get(0).getDescription()); + assertNotNull(libraryInfos.get(0).getCode()); + } + + @Test + public void testFunctionLibraryListWithCodeVerboseTwo() throws IOException { + loadAllLibraries(); + List libraryInfos = client.tFunctionList(TFunctionListParams.listParams().library("pingpong").withCode().verbose(2)); + assertEquals(1, libraryInfos.size()); + assertEquals("pingpong", libraryInfos.get(0).getName()); + assertEquals("You PING, we PONG", libraryInfos.get(0).getFunctions().get(0).getDescription()); + assertNotNull(libraryInfos.get(0).getCode()); + } + + @Test + public void testFunctionLibraryListWithCodeVerboseThree() throws IOException { + loadAllLibraries(); + List libraryInfos = client.tFunctionList(TFunctionListParams.listParams().library("pingpong").withCode().verbose(3)); + assertEquals(1, libraryInfos.size()); + assertEquals("pingpong", libraryInfos.get(0).getName()); + assertEquals("You PING, we PONG", libraryInfos.get(0).getFunctions().get(0).getDescription()); + assertNotNull(libraryInfos.get(0).getCode()); + } + + @Test + public void testLibraryDelete() throws IOException { + loadAllLibraries(); + assertEquals("OK", client.tFunctionDelete("pingpong")); + List libraryInfos = client.tFunctionList(); + assertEquals(LIBRARIES_ARRAY.length - 1, libraryInfos.size()); + } + + @Test + public void testLibraryCallStringResult() throws IOException { + loadAllLibraries(); + Object result = client.tFunctionCall("pingpong", "playPingPong", Collections.emptyList(), + Collections.emptyList()); + assertEquals(String.class, result.getClass()); + assertEquals("PONG", result); + } + + @Test + public void testLibraryCallSetValueResult() throws IOException { + loadAllLibraries(); + Object result = client.tFunctionCall("withFlags", "my_set", Collections.singletonList("MY_KEY"), + Collections.singletonList("MY_VALUE")); + assertEquals(String.class, result.getClass()); + assertEquals("OK", result); + assertEquals("MY_VALUE", client.get("MY_KEY")); + } + + @Test + public void testLibraryCallHashResult() throws IOException { + loadAllLibraries(); + Map payload = new HashMap<>(); + payload.put("C", "Dennis Ritchie"); + payload.put("Python", "Guido van Rossum"); + payload.put("C++", "Bjarne Stroustrup"); + payload.put("JavaScript", "Brendan Eich"); + payload.put("Java", "James Gosling"); + payload.put("Ruby", "Yukihiro Matsumoto"); + + client.hmset("hash1", payload); + + Object result = client.tFunctionCall("hashitout", "hashy", Collections.singletonList("hash1"), + Collections.emptyList()); + + final Map asMap; + + if (protocol != RedisProtocol.RESP3) { + final List asList = (List) result; + asMap = flatMapToMap(asList); + + } else { + asMap = (Map) result; + } + + payload.forEach((language, author) -> { + assertThat(asMap, Matchers.hasEntry(language, author)); + }); + assertThat(Long.parseLong(asMap.get("__last_updated__")), Matchers.greaterThan(0L)); + } + + @Test + public void testFunctionLoadWithConfig() throws IOException { + loadAllLibraries(); + List argsBefore = Arrays.asList("Dictionary1", "Pollito", "Chicken"); + client.tFunctionCall("withConfig", "hset", Collections.emptyList(), argsBefore); + + String config = "{\"last_modified_field_name\":\"changed_on\"}"; + client.tFunctionLoad(readLibrary("withConfig.js"), TFunctionLoadParams.loadParams().replace().config(config)); + + List argsAfter = Arrays.asList("Dictionary2", "Gallina", "Hen"); + Object result = client.tFunctionCall("withConfig", "hset", Collections.emptyList(), argsAfter); + assertEquals(2L, result); + + Map dict1 = client.hgetAll("Dictionary1"); + Map dict2 = client.hgetAll("Dictionary2"); + + assertTrue(dict1.containsKey("Pollito")); + assertTrue(dict1.containsKey("__last_modified__")); + assertFalse(dict1.containsKey("changed_on")); + + assertTrue(dict2.containsKey("Gallina")); + assertTrue(dict2.containsKey("changed_on")); + assertFalse(dict2.containsKey("__last_modified__")); + } + + @Test + public void testLibraryCallSetValueResultAsync() throws IOException { + loadAllLibraries(); + Object result = client.tFunctionCallAsync("withFlags", "my_set", Collections.singletonList("KEY_TWO"), + Collections.singletonList("KEY_TWO_VALUE")); + assertEquals(String.class, result.getClass()); + assertEquals("OK", result); + assertEquals("KEY_TWO_VALUE", client.get("KEY_TWO")); + } + + private static String readLibrary(String filename) throws IOException { + Path path = Paths.get("src/test/resources/functions/" + filename); + return String.join("\n", Files.readAllLines(path)); + } + + private void loadAllLibraries() throws IOException { + try (Stream walk = Files.walk(Paths.get("src/test/resources/functions/"))) { + List libs = walk + .filter(p -> !Files.isDirectory(p)) // + .map(Path::toString) // + .filter(f -> f.endsWith(".js")) // + .collect(Collectors.toList()); + + libs.forEach(lib -> { + String code; + try { + code = String.join("\n", Files.readAllLines(Paths.get(lib))); + } catch (IOException e) { + throw new RuntimeException(e); + } + client.tFunctionLoad(code, TFunctionLoadParams.loadParams().replace()); + }); + } + } + + private static Map>> initializeTestLibraryConditions() { + Map>> libraryConditions = new HashMap<>(); + libraryConditions.put("streamTriggers", new ArrayList<>()); + libraryConditions.put("withFlags", new ArrayList<>()); + libraryConditions.put("pingpong", new ArrayList<>()); + libraryConditions.put("keyspaceTriggers", new ArrayList<>()); + libraryConditions.put("hashitout", new ArrayList<>()); + libraryConditions.put("withConfig", new ArrayList<>()); + + return libraryConditions; + } + + private static Map flatMapToMap(List list) { + Map map = new HashMap(list.size() / 2); + for (int i = 0; i < list.size(); i += 2) { + map.put(list.get(i), list.get(i + 1)); + } + return map; + } +} diff --git a/src/test/java/redis/clients/jedis/modules/graph/GraphAPITest.java b/src/test/java/redis/clients/jedis/modules/graph/GraphAPITest.java index 5ca177a3d5..694a1ddf78 100644 --- a/src/test/java/redis/clients/jedis/modules/graph/GraphAPITest.java +++ b/src/test/java/redis/clients/jedis/modules/graph/GraphAPITest.java @@ -770,7 +770,7 @@ public void slowlog() { assertNotNull(client.graphProfile("social", "CREATE (:person{name:'roi',age:32})")); assertNotNull(client.graphProfile("social", "CREATE (:person{name:'amit',age:30})")); - List> slowlogs = client.graphSlowlog("social"); + List> slowlogs = client.graphSlowlog("social"); assertEquals(2, slowlogs.size()); slowlogs.forEach(sl -> assertFalse(sl.isEmpty())); slowlogs.forEach(sl -> sl.forEach(Assert::assertNotNull)); diff --git a/src/test/java/redis/clients/jedis/modules/graph/GraphPipelineTest.java b/src/test/java/redis/clients/jedis/modules/graph/GraphPipelineTest.java index adb2c7eb31..22d6894333 100644 --- a/src/test/java/redis/clients/jedis/modules/graph/GraphPipelineTest.java +++ b/src/test/java/redis/clients/jedis/modules/graph/GraphPipelineTest.java @@ -25,7 +25,7 @@ public class GraphPipelineTest extends RedisModuleCommandsTestBase { - private Connection c; +// private Connection c; @BeforeClass public static void prepare() { @@ -42,20 +42,21 @@ public static void prepare() { // api.deleteGraph("social"); // api.close(); // } - - @Before - public void createApi() { - c = createConnection(); - } - - @After - public void deleteGraph() { - c.close(); - } +// +// @Before +// public void createApi() { +// c = createConnection(); +// } +// +// @After +// public void deleteGraph() { +// c.close(); +// } @Test public void testSync() { - Pipeline pipeline = new Pipeline(c); +// Pipeline pipeline = new Pipeline(c); + Pipeline pipeline = (Pipeline) client.pipelined(); pipeline.set("x", "1"); pipeline.graphQuery("social", "CREATE (:Person {name:'a'})"); @@ -140,7 +141,8 @@ record = iterator.next(); @Test public void testReadOnlyQueries() { - Pipeline pipeline = new Pipeline(c); +// Pipeline pipeline = new Pipeline(c); + Pipeline pipeline = (Pipeline) client.pipelined(); pipeline.set("x", "1"); pipeline.graphQuery("social", "CREATE (:Person {name:'a'})"); @@ -215,7 +217,8 @@ record = iterator.next(); @Test public void testWaitReplicas() { - Pipeline pipeline = new Pipeline(c); +// Pipeline pipeline = new Pipeline(c); + Pipeline pipeline = (Pipeline) client.pipelined(); pipeline.set("x", "1"); pipeline.graphProfile("social", "CREATE (:Person {name:'a'})"); pipeline.graphProfile("g", "CREATE (:Person {name:'a'})"); @@ -223,4 +226,17 @@ public void testWaitReplicas() { List results = pipeline.syncAndReturnAll(); assertEquals(Long.valueOf(0), results.get(3)); } + + @Test + @org.junit.Ignore + public void testWaitAof() { +// Pipeline pipeline = new Pipeline(c); + Pipeline pipeline = (Pipeline) client.pipelined(); + pipeline.set("x", "1"); + pipeline.graphProfile("social", "CREATE (:Person {name:'a'})"); + pipeline.graphProfile("g", "CREATE (:Person {name:'a'})"); + pipeline.waitAOF(1L, 0L, 100L); + List results = pipeline.syncAndReturnAll(); + assertEquals(0L, results.get(3)); + } } diff --git a/src/test/java/redis/clients/jedis/modules/graph/GraphTransactionTest.java b/src/test/java/redis/clients/jedis/modules/graph/GraphTransactionTest.java index 26ee4f135f..c63996e7b5 100644 --- a/src/test/java/redis/clients/jedis/modules/graph/GraphTransactionTest.java +++ b/src/test/java/redis/clients/jedis/modules/graph/GraphTransactionTest.java @@ -9,13 +9,10 @@ import java.util.Iterator; import java.util.List; -import org.junit.After; -import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import redis.clients.jedis.Connection; -import redis.clients.jedis.Transaction; +import redis.clients.jedis.AbstractTransaction; import redis.clients.jedis.graph.Header; import redis.clients.jedis.graph.Record; import redis.clients.jedis.graph.ResultSet; @@ -25,7 +22,7 @@ public class GraphTransactionTest extends RedisModuleCommandsTestBase { - private Connection c; +// private Connection c; @BeforeClass public static void prepare() { @@ -42,20 +39,21 @@ public static void prepare() { // api.deleteGraph("social"); // api.close(); // } - - @Before - public void createApi() { - c = createConnection(); - } - - @After - public void deleteGraph() { - c.close(); - } +// +// @Before +// public void createApi() { +// c = createConnection(); +// } +// +// @After +// public void deleteGraph() { +// c.close(); +// } @Test public void testMultiExec() { - Transaction transaction = new Transaction(c); +// Transaction transaction = new Transaction(c); + AbstractTransaction transaction = client.multi(); transaction.set("x", "1"); transaction.graphQuery("social", "CREATE (:Person {name:'a'})"); @@ -178,7 +176,8 @@ record = iterator.next(); @Test public void testMultiExecWithReadOnlyQueries() { - Transaction transaction = new Transaction(c); +// Transaction transaction = new Transaction(c); + AbstractTransaction transaction = client.multi(); transaction.set("x", "1"); transaction.graphQuery("social", "CREATE (:Person {name:'a'})"); diff --git a/src/test/java/redis/clients/jedis/modules/graph/GraphValuesTest.java b/src/test/java/redis/clients/jedis/modules/graph/GraphValuesTest.java index fe4737e197..8761e0f786 100644 --- a/src/test/java/redis/clients/jedis/modules/graph/GraphValuesTest.java +++ b/src/test/java/redis/clients/jedis/modules/graph/GraphValuesTest.java @@ -38,4 +38,12 @@ public void parseNaN() { Record r = rs.iterator().next(); assertEquals(Double.NaN, r.getValue(0), 0d); } + + @Test + public void parseMinusNaN() { + ResultSet rs = client.graphQuery("db", "RETURN sqrt(-1)"); + assertEquals(1, rs.size()); + Record r = rs.iterator().next(); + assertEquals(Double.NaN, r.getValue(0), 0d); + } } diff --git a/src/test/java/redis/clients/jedis/modules/json/JsonObjects.java b/src/test/java/redis/clients/jedis/modules/json/JsonObjects.java index 9af5ec7608..dbe44ab3f8 100644 --- a/src/test/java/redis/clients/jedis/modules/json/JsonObjects.java +++ b/src/test/java/redis/clients/jedis/modules/json/JsonObjects.java @@ -1,5 +1,7 @@ package redis.clients.jedis.modules.json; +import java.time.Instant; +import java.util.List; import java.util.Objects; public class JsonObjects { @@ -15,6 +17,16 @@ public IRLObject() { this.str = "string"; this.bool = true; } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + final IRLObject other = (IRLObject) obj; + return Objects.equals(str, other.str) + && Objects.equals(bool, other.bool); + } } @SuppressWarnings("unused") @@ -99,4 +111,58 @@ public boolean equals(Object o) { && Objects.equals(baz, other.baz); } } + + public static class Person { + public String name; + public int age; + public String address; + public String phone; + public List childrens; + + public Person(String name, int age, String address, String phone, List childrens) { + this.name = name; + this.age = age; + this.address = address; + this.phone = phone; + this.childrens = childrens; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null) { + return false; + } + // if (getClass() != o.getClass()) { + // return false; + // } + Person other = (Person) o; + + return Objects.equals(name, other.name) + && Objects.equals(age, other.age) + && Objects.equals(address, other.address) + && Objects.equals(phone, other.phone) + && Objects.equals(childrens, other.childrens); + } + } + + public static class Tick { + private final String id; + private final Instant created; + + public Tick(String id, Instant created) { + this.id = id; + this.created = created; + } + + public String getId() { + return id; + } + + public Instant getCreated() { + return created; + } + } } diff --git a/src/test/java/redis/clients/jedis/modules/json/RedisJsonV1Test.java b/src/test/java/redis/clients/jedis/modules/json/RedisJsonV1Test.java index c3f46fa656..5843b6e06a 100644 --- a/src/test/java/redis/clients/jedis/modules/json/RedisJsonV1Test.java +++ b/src/test/java/redis/clients/jedis/modules/json/RedisJsonV1Test.java @@ -7,177 +7,207 @@ import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; + +import java.time.Instant; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; + +import org.junit.Assume; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import redis.clients.jedis.RedisProtocol; import redis.clients.jedis.exceptions.JedisDataException; import redis.clients.jedis.json.JsonSetParams; import redis.clients.jedis.json.Path; +import redis.clients.jedis.json.commands.RedisJsonV1Commands; import redis.clients.jedis.modules.RedisModuleCommandsTestBase; +import redis.clients.jedis.util.JsonObjectMapperTestUtil; +import redis.clients.jedis.util.RedisProtocolUtil; public class RedisJsonV1Test extends RedisModuleCommandsTestBase { + private final Gson gson = new Gson(); + + private RedisJsonV1Commands jsonV1; + @BeforeClass public static void prepare() { + Assume.assumeFalse(RedisProtocolUtil.getRedisProtocol() == RedisProtocol.RESP3); RedisModuleCommandsTestBase.prepare(); } - private final Gson gson = new Gson(); + @Before + @Override + public void setUp() { + super.setUp(); + this.jsonV1 = super.client; + } @Test public void basicSetGetShouldSucceed() { // naive set with a path -// client.jsonSet("null", null, ROOT_PATH); - client.jsonSet("null", ROOT_PATH, (Object) null); - assertNull(client.jsonGet("null", String.class, ROOT_PATH)); +// jsonClient.jsonSet("null", null, ROOT_PATH); + jsonV1.jsonSet("null", ROOT_PATH, (Object) null); + assertNull(jsonV1.jsonGet("null", String.class, ROOT_PATH)); // real scalar value and no path - client.jsonSet("str", ROOT_PATH, "strong"); - assertEquals("strong", client.jsonGet("str")); + jsonV1.jsonSet("str", ROOT_PATH, "strong"); + assertEquals("strong", jsonV1.jsonGet("str")); // a slightly more complex object IRLObject obj = new IRLObject(); - client.jsonSet("obj", ROOT_PATH, obj); + jsonV1.jsonSet("obj", ROOT_PATH, obj); Object expected = gson.fromJson(gson.toJson(obj), Object.class); - assertTrue(expected.equals(client.jsonGet("obj"))); + assertTrue(expected.equals(jsonV1.jsonGet("obj"))); // check an update Path p = Path.of(".str"); - client.jsonSet("obj", p, "strung"); - assertEquals("strung", client.jsonGet("obj", String.class, p)); + jsonV1.jsonSet("obj", p, "strung"); + assertEquals("strung", jsonV1.jsonGet("obj", String.class, p)); } @Test public void setExistingPathOnlyIfExistsShouldSucceed() { - client.jsonSet("obj", ROOT_PATH, new IRLObject()); + jsonV1.jsonSet("obj", ROOT_PATH, new IRLObject()); Path p = Path.of(".str"); - client.jsonSet("obj", p, "strangle", JsonSetParams.jsonSetParams().xx()); - assertEquals("strangle", client.jsonGet("obj", String.class, p)); + jsonV1.jsonSet("obj", p, "strangle", JsonSetParams.jsonSetParams().xx()); + assertEquals("strangle", jsonV1.jsonGet("obj", String.class, p)); } @Test public void setNonExistingOnlyIfNotExistsShouldSucceed() { - client.jsonSet("obj", ROOT_PATH, new IRLObject()); + jsonV1.jsonSet("obj", ROOT_PATH, new IRLObject()); Path p = Path.of(".none"); - client.jsonSet("obj", p, "strangle", JsonSetParams.jsonSetParams().nx()); - assertEquals("strangle", client.jsonGet("obj", String.class, p)); + jsonV1.jsonSet("obj", p, "strangle", JsonSetParams.jsonSetParams().nx()); + assertEquals("strangle", jsonV1.jsonGet("obj", String.class, p)); } @Test public void setWithoutAPathDefaultsToRootPath() { - client.jsonSet("obj1", ROOT_PATH, new IRLObject()); -// client.jsonSet("obj1", "strangle", JsonSetParams.jsonSetParams().xx()); - client.jsonSetLegacy("obj1", (Object) "strangle", JsonSetParams.jsonSetParams().xx()); - assertEquals("strangle", client.jsonGet("obj1", String.class, ROOT_PATH)); + jsonV1.jsonSet("obj1", ROOT_PATH, new IRLObject()); +// jsonClient.jsonSet("obj1", "strangle", JsonSetParams.jsonSetParams().xx()); + jsonV1.jsonSetLegacy("obj1", (Object) "strangle", JsonSetParams.jsonSetParams().xx()); + assertEquals("strangle", jsonV1.jsonGet("obj1", String.class, ROOT_PATH)); } @Test public void setExistingPathOnlyIfNotExistsShouldFail() { - client.jsonSet("obj", ROOT_PATH, new IRLObject()); + jsonV1.jsonSet("obj", ROOT_PATH, new IRLObject()); Path p = Path.of(".str"); - assertNull(client.jsonSet("obj", p, "strangle", JsonSetParams.jsonSetParams().nx())); + assertNull(jsonV1.jsonSet("obj", p, "strangle", JsonSetParams.jsonSetParams().nx())); } @Test public void setNonExistingPathOnlyIfExistsShouldFail() { - client.jsonSet("obj", ROOT_PATH, new IRLObject()); + jsonV1.jsonSet("obj", ROOT_PATH, new IRLObject()); Path p = Path.of(".none"); - assertNull(client.jsonSet("obj", p, "strangle", JsonSetParams.jsonSetParams().xx())); + assertNull(jsonV1.jsonSet("obj", p, "strangle", JsonSetParams.jsonSetParams().xx())); } @Test(expected = JedisDataException.class) public void setException() { // should error on non root path for new key - client.jsonSet("test", Path.of(".foo"), "bar"); + jsonV1.jsonSet("test", Path.of(".foo"), "bar"); } @Test public void getMultiplePathsShouldSucceed() { // check multiple paths IRLObject obj = new IRLObject(); - client.jsonSet("obj", gson.toJson(obj)); + jsonV1.jsonSetLegacy("obj", obj); Object expected = gson.fromJson(gson.toJson(obj), Object.class); - assertTrue(expected.equals(client.jsonGet("obj", Object.class, Path.of("bool"), Path.of("str")))); - } - - @Test - public void getMultiplePathsShouldSucceedWithLegacy() { - // check multiple paths - IRLObject obj = new IRLObject(); - client.jsonSetLegacy("obj", obj); - Object expected = gson.fromJson(gson.toJson(obj), Object.class); - assertTrue(expected.equals(client.jsonGet("obj", Object.class, Path.of("bool"), Path.of("str")))); + assertTrue(expected.equals(jsonV1.jsonGet("obj", Object.class, Path.of("bool"), Path.of("str")))); } @Test public void toggle() { IRLObject obj = new IRLObject(); - client.jsonSetLegacy("obj", obj); + jsonV1.jsonSetLegacy("obj", obj); Path pbool = Path.of(".bool"); // check initial value - assertTrue(client.jsonGet("obj", Boolean.class, pbool)); + assertTrue(jsonV1.jsonGet("obj", Boolean.class, pbool)); // true -> false - client.jsonToggle("obj", pbool); - assertFalse(client.jsonGet("obj", Boolean.class, pbool)); + jsonV1.jsonToggle("obj", pbool); + assertFalse(jsonV1.jsonGet("obj", Boolean.class, pbool)); // false -> true - client.jsonToggle("obj", pbool); - assertTrue(client.jsonGet("obj", Boolean.class, pbool)); + jsonV1.jsonToggle("obj", pbool); + assertTrue(jsonV1.jsonGet("obj", Boolean.class, pbool)); // ignore non-boolean field Path pstr = Path.of(".str"); try { - client.jsonToggle("obj", pstr); + jsonV1.jsonToggle("obj", pstr); fail("String not a bool"); } catch (JedisDataException jde) { assertTrue(jde.getMessage().contains("not a bool")); } - assertEquals("string", client.jsonGet("obj", String.class, pstr)); + assertEquals("string", jsonV1.jsonGet("obj", String.class, pstr)); } @Test(expected = JedisDataException.class) public void getAbsent() { - client.jsonSet("test", ROOT_PATH, "foo"); - client.jsonGet("test", String.class, Path.of(".bar")); + jsonV1.jsonSet("test", ROOT_PATH, "foo"); + jsonV1.jsonGet("test", String.class, Path.of(".bar")); } @Test public void delValidShouldSucceed() { // check deletion of a single path - client.jsonSet("obj", ROOT_PATH, new IRLObject()); - assertEquals(1L, client.jsonDel("obj", Path.of(".str"))); + jsonV1.jsonSet("obj", ROOT_PATH, new IRLObject()); + assertEquals(1L, jsonV1.jsonDel("obj", Path.of(".str"))); assertTrue(client.exists("obj")); // check deletion root using default root -> key is removed - assertEquals(1L, client.jsonDel("obj")); + assertEquals(1L, jsonV1.jsonDel("obj")); assertFalse(client.exists("obj")); } @Test public void delNonExistingPathsAreIgnored() { - client.jsonSet("foobar", ROOT_PATH, new FooBarObject()); - assertEquals(0L, client.jsonDel("foobar", Path.of(".foo[1]"))); + jsonV1.jsonSet("foobar", ROOT_PATH, new FooBarObject()); + assertEquals(0L, jsonV1.jsonDel("foobar", Path.of(".foo[1]"))); } @Test public void typeChecksShouldSucceed() { - assertNull(client.jsonType("foobar")); - client.jsonSet("foobar", ROOT_PATH, new FooBarObject()); - assertSame(Object.class, client.jsonType("foobar")); - assertSame(Object.class, client.jsonType("foobar", ROOT_PATH)); - assertSame(String.class, client.jsonType("foobar", Path.of(".foo"))); - assertSame(int.class, client.jsonType("foobar", Path.of(".fooI"))); - assertSame(float.class, client.jsonType("foobar", Path.of(".fooF"))); - assertSame(List.class, client.jsonType("foobar", Path.of(".fooArr"))); - assertSame(boolean.class, client.jsonType("foobar", Path.of(".fooB"))); - assertNull(client.jsonType("foobar", Path.of(".fooErr"))); + assertNull(jsonV1.jsonType("foobar")); + jsonV1.jsonSet("foobar", ROOT_PATH, new FooBarObject()); + assertSame(Object.class, jsonV1.jsonType("foobar")); + assertSame(Object.class, jsonV1.jsonType("foobar", ROOT_PATH)); + assertSame(String.class, jsonV1.jsonType("foobar", Path.of(".foo"))); + assertSame(int.class, jsonV1.jsonType("foobar", Path.of(".fooI"))); + assertSame(float.class, jsonV1.jsonType("foobar", Path.of(".fooF"))); + assertSame(List.class, jsonV1.jsonType("foobar", Path.of(".fooArr"))); + assertSame(boolean.class, jsonV1.jsonType("foobar", Path.of(".fooB"))); + assertNull(jsonV1.jsonType("foobar", Path.of(".fooErr"))); + } + + @Test + public void testJsonMerge() { + // create data + List childrens = new ArrayList<>(); + childrens.add("Child 1"); + Person person = new Person("John Doe", 25, "123 Main Street", "123-456-7890", childrens); + assertEquals("OK", jsonV1.jsonSet("test_merge", ROOT_PATH, person)); + + // After 5 years: + person.age = 30; + person.childrens.add("Child 2"); + person.childrens.add("Child 3"); + + // merge the new data + assertEquals("OK", jsonV1.jsonMerge("test_merge", Path.of((".childrens")), person.childrens)); + assertEquals("OK", jsonV1.jsonMerge("test_merge", Path.of((".age")), person.age)); + assertEquals(person, jsonV1.jsonGet("test_merge", Person.class)); } @Test @@ -187,10 +217,10 @@ public void mgetWithPathWithAllKeysExist() { Qux qux1 = new Qux("quux1", "corge1", "garply1", baz1); Qux qux2 = new Qux("quux2", "corge2", "garply2", baz2); - client.jsonSetLegacy("qux1", qux1); - client.jsonSetLegacy("qux2", qux2); + jsonV1.jsonSetLegacy("qux1", qux1); + jsonV1.jsonSetLegacy("qux2", qux2); - List allBaz = client.jsonMGet(Path.of("baz"), Baz.class, "qux1", "qux2"); + List allBaz = jsonV1.jsonMGet(Path.of("baz"), Baz.class, "qux1", "qux2"); assertEquals(2, allBaz.size()); @@ -214,10 +244,10 @@ public void mgetAtRootPathWithMissingKeys() { Qux qux1 = new Qux("quux1", "corge1", "garply1", baz1); Qux qux2 = new Qux("quux2", "corge2", "garply2", baz2); - client.jsonSet("qux1", gson.toJson(qux1)); - client.jsonSet("qux2", gson.toJson(qux2)); + jsonV1.jsonSetLegacy("qux1", qux1); + jsonV1.jsonSetLegacy("qux2", qux2); - List allQux = client.jsonMGet(Qux.class, "qux1", "qux2", "qux3"); + List allQux = jsonV1.jsonMGet(Qux.class, "qux1", "qux2", "qux3"); assertEquals(3, allQux.size()); assertNull(allQux.get(2)); @@ -227,31 +257,31 @@ public void mgetAtRootPathWithMissingKeys() { @Test public void arrLen() { - client.jsonSet("foobar", ROOT_PATH, new FooBarObject()); - assertEquals(Long.valueOf(3), client.jsonArrLen("foobar", Path.of(".fooArr"))); + jsonV1.jsonSet("foobar", ROOT_PATH, new FooBarObject()); + assertEquals(Long.valueOf(3), jsonV1.jsonArrLen("foobar", Path.of(".fooArr"))); } @Test public void arrLenDefaultPath() { - assertNull(client.jsonArrLen("array")); - client.jsonSetLegacy("array", new int[]{1, 2, 3}); - assertEquals(Long.valueOf(3), client.jsonArrLen("array")); + assertNull(jsonV1.jsonArrLen("array")); + jsonV1.jsonSetLegacy("array", new int[]{1, 2, 3}); + assertEquals(Long.valueOf(3), jsonV1.jsonArrLen("array")); } @Test public void clearArray() { - client.jsonSet("foobar", ROOT_PATH, new FooBarObject()); + jsonV1.jsonSet("foobar", ROOT_PATH, new FooBarObject()); Path arrPath = Path.of(".fooArr"); - assertEquals(Long.valueOf(3), client.jsonArrLen("foobar", arrPath)); + assertEquals(Long.valueOf(3), jsonV1.jsonArrLen("foobar", arrPath)); - assertEquals(1L, client.jsonClear("foobar", arrPath)); - assertEquals(Long.valueOf(0), client.jsonArrLen("foobar", arrPath)); + assertEquals(1L, jsonV1.jsonClear("foobar", arrPath)); + assertEquals(Long.valueOf(0), jsonV1.jsonArrLen("foobar", arrPath)); // ignore non-array Path strPath = Path.of("foo"); - assertEquals(0L, client.jsonClear("foobar", strPath)); - assertEquals("bar", client.jsonGet("foobar", String.class, strPath)); + assertEquals(0L, jsonV1.jsonClear("foobar", strPath)); + assertEquals("bar", jsonV1.jsonGet("foobar", String.class, strPath)); } @Test @@ -259,12 +289,12 @@ public void clearObject() { Baz baz = new Baz("quuz", "grault", "waldo"); Qux qux = new Qux("quux", "corge", "garply", baz); - client.jsonSet("qux", gson.toJson(qux)); + jsonV1.jsonSetLegacy("qux", qux); Path objPath = Path.of("baz"); - assertEquals(baz, client.jsonGet("qux", Baz.class, objPath)); + assertEquals(baz, jsonV1.jsonGet("qux", Baz.class, objPath)); - assertEquals(1L, client.jsonClear("qux", objPath)); - assertEquals(new Baz(null, null, null), client.jsonGet("qux", Baz.class, objPath)); + assertEquals(1L, jsonV1.jsonClear("qux", objPath)); + assertEquals(new Baz(null, null, null), jsonV1.jsonGet("qux", Baz.class, objPath)); } @Test @@ -272,10 +302,10 @@ public void arrAppendSameType() { String json = "{ a: 'hello', b: [1, 2, 3], c: { d: ['ello'] }}"; JsonObject jsonObject = gson.fromJson(json, JsonObject.class); - client.jsonSet("test_arrappend", ROOT_PATH, jsonObject); - assertEquals(Long.valueOf(6), client.jsonArrAppend("test_arrappend", Path.of(".b"), 4, 5, 6)); + jsonV1.jsonSet("test_arrappend", ROOT_PATH, jsonObject); + assertEquals(Long.valueOf(6), jsonV1.jsonArrAppend("test_arrappend", Path.of(".b"), 4, 5, 6)); - Integer[] array = client.jsonGet("test_arrappend", Integer[].class, Path.of(".b")); + Integer[] array = jsonV1.jsonGet("test_arrappend", Integer[].class, Path.of(".b")); assertArrayEquals(new Integer[]{1, 2, 3, 4, 5, 6}, array); } @@ -284,10 +314,10 @@ public void arrAppendMultipleTypes() { String json = "{ a: 'hello', b: [1, 2, 3], c: { d: ['ello'] }}"; JsonObject jsonObject = gson.fromJson(json, JsonObject.class); - client.jsonSet("test_arrappend", ROOT_PATH, jsonObject); - assertEquals(Long.valueOf(6), client.jsonArrAppend("test_arrappend", Path.of(".b"), "foo", true, null)); + jsonV1.jsonSet("test_arrappend", ROOT_PATH, jsonObject); + assertEquals(Long.valueOf(6), jsonV1.jsonArrAppend("test_arrappend", Path.of(".b"), "foo", true, null)); - Object[] array = client.jsonGet("test_arrappend", Object[].class, Path.of(".b")); + Object[] array = jsonV1.jsonGet("test_arrappend", Object[].class, Path.of(".b")); // NOTE: GSon converts numeric types to the most accommodating type (Double) // when type information is not provided (as in the Object[] below) @@ -299,10 +329,10 @@ public void arrAppendMultipleTypesWithDeepPath() { String json = "{ a: 'hello', b: [1, 2, 3], c: { d: ['ello'] }}"; JsonObject jsonObject = gson.fromJson(json, JsonObject.class); - client.jsonSet("test_arrappend", ROOT_PATH, jsonObject); - assertEquals(Long.valueOf(4), client.jsonArrAppend("test_arrappend", Path.of(".c.d"), "foo", true, null)); + jsonV1.jsonSet("test_arrappend", ROOT_PATH, jsonObject); + assertEquals(Long.valueOf(4), jsonV1.jsonArrAppend("test_arrappend", Path.of(".c.d"), "foo", true, null)); - Object[] array = client.jsonGet("test_arrappend", Object[].class, Path.of(".c.d")); + Object[] array = jsonV1.jsonGet("test_arrappend", Object[].class, Path.of(".c.d")); assertArrayEquals(new Object[]{"ello", "foo", true, null}, array); } @@ -311,10 +341,10 @@ public void arrAppendAgaintsEmptyArray() { String json = "{ a: 'hello', b: [1, 2, 3], c: { d: [] }}"; JsonObject jsonObject = gson.fromJson(json, JsonObject.class); - client.jsonSet("test_arrappend", ROOT_PATH, jsonObject); - assertEquals(Long.valueOf(3), client.jsonArrAppend("test_arrappend", Path.of(".c.d"), "a", "b", "c")); + jsonV1.jsonSet("test_arrappend", ROOT_PATH, jsonObject); + assertEquals(Long.valueOf(3), jsonV1.jsonArrAppend("test_arrappend", Path.of(".c.d"), "a", "b", "c")); - String[] array = client.jsonGet("test_arrappend", String[].class, Path.of(".c.d")); + String[] array = jsonV1.jsonGet("test_arrappend", String[].class, Path.of(".c.d")); assertArrayEquals(new String[]{"a", "b", "c"}, array); } @@ -323,38 +353,38 @@ public void arrAppendPathIsNotArray() { String json = "{ a: 'hello', b: [1, 2, 3], c: { d: ['ello'] }}"; JsonObject jsonObject = gson.fromJson(json, JsonObject.class); - client.jsonSet("test_arrappend", ROOT_PATH, jsonObject); - client.jsonArrAppend("test_arrappend", Path.of(".a"), 1); + jsonV1.jsonSet("test_arrappend", ROOT_PATH, jsonObject); + jsonV1.jsonArrAppend("test_arrappend", Path.of(".a"), 1); } @Test(expected = JedisDataException.class) public void arrIndexAbsentKey() { - client.jsonArrIndex("quxquux", ROOT_PATH, gson.toJson(new Object())); + jsonV1.jsonArrIndex("quxquux", ROOT_PATH, gson.toJson(new Object())); } @Test public void arrIndexWithInts() { - client.jsonSet("quxquux", ROOT_PATH, new int[]{8, 6, 7, 5, 3, 0, 9}); - assertEquals(2L, client.jsonArrIndex("quxquux", ROOT_PATH, 7)); - assertEquals(-1L, client.jsonArrIndex("quxquux", ROOT_PATH, "7")); + jsonV1.jsonSet("quxquux", ROOT_PATH, new int[]{8, 6, 7, 5, 3, 0, 9}); + assertEquals(2L, jsonV1.jsonArrIndex("quxquux", ROOT_PATH, 7)); + assertEquals(-1L, jsonV1.jsonArrIndex("quxquux", ROOT_PATH, "7")); } @Test public void arrIndexWithStrings() { - client.jsonSet("quxquux", ROOT_PATH, new String[]{"8", "6", "7", "5", "3", "0", "9"}); - assertEquals(2L, client.jsonArrIndex("quxquux", ROOT_PATH, "7")); + jsonV1.jsonSet("quxquux", ROOT_PATH, new String[]{"8", "6", "7", "5", "3", "0", "9"}); + assertEquals(2L, jsonV1.jsonArrIndex("quxquux", ROOT_PATH, "7")); } @Test public void arrIndexWithStringsAndPath() { - client.jsonSet("foobar", ROOT_PATH, new FooBarObject()); - assertEquals(1L, client.jsonArrIndex("foobar", Path.of(".fooArr"), "b")); + jsonV1.jsonSet("foobar", ROOT_PATH, new FooBarObject()); + assertEquals(1L, jsonV1.jsonArrIndex("foobar", Path.of(".fooArr"), "b")); } @Test(expected = JedisDataException.class) public void arrIndexNonExistentPath() { - client.jsonSet("foobar", ROOT_PATH, new FooBarObject()); - assertEquals(1L, client.jsonArrIndex("foobar", Path.of(".barArr"), "x")); + jsonV1.jsonSet("foobar", ROOT_PATH, new FooBarObject()); + assertEquals(1L, jsonV1.jsonArrIndex("foobar", Path.of(".barArr"), "x")); } @Test @@ -362,10 +392,10 @@ public void arrInsert() { String json = "['hello', 'world', true, 1, 3, null, false]"; JsonArray jsonArray = gson.fromJson(json, JsonArray.class); - client.jsonSet("test_arrinsert", ROOT_PATH, jsonArray); - assertEquals(8L, client.jsonArrInsert("test_arrinsert", ROOT_PATH, 1, "foo")); + jsonV1.jsonSet("test_arrinsert", ROOT_PATH, jsonArray); + assertEquals(8L, jsonV1.jsonArrInsert("test_arrinsert", ROOT_PATH, 1, "foo")); - Object[] array = client.jsonGet("test_arrinsert", Object[].class, ROOT_PATH); + Object[] array = jsonV1.jsonGet("test_arrinsert", Object[].class, ROOT_PATH); // NOTE: GSon converts numeric types to the most accommodating type (Double) // when type information is not provided (as in the Object[] below) @@ -377,117 +407,125 @@ public void arrInsertWithNegativeIndex() { String json = "['hello', 'world', true, 1, 3, null, false]"; JsonArray jsonArray = gson.fromJson(json, JsonArray.class); - client.jsonSet("test_arrinsert", ROOT_PATH, jsonArray); - assertEquals(8L, client.jsonArrInsert("test_arrinsert", ROOT_PATH, -1, "foo")); + jsonV1.jsonSet("test_arrinsert", ROOT_PATH, jsonArray); + assertEquals(8L, jsonV1.jsonArrInsert("test_arrinsert", ROOT_PATH, -1, "foo")); - Object[] array = client.jsonGet("test_arrinsert", Object[].class, ROOT_PATH); + Object[] array = jsonV1.jsonGet("test_arrinsert", Object[].class, ROOT_PATH); assertArrayEquals(new Object[]{"hello", "world", true, 1.0, 3.0, null, "foo", false}, array); } @Test public void testArrayPop() { - client.jsonSet("arr", ROOT_PATH, new int[]{0, 1, 2, 3, 4}); - assertEquals(Long.valueOf(4), client.jsonArrPop("arr", Long.class, ROOT_PATH)); - assertEquals(Long.valueOf(3), client.jsonArrPop("arr", Long.class, ROOT_PATH, -1)); - assertEquals(Long.valueOf(2), client.jsonArrPop("arr", Long.class)); - assertEquals(Long.valueOf(0), client.jsonArrPop("arr", Long.class, ROOT_PATH, 0)); - assertEquals(Double.valueOf(1), client.jsonArrPop("arr")); + jsonV1.jsonSet("arr", ROOT_PATH, new int[]{0, 1, 2, 3, 4}); + assertEquals(Long.valueOf(4), jsonV1.jsonArrPop("arr", Long.class, ROOT_PATH)); + assertEquals(Long.valueOf(3), jsonV1.jsonArrPop("arr", Long.class, ROOT_PATH, -1)); + assertEquals(Long.valueOf(2), jsonV1.jsonArrPop("arr", Long.class)); + assertEquals(Long.valueOf(0), jsonV1.jsonArrPop("arr", Long.class, ROOT_PATH, 0)); + assertEquals(Double.valueOf(1), jsonV1.jsonArrPop("arr")); } @Test public void arrTrim() { - client.jsonSet("arr", ROOT_PATH, new int[]{0, 1, 2, 3, 4}); - assertEquals(Long.valueOf(3), client.jsonArrTrim("arr", ROOT_PATH, 1, 3)); - assertArrayEquals(new Integer[]{1, 2, 3}, client.jsonGet("arr", Integer[].class, ROOT_PATH)); + jsonV1.jsonSet("arr", ROOT_PATH, new int[]{0, 1, 2, 3, 4}); + assertEquals(Long.valueOf(3), jsonV1.jsonArrTrim("arr", ROOT_PATH, 1, 3)); + assertArrayEquals(new Integer[]{1, 2, 3}, jsonV1.jsonGet("arr", Integer[].class, ROOT_PATH)); } @Test public void strAppend() { - client.jsonSet("str", ROOT_PATH, "foo"); - assertEquals(6L, client.jsonStrAppend("str", ROOT_PATH, "bar")); - assertEquals("foobar", client.jsonGet("str", String.class, ROOT_PATH)); - assertEquals(8L, client.jsonStrAppend("str", "ed")); -// assertEquals("foobared", client.jsonGet("str", String.class)); - assertEquals("foobared", client.jsonGet("str")); + jsonV1.jsonSet("str", ROOT_PATH, "foo"); + assertEquals(6L, jsonV1.jsonStrAppend("str", ROOT_PATH, "bar")); + assertEquals("foobar", jsonV1.jsonGet("str", String.class, ROOT_PATH)); + assertEquals(8L, jsonV1.jsonStrAppend("str", "ed")); +// assertEquals("foobared", jsonClient.jsonGet("str", String.class)); + assertEquals("foobared", jsonV1.jsonGet("str")); } @Test public void strLen() { - assertNull(client.jsonStrLen("str")); - client.jsonSet("str", ROOT_PATH, "foo"); - assertEquals(Long.valueOf(3), client.jsonStrLen("str")); - assertEquals(Long.valueOf(3), client.jsonStrLen("str", ROOT_PATH)); + assertNull(jsonV1.jsonStrLen("str")); + jsonV1.jsonSet("str", ROOT_PATH, "foo"); + assertEquals(Long.valueOf(3), jsonV1.jsonStrLen("str")); + assertEquals(Long.valueOf(3), jsonV1.jsonStrLen("str", ROOT_PATH)); } @Test public void numIncrBy() { - client.jsonSetLegacy("doc", gson.fromJson("{a:3}", JsonObject.class)); - assertEquals(5d, client.jsonNumIncrBy("doc", Path.of(".a"), 2), 0d); + jsonV1.jsonSetLegacy("doc", gson.fromJson("{a:3}", JsonObject.class)); + assertEquals(5d, jsonV1.jsonNumIncrBy("doc", Path.of(".a"), 2), 0d); } @Test public void obj() { - assertNull(client.jsonObjLen("doc")); - assertNull(client.jsonObjKeys("doc")); - assertNull(client.jsonObjLen("doc", ROOT_PATH)); - assertNull(client.jsonObjKeys("doc", ROOT_PATH)); + assertNull(jsonV1.jsonObjLen("doc")); + assertNull(jsonV1.jsonObjKeys("doc")); + assertNull(jsonV1.jsonObjLen("doc", ROOT_PATH)); + assertNull(jsonV1.jsonObjKeys("doc", ROOT_PATH)); String json = "{\"a\":[3], \"nested\": {\"a\": {\"b\":2, \"c\": 1}}}"; - client.jsonSetWithPlainString("doc", ROOT_PATH, json); - assertEquals(Long.valueOf(2), client.jsonObjLen("doc")); - assertEquals(Arrays.asList("a", "nested"), client.jsonObjKeys("doc")); - assertEquals(Long.valueOf(2), client.jsonObjLen("doc", Path.of(".nested.a"))); - assertEquals(Arrays.asList("b", "c"), client.jsonObjKeys("doc", Path.of(".nested.a"))); + jsonV1.jsonSetWithPlainString("doc", ROOT_PATH, json); + assertEquals(Long.valueOf(2), jsonV1.jsonObjLen("doc")); + assertEquals(Arrays.asList("a", "nested"), jsonV1.jsonObjKeys("doc")); + assertEquals(Long.valueOf(2), jsonV1.jsonObjLen("doc", Path.of(".nested.a"))); + assertEquals(Arrays.asList("b", "c"), jsonV1.jsonObjKeys("doc", Path.of(".nested.a"))); } @Test public void debugMemory() { - assertEquals(0L, client.jsonDebugMemory("json")); - assertEquals(0L, client.jsonDebugMemory("json", ROOT_PATH)); + assertEquals(0L, jsonV1.jsonDebugMemory("json")); + assertEquals(0L, jsonV1.jsonDebugMemory("json", ROOT_PATH)); String json = "{ foo: 'bar', bar: { foo: 10 }}"; JsonObject jsonObject = gson.fromJson(json, JsonObject.class); - client.jsonSet("json", ROOT_PATH, jsonObject); + jsonV1.jsonSet("json", ROOT_PATH, jsonObject); // it is okay as long as any 'long' is returned - client.jsonDebugMemory("json"); - client.jsonDebugMemory("json", ROOT_PATH); - client.jsonDebugMemory("json", Path.of(".bar")); + jsonV1.jsonDebugMemory("json"); + jsonV1.jsonDebugMemory("json", ROOT_PATH); + jsonV1.jsonDebugMemory("json", Path.of(".bar")); } @Test public void plainString() { String json = "{\"foo\":\"bar\",\"bar\":{\"foo\":10}}"; - assertEquals("OK", client.jsonSetWithPlainString("plain", ROOT_PATH, json)); - assertEquals(json, client.jsonGetAsPlainString("plain", ROOT_PATH)); + assertEquals("OK", jsonV1.jsonSetWithPlainString("plain", ROOT_PATH, json)); + assertEquals(json, jsonV1.jsonGetAsPlainString("plain", ROOT_PATH)); + } + + @Test + public void testJsonGsonParser() { + Tick person = new Tick("foo", Instant.now()); + + // setting the custom json gson parser + client.setJsonObjectMapper(JsonObjectMapperTestUtil.getCustomGsonObjectMapper()); + + jsonV1.jsonSet(person.getId(), ROOT_PATH, person); + + String valueExpected = jsonV1.jsonGet(person.getId(), String.class, Path.of(".created")); + assertEquals(valueExpected, person.getCreated().toString()); } @Test - public void resp() { - assertNull(client.jsonResp("resp")); - assertNull(client.jsonResp("resp", ROOT_PATH)); + public void testDefaultJsonGsonParserStringsMustBeDifferent() { + Tick tick = new Tick("foo", Instant.now()); + + // using the default json gson parser which is automatically configured - String json = "{\"foo\": {\"hello\":\"world\"}, \"bar\": [null, 3, 2.5, true]}"; - client.jsonSetWithPlainString("resp", ROOT_PATH, json); + jsonV1.jsonSet(tick.getId(), ROOT_PATH, tick); - List resp = client.jsonResp("resp"); - assertEquals("{", resp.get(0)); + Object valueExpected = jsonV1.jsonGet(tick.getId(), Path.of(".created")); + assertNotEquals(valueExpected, tick.getCreated().toString()); + } + + @Test + public void testJsonJacksonParser() { + Tick person = new Tick("foo", Instant.now()); - assertEquals("foo", resp.get(1)); - assertEquals(Arrays.asList("{", "hello", "world"), resp.get(2)); + // setting the custom json jackson parser + client.setJsonObjectMapper(JsonObjectMapperTestUtil.getCustomJacksonObjectMapper()); - assertEquals("bar", resp.get(3)); - List arr = (List) resp.get(4); - assertEquals("[", arr.get(0)); - assertNull(arr.get(1)); - assertEquals(Long.valueOf(3), arr.get(2)); - assertEquals("2.5", arr.get(3)); - assertEquals("true", arr.get(4)); + jsonV1.jsonSet(person.getId(), ROOT_PATH, person); - arr = client.jsonResp("resp", Path.of(".bar")); - assertEquals("[", arr.get(0)); - assertNull(arr.get(1)); - assertEquals(Long.valueOf(3), arr.get(2)); - assertEquals("2.5", arr.get(3)); - assertEquals("true", arr.get(4)); + String valueExpected = jsonV1.jsonGet(person.getId(), String.class, Path.of(".created")); + assertEquals(valueExpected, person.getCreated().toString()); } } diff --git a/src/test/java/redis/clients/jedis/modules/json/RedisJsonV2Test.java b/src/test/java/redis/clients/jedis/modules/json/RedisJsonV2Test.java index d418fe1e6d..f36832da51 100644 --- a/src/test/java/redis/clients/jedis/modules/json/RedisJsonV2Test.java +++ b/src/test/java/redis/clients/jedis/modules/json/RedisJsonV2Test.java @@ -1,6 +1,5 @@ package redis.clients.jedis.modules.json; -import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; import static org.junit.Assert.*; import static redis.clients.jedis.json.Path2.ROOT_PATH; @@ -8,101 +7,139 @@ import com.google.gson.Gson; import java.util.Arrays; +import java.util.Collections; import java.util.List; import org.json.JSONArray; import org.json.JSONObject; +import org.junit.Assume; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import redis.clients.jedis.RedisProtocol; import redis.clients.jedis.exceptions.JedisDataException; import redis.clients.jedis.json.JsonSetParams; import redis.clients.jedis.json.Path2; +import redis.clients.jedis.json.commands.RedisJsonV2Commands; import redis.clients.jedis.modules.RedisModuleCommandsTestBase; +import redis.clients.jedis.util.RedisProtocolUtil; public class RedisJsonV2Test extends RedisModuleCommandsTestBase { + private static final Gson gson = new Gson(); + + private RedisJsonV2Commands jsonV2; + @BeforeClass public static void prepare() { RedisModuleCommandsTestBase.prepare(); } - private static final Gson gson = new Gson(); + @Before + @Override + public void setUp() { + super.setUp(); + this.jsonV2 = super.client; + } @Test public void basicSetGetShouldSucceed() { + Assume.assumeFalse(RedisProtocolUtil.getRedisProtocol() == RedisProtocol.RESP3); // naive set with a path -// client.jsonSet("null", null, ROOT_PATH); - client.jsonSetWithEscape("null", ROOT_PATH, (Object) null); - assertJsonArrayEquals(jsonArray((Object) null), client.jsonGet("null", ROOT_PATH)); + jsonV2.jsonSetWithEscape("null", ROOT_PATH, (Object) null); + assertJsonArrayEquals(jsonArray((Object) null), jsonV2.jsonGet("null", ROOT_PATH)); // real scalar value and no path - client.jsonSetWithEscape("str", "strong"); - assertEquals("strong", client.jsonGet("str")); + jsonV2.jsonSetWithEscape("str", "strong"); + assertEquals("strong", jsonV2.jsonGet("str")); // a slightly more complex object IRLObject obj = new IRLObject(); - client.jsonSetWithEscape("obj", obj); + jsonV2.jsonSetWithEscape("obj", obj); Object expected = gson.fromJson(gson.toJson(obj), Object.class); - assertTrue(expected.equals(client.jsonGet("obj"))); + assertTrue(expected.equals(jsonV2.jsonGet("obj"))); + + // check an update + Path2 p = Path2.of(".str"); + jsonV2.jsonSet("obj", p, gson.toJson("strung")); + assertJsonArrayEquals(jsonArray("strung"), jsonV2.jsonGet("obj", p)); + } + + @Test + public void basicSetGetShouldSucceedResp3() { + Assume.assumeTrue(RedisProtocolUtil.getRedisProtocol() == RedisProtocol.RESP3); + + // naive set with a path + jsonV2.jsonSetWithEscape("null", ROOT_PATH, (Object) null); + assertJsonArrayEquals(jsonArray((Object) null), jsonV2.jsonGet("null", ROOT_PATH)); + + // real scalar value and no path + jsonV2.jsonSetWithEscape("str", "strong"); + assertJsonArrayEquals(jsonArray("strong"), jsonV2.jsonGet("str")); + + // a slightly more complex object + IRLObject obj = new IRLObject(); + jsonV2.jsonSetWithEscape("obj", obj); + assertJsonArrayEquals(jsonArray(new JSONObject(gson.toJson(obj))), jsonV2.jsonGet("obj")); // check an update Path2 p = Path2.of(".str"); - client.jsonSet("obj", p, gson.toJson("strung")); - assertJsonArrayEquals(jsonArray("strung"), client.jsonGet("obj", p)); + jsonV2.jsonSet("obj", p, gson.toJson("strung")); + assertJsonArrayEquals(jsonArray("strung"), jsonV2.jsonGet("obj", p)); } @Test public void setExistingPathOnlyIfExistsShouldSucceed() { - client.jsonSetWithEscape("obj", new IRLObject()); + jsonV2.jsonSetWithEscape("obj", new IRLObject()); Path2 p = Path2.of(".str"); - client.jsonSetWithEscape("obj", p, "strangle", JsonSetParams.jsonSetParams().xx()); - assertJsonArrayEquals(jsonArray("strangle"), client.jsonGet("obj", p)); + jsonV2.jsonSetWithEscape("obj", p, "strangle", JsonSetParams.jsonSetParams().xx()); + assertJsonArrayEquals(jsonArray("strangle"), jsonV2.jsonGet("obj", p)); } @Test public void setNonExistingOnlyIfNotExistsShouldSucceed() { - client.jsonSet("obj", gson.toJson(new IRLObject())); + jsonV2.jsonSet("obj", gson.toJson(new IRLObject())); Path2 p = Path2.of(".none"); - client.jsonSet("obj", p, gson.toJson("strangle"), JsonSetParams.jsonSetParams().nx()); - assertJsonArrayEquals(jsonArray("strangle"), client.jsonGet("obj", p)); + jsonV2.jsonSet("obj", p, gson.toJson("strangle"), JsonSetParams.jsonSetParams().nx()); + assertJsonArrayEquals(jsonArray("strangle"), jsonV2.jsonGet("obj", p)); } @Test public void setWithoutAPathDefaultsToRootPath() { String objStr = gson.toJson(new IRLObject()); - client.jsonSet("obj1", new JSONObject(objStr)); -// client.jsonSet("obj1", "strangle", JsonSetParams.jsonSetParams().xx()); - client.jsonSetWithEscape("obj1", (Object) "strangle", JsonSetParams.jsonSetParams().xx()); - assertJsonArrayEquals(jsonArray("strangle"), client.jsonGet("obj1", ROOT_PATH)); + jsonV2.jsonSet("obj1", new JSONObject(objStr)); +// jsonClient.jsonSet("obj1", "strangle", JsonSetParams.jsonSetParams().xx()); + jsonV2.jsonSetWithEscape("obj1", (Object) "strangle", JsonSetParams.jsonSetParams().xx()); + assertJsonArrayEquals(jsonArray("strangle"), jsonV2.jsonGet("obj1", ROOT_PATH)); } @Test public void setExistingPathOnlyIfNotExistsShouldFail() { - client.jsonSetWithEscape("obj", new IRLObject()); + jsonV2.jsonSetWithEscape("obj", new IRLObject()); Path2 p = Path2.of(".str"); - assertNull(client.jsonSetWithEscape("obj", p, "strangle", JsonSetParams.jsonSetParams().nx())); + assertNull(jsonV2.jsonSetWithEscape("obj", p, "strangle", JsonSetParams.jsonSetParams().nx())); } @Test public void setNonExistingPathOnlyIfExistsShouldFail() { - client.jsonSetWithEscape("obj", new IRLObject()); + jsonV2.jsonSetWithEscape("obj", new IRLObject()); Path2 p = Path2.of(".none"); - assertNull(client.jsonSetWithEscape("obj", p, "strangle", JsonSetParams.jsonSetParams().xx())); + assertNull(jsonV2.jsonSetWithEscape("obj", p, "strangle", JsonSetParams.jsonSetParams().xx())); } @Test(expected = JedisDataException.class) public void setException() { // should error on non root path for new key - client.jsonSet("test", Path2.of(".foo"), "bar"); + jsonV2.jsonSet("test", Path2.of(".foo"), "bar"); } @Test public void getMultiplePathsShouldSucceed() { // check multiple paths IRLObject obj = new IRLObject(); - client.jsonSetWithEscape("obj", obj); - JSONObject result = (JSONObject) client.jsonGet("obj", Path2.of("bool"), Path2.of("str")); + jsonV2.jsonSetWithEscape("obj", obj); + JSONObject result = (JSONObject) jsonV2.jsonGet("obj", Path2.of("bool"), Path2.of("str")); assertJsonArrayEquals(jsonArray(true), result.get("$.bool")); assertJsonArrayEquals(jsonArray("string"), result.get("$.str")); } @@ -114,69 +151,119 @@ public void getMultiLevels() { JSONObject inner = new JSONObject(); inner.put("foo", "Jane"); obj.put("bar", inner); - client.jsonSet("multi", obj); - assertJsonArrayEquals(jsonArray("John", "Jane"), client.jsonGet("multi", new Path2("..foo"))); + jsonV2.jsonSet("multi", obj); + assertJsonArrayEquals(jsonArray("John", "Jane"), jsonV2.jsonGet("multi", new Path2("..foo"))); } @Test public void toggle() { IRLObject obj = new IRLObject(); - client.jsonSetWithEscape("obj", obj); + jsonV2.jsonSetWithEscape("obj", obj); Path2 pbool = Path2.of(".bool"); // check initial value - assertJsonArrayEquals(jsonArray(true), client.jsonGet("obj", pbool)); + assertJsonArrayEquals(jsonArray(true), jsonV2.jsonGet("obj", pbool)); // true -> false - client.jsonToggle("obj", pbool); - assertJsonArrayEquals(jsonArray(false), client.jsonGet("obj", pbool)); + jsonV2.jsonToggle("obj", pbool); + assertJsonArrayEquals(jsonArray(false), jsonV2.jsonGet("obj", pbool)); // false -> true - client.jsonToggle("obj", pbool); - assertJsonArrayEquals(jsonArray(true), client.jsonGet("obj", pbool)); + jsonV2.jsonToggle("obj", pbool); + assertJsonArrayEquals(jsonArray(true), jsonV2.jsonGet("obj", pbool)); // ignore non-boolean field Path2 pstr = Path2.of(".str"); - assertEquals(singletonList(null), client.jsonToggle("obj", pstr)); - assertJsonArrayEquals(jsonArray("string"), client.jsonGet("obj", pstr)); + assertEquals(singletonList(null), jsonV2.jsonToggle("obj", pstr)); + assertJsonArrayEquals(jsonArray("string"), jsonV2.jsonGet("obj", pstr)); } @Test public void getAbsent() { - client.jsonSetWithEscape("test", ROOT_PATH, "foo"); - assertJsonArrayEquals(jsonArray(), client.jsonGet("test", Path2.of(".bar"))); + jsonV2.jsonSetWithEscape("test", ROOT_PATH, "foo"); + assertJsonArrayEquals(jsonArray(), jsonV2.jsonGet("test", Path2.of(".bar"))); } @Test public void delValidShouldSucceed() { // check deletion of a single path - client.jsonSetWithEscape("obj", ROOT_PATH, new IRLObject()); - assertEquals(1L, client.jsonDel("obj", Path2.of(".str"))); + jsonV2.jsonSetWithEscape("obj", ROOT_PATH, new IRLObject()); + assertEquals(1L, jsonV2.jsonDel("obj", Path2.of(".str"))); assertTrue(client.exists("obj")); // check deletion root using default root -> key is removed - assertEquals(1L, client.jsonDel("obj")); + assertEquals(1L, jsonV2.jsonDel("obj")); assertFalse(client.exists("obj")); } @Test public void delNonExistingPathsAreIgnored() { - client.jsonSetWithEscape("foobar", ROOT_PATH, new FooBarObject()); - assertEquals(0L, client.jsonDel("foobar", Path2.of(".foo[1]"))); + jsonV2.jsonSetWithEscape("foobar", ROOT_PATH, new FooBarObject()); + assertEquals(0L, jsonV2.jsonDel("foobar", Path2.of(".foo[1]"))); } @Test public void typeChecksShouldSucceed() { - client.jsonSet("foobar", ROOT_PATH, new JSONObject(gson.toJson(new FooBarObject()))); - assertSame(Object.class, client.jsonType("foobar")); - assertEquals(singletonList(Object.class), client.jsonType("foobar", ROOT_PATH)); - assertEquals(singletonList(String.class), client.jsonType("foobar", Path2.of(".foo"))); - assertEquals(singletonList(int.class), client.jsonType("foobar", Path2.of(".fooI"))); - assertEquals(singletonList(float.class), client.jsonType("foobar", Path2.of(".fooF"))); - assertEquals(singletonList(List.class), client.jsonType("foobar", Path2.of(".fooArr"))); - assertEquals(singletonList(boolean.class), client.jsonType("foobar", Path2.of(".fooB"))); - assertEquals(emptyList(), client.jsonType("foobar", Path2.of(".fooErr"))); + jsonV2.jsonSet("foobar", ROOT_PATH, new JSONObject(gson.toJson(new FooBarObject()))); + assertEquals(singletonList(Object.class), jsonV2.jsonType("foobar", ROOT_PATH)); + assertEquals(singletonList(String.class), jsonV2.jsonType("foobar", Path2.of(".foo"))); + assertEquals(singletonList(int.class), jsonV2.jsonType("foobar", Path2.of(".fooI"))); + assertEquals(singletonList(float.class), jsonV2.jsonType("foobar", Path2.of(".fooF"))); + assertEquals(singletonList(List.class), jsonV2.jsonType("foobar", Path2.of(".fooArr"))); + assertEquals(singletonList(boolean.class), jsonV2.jsonType("foobar", Path2.of(".fooB"))); + assertEquals(Collections.emptyList(), jsonV2.jsonType("foobar", Path2.of(".fooErr"))); + } + + @Test + public void testJsonMerge() { + // Test with root path + JSONObject json = new JSONObject("{\"person\":{\"name\":\"John Doe\",\"age\":25,\"address\":{\"home\":\"123 Main Street\"},\"phone\":\"123-456-7890\"}}"); + assertEquals("OK", jsonV2.jsonSet("test_merge", json)); + + json = new JSONObject("{\"person\":{\"name\":\"John Doe\",\"age\":30,\"address\":{\"home\":\"123 Main Street\"},\"phone\":\"123-456-7890\"}}"); + assertEquals("OK", jsonV2.jsonMerge("test_merge", Path2.of("$"), "{\"person\":{\"age\":30}}")); + + assertJsonArrayEquals(jsonArray(json), jsonV2.jsonGet("test_merge", Path2.of("$"))); + + // Test with root path path $.a.b + assertEquals("OK", jsonV2.jsonMerge("test_merge", Path2.of("$.person.address"), "{\"work\":\"Redis office\"}")); + json = new JSONObject("{\"person\":{\"name\":\"John Doe\",\"age\":30,\"address\":{\"home\":\"123 Main Street\",\"work\":\"Redis office\"},\"phone\":\"123-456-7890\"}}"); + assertJsonArrayEquals(jsonArray(json), jsonV2.jsonGet("test_merge", Path2.of("$"))); + + // Test with null value to delete a value + assertEquals("OK", jsonV2.jsonMerge("test_merge", Path2.of("$.person"), "{\"age\":null}")); + json = new JSONObject("{\"person\":{\"name\":\"John Doe\",\"address\":{\"home\":\"123 Main Street\",\"work\":\"Redis office\"},\"phone\":\"123-456-7890\"}}"); + assertJsonArrayEquals(jsonArray(json), jsonV2.jsonGet("test_merge", Path2.of("$"))); + + // cleanup + assertEquals(1L, client.del("test_merge")); + } + + @Test + public void testJsonMergeArray() + { + // Test merge on an array + JSONObject json = new JSONObject("{\"a\":{\"b\":{\"c\":[\"d\",\"e\"]}}}"); + assertEquals("OK", jsonV2.jsonSet("test_merge_array", Path2.of("$"), json)); + assertEquals("OK", jsonV2.jsonMerge("test_merge_array", Path2.of("$.a.b.c"), "[\"f\"]")); + + json = new JSONObject("{\"a\":{\"b\":{\"c\":[\"f\"]}}}"); + assertJsonArrayEquals(jsonArray(json), jsonV2.jsonGet("test_merge_array", Path2.of("$"))); + + // assertEquals("{{a={b={c=[f]}}}", jsonClient.jsonGet("test_merge_array", Path2.of("$"))); + + // Test merge an array on a value + assertEquals("OK", jsonV2.jsonSet("test_merge_array", Path2.of("$"), "{\"a\":{\"b\":{\"c\":\"d\"}}}")); + assertEquals("OK", jsonV2.jsonMerge("test_merge_array", Path2.of("$.a.b.c"), "[\"f\"]")); + json = new JSONObject("{\"a\":{\"b\":{\"c\":[\"f\"]}}}"); + assertJsonArrayEquals(jsonArray(json), jsonV2.jsonGet("test_merge_array", Path2.of("$"))); + + // Test with null value to delete an array value + assertEquals("OK", jsonV2.jsonSet("test_merge_array", Path2.of("$"), "{\"a\":{\"b\":{\"c\":[\"d\",\"e\"]}}}")); + assertEquals("OK", jsonV2.jsonMerge("test_merge_array", Path2.of("$.a.b"), "{\"c\":null}")); + json = new JSONObject("{\"a\":{\"b\":{}}}"); + assertJsonArrayEquals(jsonArray(json), jsonV2.jsonGet("test_merge_array", Path2.of("$"))); } @Test @@ -186,10 +273,10 @@ public void mgetWithPathWithAllKeysExist() { Qux qux1 = new Qux("quux1", "corge1", "garply1", baz1); Qux qux2 = new Qux("quux2", "corge2", "garply2", baz2); - client.jsonSet("qux1", new JSONObject(gson.toJson(qux1))); - client.jsonSet("qux2", new JSONObject(gson.toJson(qux2))); + jsonV2.jsonSet("qux1", new JSONObject(gson.toJson(qux1))); + jsonV2.jsonSet("qux2", new JSONObject(gson.toJson(qux2))); - List list = client.jsonMGet(Path2.of("baz"), "qux1", "qux2"); + List list = jsonV2.jsonMGet(Path2.of("baz"), "qux1", "qux2"); assertEquals(2, list.size()); assertJsonArrayEquals(jsonArray(new JSONObject(gson.toJson(baz1))), list.get(0)); assertJsonArrayEquals(jsonArray(new JSONObject(gson.toJson(baz2))), list.get(1)); @@ -202,10 +289,10 @@ public void mgetAtRootPathWithMissingKeys() { Qux qux1 = new Qux("quux1", "corge1", "garply1", baz1); Qux qux2 = new Qux("quux2", "corge2", "garply2", baz2); - client.jsonSetWithEscape("qux1", qux1); - client.jsonSetWithEscape("qux2", qux2); + jsonV2.jsonSetWithEscape("qux1", qux1); + jsonV2.jsonSetWithEscape("qux2", qux2); - List list = client.jsonMGet("qux1", "qux2", "qux3"); + List list = jsonV2.jsonMGet("qux1", "qux2", "qux3"); assertEquals(3, list.size()); assertNull(list.get(2)); @@ -215,24 +302,24 @@ public void mgetAtRootPathWithMissingKeys() { @Test public void arrLen() { - client.jsonSet("arr", ROOT_PATH, new JSONArray(new int[]{0, 1, 2, 3, 4})); - assertEquals(singletonList(5L), client.jsonArrLen("arr", ROOT_PATH)); + jsonV2.jsonSet("arr", ROOT_PATH, new JSONArray(new int[]{0, 1, 2, 3, 4})); + assertEquals(singletonList(5L), jsonV2.jsonArrLen("arr", ROOT_PATH)); } @Test public void clearArray() { - client.jsonSet("foobar", ROOT_PATH, gson.toJson(new FooBarObject())); + jsonV2.jsonSet("foobar", ROOT_PATH, gson.toJson(new FooBarObject())); Path2 arrPath = Path2.of(".fooArr"); - assertEquals(singletonList(3L), client.jsonArrLen("foobar", arrPath)); + assertEquals(singletonList(3L), jsonV2.jsonArrLen("foobar", arrPath)); - assertEquals(1L, client.jsonClear("foobar", arrPath)); - assertEquals(singletonList(0L), client.jsonArrLen("foobar", arrPath)); + assertEquals(1L, jsonV2.jsonClear("foobar", arrPath)); + assertEquals(singletonList(0L), jsonV2.jsonArrLen("foobar", arrPath)); // ignore non-array Path2 strPath = Path2.of(".foo"); - assertEquals(0L, client.jsonClear("foobar", strPath)); - assertJsonArrayEquals(jsonArray("bar"), client.jsonGet("foobar", strPath)); + assertEquals(0L, jsonV2.jsonClear("foobar", strPath)); + assertJsonArrayEquals(jsonArray("bar"), jsonV2.jsonGet("foobar", strPath)); } @Test @@ -240,22 +327,22 @@ public void clearObject() { Baz baz = new Baz("quuz", "grault", "waldo"); Qux qux = new Qux("quux", "corge", "garply", baz); - client.jsonSet("qux", gson.toJson(qux)); + jsonV2.jsonSet("qux", gson.toJson(qux)); Path2 objPath = Path2.of(".baz"); -// assertEquals(baz, client.jsonGet("qux", objPath)); +// assertEquals(baz, jsonClient.jsonGet("qux", objPath)); - assertEquals(1L, client.jsonClear("qux", objPath)); -// assertEquals(new Baz(null, null, null), client.jsonGet("qux", objPath)); - assertJsonArrayEquals(jsonArray(new JSONObject()), client.jsonGet("qux", objPath)); + assertEquals(1L, jsonV2.jsonClear("qux", objPath)); +// assertEquals(new Baz(null, null, null), jsonClient.jsonGet("qux", objPath)); + assertJsonArrayEquals(jsonArray(new JSONObject()), jsonV2.jsonGet("qux", objPath)); } @Test public void arrAppendSameType() { String json = "{ a: 'hello', b: [1, 2, 3], c: { d: ['ello'] }}"; - client.jsonSet("test_arrappend", ROOT_PATH, new JSONObject(json)); - assertEquals(singletonList(6L), client.jsonArrAppend("test_arrappend", Path2.of(".b"), 4, 5, 6)); + jsonV2.jsonSet("test_arrappend", ROOT_PATH, new JSONObject(json)); + assertEquals(singletonList(6L), jsonV2.jsonArrAppend("test_arrappend", Path2.of(".b"), 4, 5, 6)); - assertJsonArrayEquals(jsonArray(jsonArray(1, 2, 3, 4, 5, 6)), client.jsonGet("test_arrappend", Path2.of(".b"))); + assertJsonArrayEquals(jsonArray(jsonArray(1, 2, 3, 4, 5, 6)), jsonV2.jsonGet("test_arrappend", Path2.of(".b"))); } @Test @@ -264,174 +351,158 @@ public void arrAppendMultipleTypes() { Object trueObject = gson.toJson(true); Object nullObject = gson.toJson(null); String json = "{ a: 'hello', b: [1, 2, 3], c: { d: ['ello'] }}"; - client.jsonSet("test_arrappend", ROOT_PATH, new JSONObject(json)); - assertEquals(singletonList(6L), client.jsonArrAppend("test_arrappend", Path2.of(".b"), fooObject, trueObject, nullObject)); + jsonV2.jsonSet("test_arrappend", ROOT_PATH, new JSONObject(json)); + assertEquals(singletonList(6L), jsonV2.jsonArrAppend("test_arrappend", Path2.of(".b"), fooObject, trueObject, nullObject)); - assertJsonArrayEquals(jsonArray(jsonArray(1, 2, 3, "foo", true, null)), client.jsonGet("test_arrappend", Path2.of(".b"))); + assertJsonArrayEquals(jsonArray(jsonArray(1, 2, 3, "foo", true, null)), jsonV2.jsonGet("test_arrappend", Path2.of(".b"))); } @Test public void arrAppendMultipleTypesWithDeepPath() { String json = "{ a: 'hello', b: [1, 2, 3], c: { d: ['ello'] }}"; - client.jsonSet("test_arrappend", ROOT_PATH, new JSONObject(json)); - assertEquals(singletonList(4L), client.jsonArrAppendWithEscape("test_arrappend", Path2.of(".c.d"), "foo", true, null)); + jsonV2.jsonSet("test_arrappend", ROOT_PATH, new JSONObject(json)); + assertEquals(singletonList(4L), jsonV2.jsonArrAppendWithEscape("test_arrappend", Path2.of(".c.d"), "foo", true, null)); - assertJsonArrayEquals(jsonArray(jsonArray("ello", "foo", true, null)), client.jsonGet("test_arrappend", Path2.of(".c.d"))); + assertJsonArrayEquals(jsonArray(jsonArray("ello", "foo", true, null)), jsonV2.jsonGet("test_arrappend", Path2.of(".c.d"))); } @Test public void arrAppendAgaintsEmptyArray() { String json = "{ a: 'hello', b: [1, 2, 3], c: { d: [] }}"; - client.jsonSet("test_arrappend", ROOT_PATH, new JSONObject(json)); - assertEquals(singletonList(3L), client.jsonArrAppendWithEscape("test_arrappend", Path2.of(".c.d"), "a", "b", "c")); + jsonV2.jsonSet("test_arrappend", ROOT_PATH, new JSONObject(json)); + assertEquals(singletonList(3L), jsonV2.jsonArrAppendWithEscape("test_arrappend", Path2.of(".c.d"), "a", "b", "c")); - assertJsonArrayEquals(jsonArray(jsonArray("a", "b", "c")), client.jsonGet("test_arrappend", Path2.of(".c.d"))); + assertJsonArrayEquals(jsonArray(jsonArray("a", "b", "c")), jsonV2.jsonGet("test_arrappend", Path2.of(".c.d"))); } @Test public void arrAppendPathIsNotArray() { String json = "{ a: 'hello', b: [1, 2, 3], c: { d: ['ello'] }}"; - client.jsonSet("test_arrappend", ROOT_PATH, new JSONObject(json)); - assertEquals(singletonList(null), client.jsonArrAppend("test_arrappend", Path2.of(".a"), 1)); - assertEquals(singletonList(null), client.jsonArrAppend("test_arrappend", Path2.of(".a"), gson.toJson(1))); - assertEquals(singletonList(null), client.jsonArrAppendWithEscape("test_arrappend", Path2.of(".a"), 1)); + jsonV2.jsonSet("test_arrappend", ROOT_PATH, new JSONObject(json)); + assertEquals(singletonList(null), jsonV2.jsonArrAppend("test_arrappend", Path2.of(".a"), 1)); + assertEquals(singletonList(null), jsonV2.jsonArrAppend("test_arrappend", Path2.of(".a"), gson.toJson(1))); + assertEquals(singletonList(null), jsonV2.jsonArrAppendWithEscape("test_arrappend", Path2.of(".a"), 1)); } @Test(expected = JedisDataException.class) public void arrIndexAbsentKey() { - client.jsonArrIndexWithEscape("quxquux", ROOT_PATH, new JSONObject()); + jsonV2.jsonArrIndexWithEscape("quxquux", ROOT_PATH, new JSONObject()); } @Test public void arrIndexWithInts() { - client.jsonSetWithEscape("quxquux", ROOT_PATH, new int[]{8, 6, 7, 5, 3, 0, 9}); - assertEquals(singletonList(2L), client.jsonArrIndexWithEscape("quxquux", ROOT_PATH, 7)); - assertEquals(singletonList(-1L), client.jsonArrIndexWithEscape("quxquux", ROOT_PATH, "7")); + jsonV2.jsonSetWithEscape("quxquux", ROOT_PATH, new int[]{8, 6, 7, 5, 3, 0, 9}); + assertEquals(singletonList(2L), jsonV2.jsonArrIndexWithEscape("quxquux", ROOT_PATH, 7)); + assertEquals(singletonList(-1L), jsonV2.jsonArrIndexWithEscape("quxquux", ROOT_PATH, "7")); } @Test public void arrIndexWithStrings() { - client.jsonSetWithEscape("quxquux", ROOT_PATH, new String[]{"8", "6", "7", "5", "3", "0", "9"}); - assertEquals(singletonList(2L), client.jsonArrIndexWithEscape("quxquux", ROOT_PATH, "7")); + jsonV2.jsonSetWithEscape("quxquux", ROOT_PATH, new String[]{"8", "6", "7", "5", "3", "0", "9"}); + assertEquals(singletonList(2L), jsonV2.jsonArrIndexWithEscape("quxquux", ROOT_PATH, "7")); } @Test public void arrIndexWithStringsAndPath() { - client.jsonSetWithEscape("foobar", ROOT_PATH, new FooBarObject()); - assertEquals(singletonList(1L), client.jsonArrIndexWithEscape("foobar", Path2.of(".fooArr"), "b")); + jsonV2.jsonSetWithEscape("foobar", ROOT_PATH, new FooBarObject()); + assertEquals(singletonList(1L), jsonV2.jsonArrIndexWithEscape("foobar", Path2.of(".fooArr"), "b")); } @Test public void arrIndexNonExistentPath() { - client.jsonSet("foobar", ROOT_PATH, gson.toJson(new FooBarObject())); - assertEquals(emptyList(), client.jsonArrIndex("foobar", Path2.of(".barArr"), gson.toJson("x"))); + jsonV2.jsonSet("foobar", ROOT_PATH, gson.toJson(new FooBarObject())); + assertEquals(Collections.emptyList(), jsonV2.jsonArrIndex("foobar", Path2.of(".barArr"), gson.toJson("x"))); } @Test public void arrInsert() { String json = "['hello', 'world', true, 1, 3, null, false]"; - client.jsonSet("test_arrinsert", ROOT_PATH, new JSONArray(json)); - assertEquals(singletonList(8L), client.jsonArrInsertWithEscape("test_arrinsert", ROOT_PATH, 1, "foo")); + jsonV2.jsonSet("test_arrinsert", ROOT_PATH, new JSONArray(json)); + assertEquals(singletonList(8L), jsonV2.jsonArrInsertWithEscape("test_arrinsert", ROOT_PATH, 1, "foo")); assertJsonArrayEquals(jsonArray(jsonArray("hello", "foo", "world", true, 1, 3, null, false)), - client.jsonGet("test_arrinsert", ROOT_PATH)); + jsonV2.jsonGet("test_arrinsert", ROOT_PATH)); } @Test public void arrInsertWithNegativeIndex() { String json = "['hello', 'world', true, 1, 3, null, false]"; - client.jsonSet("test_arrinsert", ROOT_PATH, new JSONArray(json)); - assertEquals(singletonList(8L), client.jsonArrInsertWithEscape("test_arrinsert", ROOT_PATH, -1, "foo")); + jsonV2.jsonSet("test_arrinsert", ROOT_PATH, new JSONArray(json)); + assertEquals(singletonList(8L), jsonV2.jsonArrInsertWithEscape("test_arrinsert", ROOT_PATH, -1, "foo")); assertJsonArrayEquals(jsonArray(jsonArray("hello", "world", true, 1, 3, null, "foo", false)), - client.jsonGet("test_arrinsert", ROOT_PATH)); + jsonV2.jsonGet("test_arrinsert", ROOT_PATH)); } @Test public void arrPop() { - client.jsonSet("arr", ROOT_PATH, new JSONArray(new int[]{0, 1, 2, 3, 4})); - assertEquals(singletonList(4d), client.jsonArrPop("arr", ROOT_PATH)); - assertEquals(singletonList(3d), client.jsonArrPop("arr", ROOT_PATH, -1)); - assertEquals(singletonList(0d), client.jsonArrPop("arr", ROOT_PATH, 0)); + jsonV2.jsonSet("arr", ROOT_PATH, new JSONArray(new int[]{0, 1, 2, 3, 4})); + assertEquals(singletonList(4d), jsonV2.jsonArrPop("arr", ROOT_PATH)); + assertEquals(singletonList(3d), jsonV2.jsonArrPop("arr", ROOT_PATH, -1)); + assertEquals(singletonList(0d), jsonV2.jsonArrPop("arr", ROOT_PATH, 0)); } @Test public void arrTrim() { -// client.jsonSet("arr", ROOT_PATH, new int[]{0, 1, 2, 3, 4}); - client.jsonSet("arr", ROOT_PATH, new JSONArray(new int[]{0, 1, 2, 3, 4})); - assertEquals(singletonList(3L), client.jsonArrTrim("arr", ROOT_PATH, 1, 3)); -// assertArrayEquals(new Integer[]{1, 2, 3}, client.jsonGet("arr", Integer[].class, ROOT_PATH)); - assertJsonArrayEquals(jsonArray(jsonArray(1, 2, 3)), client.jsonGet("arr", ROOT_PATH)); +// jsonClient.jsonSet("arr", ROOT_PATH, new int[]{0, 1, 2, 3, 4}); + jsonV2.jsonSet("arr", ROOT_PATH, new JSONArray(new int[]{0, 1, 2, 3, 4})); + assertEquals(singletonList(3L), jsonV2.jsonArrTrim("arr", ROOT_PATH, 1, 3)); +// assertArrayEquals(new Integer[]{1, 2, 3}, jsonClient.jsonGet("arr", Integer[].class, ROOT_PATH)); + assertJsonArrayEquals(jsonArray(jsonArray(1, 2, 3)), jsonV2.jsonGet("arr", ROOT_PATH)); } @Test public void strAppend() { -// client.jsonSet("str", ROOT_PATH, "foo"); - client.jsonSet("str", ROOT_PATH, gson.toJson("foo")); - assertEquals(singletonList(6L), client.jsonStrAppend("str", ROOT_PATH, "bar")); - assertEquals("foobar", client.jsonGet("str")); +// jsonClient.jsonSet("str", ROOT_PATH, "foo"); + jsonV2.jsonSet("str", ROOT_PATH, gson.toJson("foo")); + assertEquals(singletonList(6L), jsonV2.jsonStrAppend("str", ROOT_PATH, "bar")); + assertJsonArrayEquals(jsonArray("foobar"), jsonV2.jsonGet("str", ROOT_PATH)); } @Test public void strLen() { - client.jsonSetWithEscape("str", "foobar"); - assertEquals(singletonList(6L), client.jsonStrLen("str", ROOT_PATH)); + jsonV2.jsonSetWithEscape("str", "foobar"); + assertEquals(singletonList(6L), jsonV2.jsonStrLen("str", ROOT_PATH)); } @Test public void numIncrBy() { - client.jsonSet("doc", "{\"a\":\"b\",\"b\":[{\"a\":2}, {\"a\":5}, {\"a\":\"c\"}]}"); - assertJsonArrayEquals(jsonArray((Object) null), client.jsonNumIncrBy("doc", Path2.of(".a"), 1d)); - assertJsonArrayEquals(jsonArray(null, 4, 7, null), client.jsonNumIncrBy("doc", Path2.of("..a"), 2d)); - assertJsonArrayEquals(jsonArray((Object) null), client.jsonNumIncrBy("doc", Path2.of("..b"), 0d)); - assertJsonArrayEquals(jsonArray(), client.jsonNumIncrBy("doc", Path2.of("..c"), 0d)); + Assume.assumeFalse(RedisProtocolUtil.getRedisProtocol() == RedisProtocol.RESP3); + jsonV2.jsonSet("doc", "{\"a\":\"b\",\"b\":[{\"a\":2}, {\"a\":5}, {\"a\":\"c\"}]}"); + assertJsonArrayEquals(jsonArray((Object) null), jsonV2.jsonNumIncrBy("doc", Path2.of(".a"), 1d)); + assertJsonArrayEquals(jsonArray(null, 4, 7, null), jsonV2.jsonNumIncrBy("doc", Path2.of("..a"), 2d)); + assertJsonArrayEquals(jsonArray((Object) null), jsonV2.jsonNumIncrBy("doc", Path2.of("..b"), 0d)); + assertJsonArrayEquals(jsonArray(), jsonV2.jsonNumIncrBy("doc", Path2.of("..c"), 0d)); } @Test - public void obj() { - String json = "{\"a\":[3], \"nested\": {\"a\": {\"b\":2, \"c\": 1}}}"; - client.jsonSet("doc", ROOT_PATH, json); - assertEquals(Arrays.asList(2L), client.jsonObjLen("doc", ROOT_PATH)); - assertEquals(Arrays.asList(Arrays.asList("a", "nested")), client.jsonObjKeys("doc", ROOT_PATH)); - assertEquals(Arrays.asList(null, 2L), client.jsonObjLen("doc", Path2.of("..a"))); - assertEquals(Arrays.asList(null, Arrays.asList("b", "c")), client.jsonObjKeys("doc", Path2.of("..a"))); + public void numIncrByResp3() { + Assume.assumeTrue(RedisProtocolUtil.getRedisProtocol() == RedisProtocol.RESP3); + jsonV2.jsonSet("doc", "{\"a\":\"b\",\"b\":[{\"a\":2}, {\"a\":5}, {\"a\":\"c\"}]}"); + assertEquals(singletonList((Object) null), jsonV2.jsonNumIncrBy("doc", Path2.of(".a"), 1d)); + assertEquals(Arrays.asList(null, 4d, 7d, null), jsonV2.jsonNumIncrBy("doc", Path2.of("..a"), 2d)); + assertEquals(singletonList((Object) null), jsonV2.jsonNumIncrBy("doc", Path2.of("..b"), 0d)); + assertEquals(Collections.emptyList(), jsonV2.jsonNumIncrBy("doc", Path2.of("..c"), 0d)); } @Test - public void debugMemory() { - assertEquals(emptyList(), client.jsonDebugMemory("json", ROOT_PATH)); - - client.jsonSet("json", new JSONObject("{ foo: 'bar', bar: { foo: 10 }}")); - // it is okay as long as any 'long' is returned - client.jsonDebugMemory("json"); - assertEquals(1, client.jsonDebugMemory("json", ROOT_PATH).size()); - assertEquals(2, client.jsonDebugMemory("json", Path2.of("$..foo")).size()); - assertEquals(1, client.jsonDebugMemory("json", Path2.of("$..bar")).size()); + public void obj() { + String json = "{\"a\":[3], \"nested\": {\"a\": {\"b\":2, \"c\": 1}}}"; + jsonV2.jsonSet("doc", ROOT_PATH, json); + assertEquals(Arrays.asList(2L), jsonV2.jsonObjLen("doc", ROOT_PATH)); + assertEquals(Arrays.asList(Arrays.asList("a", "nested")), jsonV2.jsonObjKeys("doc", ROOT_PATH)); + assertEquals(Arrays.asList(null, 2L), jsonV2.jsonObjLen("doc", Path2.of("..a"))); + assertEquals(Arrays.asList(null, Arrays.asList("b", "c")), jsonV2.jsonObjKeys("doc", Path2.of("..a"))); } @Test - public void resp() { - assertNull(client.jsonResp("resp", ROOT_PATH)); - - String json = "{\"foo\": {\"hello\":\"world\"}, \"bar\": [null, 3, 2.5, true]}"; - client.jsonSet("resp", ROOT_PATH, json); - - List> fullResp = client.jsonResp("resp", ROOT_PATH); - assertEquals(1, fullResp.size()); - - List resp = fullResp.get(0); - assertEquals("{", resp.get(0)); - - assertEquals("foo", resp.get(1)); - assertEquals(Arrays.asList("{", "hello", "world"), resp.get(2)); + public void debugMemory() { + assertEquals(Collections.emptyList(), jsonV2.jsonDebugMemory("json", ROOT_PATH)); - assertEquals("bar", resp.get(3)); - List arr = (List) resp.get(4); - assertEquals("[", arr.get(0)); - assertNull(arr.get(1)); - assertEquals(Long.valueOf(3), arr.get(2)); - assertEquals("2.5", arr.get(3)); - assertEquals("true", arr.get(4)); + jsonV2.jsonSet("json", new JSONObject("{ foo: 'bar', bar: { foo: 10 }}")); + assertEquals(1, jsonV2.jsonDebugMemory("json", ROOT_PATH).size()); + assertEquals(2, jsonV2.jsonDebugMemory("json", Path2.of("$..foo")).size()); + assertEquals(1, jsonV2.jsonDebugMemory("json", Path2.of("$..bar")).size()); } private void assertJsonArrayEquals(JSONArray a, Object _b) { diff --git a/src/test/java/redis/clients/jedis/modules/search/AggregationBuilderTest.java b/src/test/java/redis/clients/jedis/modules/search/AggregationBuilderTest.java index ed4070a207..396ca3365e 100644 --- a/src/test/java/redis/clients/jedis/modules/search/AggregationBuilderTest.java +++ b/src/test/java/redis/clients/jedis/modules/search/AggregationBuilderTest.java @@ -1,355 +1,28 @@ package redis.clients.jedis.modules.search; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; -import org.junit.BeforeClass; import org.junit.Test; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import redis.clients.jedis.exceptions.JedisDataException; -import redis.clients.jedis.search.Document; -import redis.clients.jedis.search.FieldName; -import redis.clients.jedis.search.IndexOptions; -import redis.clients.jedis.search.Schema; -import redis.clients.jedis.search.aggr.AggregationBuilder; -import redis.clients.jedis.search.aggr.AggregationResult; +import redis.clients.jedis.search.aggr.Reducer; import redis.clients.jedis.search.aggr.Reducers; -import redis.clients.jedis.search.aggr.Row; -import redis.clients.jedis.search.aggr.SortedField; -import redis.clients.jedis.modules.RedisModuleCommandsTestBase; - -public class AggregationBuilderTest extends RedisModuleCommandsTestBase { - - private static final String index = "aggbindex"; - - @BeforeClass - public static void prepare() { - RedisModuleCommandsTestBase.prepare(); - } -// -// @AfterClass -// public static void tearDown() { -//// RedisModuleCommandsTestBase.tearDown(); -// } - - private void addDocument(Document doc) { - String key = doc.getId(); - Map map = new LinkedHashMap<>(); - doc.getProperties().forEach(entry -> map.put(entry.getKey(), String.valueOf(entry.getValue()))); - client.hset(key, map); - } - - private void addDocument(String key, Map objMap) { - Map strMap = new HashMap<>(); - objMap.entrySet().forEach(entry -> strMap.put(entry.getKey(), String.valueOf(entry.getValue()))); - client.hset(key, strMap); - } - - @Test - public void testAggregations() { - Schema sc = new Schema(); - sc.addSortableTextField("name", 1.0); - sc.addSortableNumericField("count"); - client.ftCreate(index, IndexOptions.defaultOptions(), sc); -// client.addDocument(new Document("data1").set("name", "abc").set("count", 10)); -// client.addDocument(new Document("data2").set("name", "def").set("count", 5)); -// client.addDocument(new Document("data3").set("name", "def").set("count", 25)); - addDocument(new Document("data1").set("name", "abc").set("count", 10)); - addDocument(new Document("data2").set("name", "def").set("count", 5)); - addDocument(new Document("data3").set("name", "def").set("count", 25)); - - AggregationBuilder r = new AggregationBuilder() - .groupBy("@name", Reducers.sum("@count").as("sum")) - .sortBy(10, SortedField.desc("@sum")); - - // actual search - AggregationResult res = client.ftAggregate(index, r); - assertEquals(2, res.totalResults); - - Row r1 = res.getRow(0); - assertNotNull(r1); - assertEquals("def", r1.getString("name")); - assertEquals(30, r1.getLong("sum")); - assertEquals(30., r1.getDouble("sum"), 0); - - assertEquals(0L, r1.getLong("nosuchcol")); - assertEquals(0.0, r1.getDouble("nosuchcol"), 0); - assertEquals("", r1.getString("nosuchcol")); - - Row r2 = res.getRow(1); - assertNotNull(r2); - assertEquals("abc", r2.getString("name")); - assertEquals(10, r2.getLong("sum")); - } - - @Test - public void testAggregations2() { - Schema sc = new Schema(); - sc.addSortableTextField("name", 1.0); - sc.addSortableNumericField("count"); - client.ftCreate(index, IndexOptions.defaultOptions(), sc); - addDocument(new Document("data1").set("name", "abc").set("count", 10)); - addDocument(new Document("data2").set("name", "def").set("count", 5)); - addDocument(new Document("data3").set("name", "def").set("count", 25)); - - AggregationBuilder r = new AggregationBuilder() - .groupBy("@name", Reducers.sum("@count").as("sum")) - .sortBy(10, SortedField.desc("@sum")); - - // actual search - AggregationResult res = client.ftAggregate(index, r); - assertEquals(2, res.getTotalResults()); - - List rows = res.getRows(); - assertEquals("def", rows.get(0).get("name")); - assertEquals("30", rows.get(0).get("sum")); - assertNull(rows.get(0).get("nosuchcol")); - - assertEquals("abc", rows.get(1).get("name")); - assertEquals("10", rows.get(1).get("sum")); - } +public class AggregationBuilderTest { @Test - public void testAggregationBuilderVerbatim() { - Schema sc = new Schema(); - sc.addSortableTextField("name", 1.0); - client.ftCreate(index, IndexOptions.defaultOptions(), sc); - addDocument(new Document("data1").set("name", "hello kitty")); - - AggregationBuilder r = new AggregationBuilder("kitti"); - - AggregationResult res = client.ftAggregate(index, r); - assertEquals(1, res.totalResults); - - r = new AggregationBuilder("kitti") - .verbatim(); - - res = client.ftAggregate(index, r); - assertEquals(0, res.totalResults); + public void reducerObject() { + Reducer reducer = Reducers.sum("@count").as("total"); + assertEquals("SUM", reducer.getName()); + assertEquals("@count", reducer.getField()); + assertEquals("total", reducer.getAlias()); } @Test - public void testAggregationBuilderTimeout() { - Schema sc = new Schema(); - sc.addSortableTextField("name", 1.0); - sc.addSortableNumericField("count"); - client.ftCreate(index, IndexOptions.defaultOptions(), sc); - addDocument(new Document("data1").set("name", "abc").set("count", 10)); - addDocument(new Document("data2").set("name", "def").set("count", 5)); - addDocument(new Document("data3").set("name", "def").set("count", 25)); - - AggregationBuilder r = new AggregationBuilder() - .groupBy("@name", Reducers.sum("@count").as("sum")) - .timeout(5000); - - AggregationResult res = client.ftAggregate(index, r); - assertEquals(2, res.totalResults); - } - - @Test - public void testAggregationBuilderParamsDialect() { - Schema sc = new Schema(); - sc.addSortableTextField("name", 1.0); - sc.addSortableNumericField("count"); - client.ftCreate(index, IndexOptions.defaultOptions(), sc); - addDocument(new Document("data1").set("name", "abc").set("count", 10)); - addDocument(new Document("data2").set("name", "def").set("count", 5)); - addDocument(new Document("data3").set("name", "def").set("count", 25)); - - Map params = new HashMap<>(); - params.put("name", "abc"); - - AggregationBuilder r = new AggregationBuilder("$name") - .groupBy("@name", Reducers.sum("@count").as("sum")) - .params(params) - .dialect(2); // From documentation - To use PARAMS, DIALECT must be set to 2 - - AggregationResult res = client.ftAggregate(index, r); - assertEquals(1, res.totalResults); - - Row r1 = res.getRow(0); - assertNotNull(r1); - assertEquals("abc", r1.getString("name")); - assertEquals(10, r1.getLong("sum")); - } - - @Test - public void testApplyAndFilterAggregations() { - Schema sc = new Schema(); - sc.addSortableTextField("name", 1.0); - sc.addSortableNumericField("subj1"); - sc.addSortableNumericField("subj2"); - client.ftCreate(index, IndexOptions.defaultOptions(), sc); -// client.addDocument(new Document("data1").set("name", "abc").set("subj1", 20).set("subj2", 70)); -// client.addDocument(new Document("data2").set("name", "def").set("subj1", 60).set("subj2", 40)); -// client.addDocument(new Document("data3").set("name", "ghi").set("subj1", 50).set("subj2", 80)); -// client.addDocument(new Document("data4").set("name", "abc").set("subj1", 30).set("subj2", 20)); -// client.addDocument(new Document("data5").set("name", "def").set("subj1", 65).set("subj2", 45)); -// client.addDocument(new Document("data6").set("name", "ghi").set("subj1", 70).set("subj2", 70)); - addDocument(new Document("data1").set("name", "abc").set("subj1", 20).set("subj2", 70)); - addDocument(new Document("data2").set("name", "def").set("subj1", 60).set("subj2", 40)); - addDocument(new Document("data3").set("name", "ghi").set("subj1", 50).set("subj2", 80)); - addDocument(new Document("data4").set("name", "abc").set("subj1", 30).set("subj2", 20)); - addDocument(new Document("data5").set("name", "def").set("subj1", 65).set("subj2", 45)); - addDocument(new Document("data6").set("name", "ghi").set("subj1", 70).set("subj2", 70)); - - AggregationBuilder r = new AggregationBuilder().apply("(@subj1+@subj2)/2", "attemptavg") - .groupBy("@name", Reducers.avg("@attemptavg").as("avgscore")) - .filter("@avgscore>=50") - .sortBy(10, SortedField.asc("@name")); - - // actual search - AggregationResult res = client.ftAggregate(index, r); - assertEquals(3, res.totalResults); - - Row r1 = res.getRow(0); - assertNotNull(r1); - assertEquals("def", r1.getString("name")); - assertEquals(52.5, r1.getDouble("avgscore"), 0); - - Row r2 = res.getRow(1); - assertNotNull(r2); - assertEquals("ghi", r2.getString("name")); - assertEquals(67.5, r2.getDouble("avgscore"), 0); - } - - @Test - public void load() { - Schema sc = new Schema(); - sc.addSortableTextField("name", 1.0); - sc.addSortableNumericField("subj1"); - sc.addSortableNumericField("subj2"); - client.ftCreate(index, IndexOptions.defaultOptions(), sc); -// client.addDocument(new Document("data1").set("name", "abc").set("subj1", 20).set("subj2", 70)); -// client.addDocument(new Document("data2").set("name", "def").set("subj1", 60).set("subj2", 40)); - addDocument(new Document("data1").set("name", "abc").set("subj1", 20).set("subj2", 70)); - addDocument(new Document("data2").set("name", "def").set("subj1", 60).set("subj2", 40)); - - AggregationBuilder builder = new AggregationBuilder() - .load(FieldName.of("@subj1").as("a"), FieldName.of("@subj2").as("b")) - .apply("(@a+@b)/2", "avg").sortByDesc("@avg"); - - AggregationResult result = client.ftAggregate(index, builder); - assertEquals(50.0, result.getRow(0).getDouble("avg"), 0d); - assertEquals(45.0, result.getRow(1).getDouble("avg"), 0d); - } - - @Test - public void loadAll() { - Schema sc = new Schema(); - sc.addSortableTextField("name", 1.0); - sc.addSortableNumericField("subj1"); - sc.addSortableNumericField("subj2"); - client.ftCreate(index, IndexOptions.defaultOptions(), sc); - addDocument(new Document("data1").set("name", "abc").set("subj1", 20).set("subj2", 70)); - addDocument(new Document("data2").set("name", "def").set("subj1", 60).set("subj2", 40)); - - AggregationBuilder builder = new AggregationBuilder() - .loadAll() - .apply("(@subj1+@subj2)/2", "avg").sortByDesc("@avg"); - - AggregationResult result = client.ftAggregate(index, builder); - assertEquals(50.0, result.getRow(0).getDouble("avg"), 0d); - assertEquals(45.0, result.getRow(1).getDouble("avg"), 0d); - } - - @Test - public void testCursor() throws InterruptedException { - Schema sc = new Schema(); - sc.addSortableTextField("name", 1.0); - sc.addSortableNumericField("count"); - client.ftCreate(index, IndexOptions.defaultOptions(), sc); -// client.addDocument(new Document("data1").set("name", "abc").set("count", 10)); -// client.addDocument(new Document("data2").set("name", "def").set("count", 5)); -// client.addDocument(new Document("data3").set("name", "def").set("count", 25)); - addDocument(new Document("data1").set("name", "abc").set("count", 10)); - addDocument(new Document("data2").set("name", "def").set("count", 5)); - addDocument(new Document("data3").set("name", "def").set("count", 25)); - - AggregationBuilder r = new AggregationBuilder() - .groupBy("@name", Reducers.sum("@count").as("sum")) - .sortBy(10, SortedField.desc("@sum")) - .cursor(1, 3000); - - // actual search - AggregationResult res = client.ftAggregate(index, r); - assertEquals(2, res.totalResults); - - Row row = res.getRow(0); - assertNotNull(row); - assertEquals("def", row.getString("name")); - assertEquals(30, row.getLong("sum")); - assertEquals(30., row.getDouble("sum"), 0); - - assertEquals(0L, row.getLong("nosuchcol")); - assertEquals(0.0, row.getDouble("nosuchcol"), 0); - assertEquals("", row.getString("nosuchcol")); - - res = client.ftCursorRead(index, res.getCursorId(), 1); - Row row2 = res.getRow(0); - assertNotNull(row2); - assertEquals("abc", row2.getString("name")); - assertEquals(10, row2.getLong("sum")); - - assertEquals("OK", client.ftCursorDel(index, res.getCursorId())); - - try { - client.ftCursorRead(index, res.getCursorId(), 1); - fail(); - } catch (JedisDataException e) { - } - - AggregationBuilder r2 = new AggregationBuilder() - .groupBy("@name", Reducers.sum("@count").as("sum")) - .sortBy(10, SortedField.desc("@sum")) - .cursor(1, 1000); - - Thread.sleep(1000); - - try { - client.ftCursorRead(index, res.getCursorId(), 1); - fail(); - } catch (JedisDataException e) { - } - } - - @Test - public void testWrongAggregation() throws InterruptedException { - Schema sc = new Schema() - .addTextField("title", 5.0) - .addTextField("body", 1.0) - .addTextField("state", 1.0) - .addNumericField("price"); - - client.ftCreate(index, IndexOptions.defaultOptions(), sc); - - // insert document(s) - Map fields = new HashMap<>(); - fields.put("title", "hello world"); - fields.put("state", "NY"); - fields.put("body", "lorem ipsum"); - fields.put("price", "1337"); -// client.addDocument("doc1", fields); - addDocument("doc1", fields); - - // wrong aggregation query - AggregationBuilder builder = new AggregationBuilder("hello") - .apply("@price/1000", "k") - .groupBy("@state", Reducers.avg("@k").as("avgprice")) - .filter("@avgprice>=2") - .sortBy(10, SortedField.asc("@state")); - - try { - client.ftAggregate(index, builder); - fail(); - } catch (JedisDataException e) { - // should throw JedisDataException on wrong aggregation query - } - + public void countObject() { + Reducer count = Reducers.count(); + assertEquals("COUNT", count.getName()); + assertNull(count.getField()); + assertNull(count.getAlias()); } } diff --git a/src/test/java/redis/clients/jedis/modules/search/AggregationTest.java b/src/test/java/redis/clients/jedis/modules/search/AggregationTest.java new file mode 100644 index 0000000000..b594f28dd1 --- /dev/null +++ b/src/test/java/redis/clients/jedis/modules/search/AggregationTest.java @@ -0,0 +1,444 @@ +package redis.clients.jedis.modules.search; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +import org.hamcrest.Matchers; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import redis.clients.jedis.RedisProtocol; +import redis.clients.jedis.exceptions.JedisDataException; +import redis.clients.jedis.search.Document; +import redis.clients.jedis.search.FieldName; +import redis.clients.jedis.search.IndexOptions; +import redis.clients.jedis.search.Schema; +import redis.clients.jedis.search.aggr.AggregationBuilder; +import redis.clients.jedis.search.aggr.AggregationResult; +import redis.clients.jedis.search.aggr.Reducers; +import redis.clients.jedis.search.aggr.Row; +import redis.clients.jedis.search.aggr.SortedField; +import redis.clients.jedis.modules.RedisModuleCommandsTestBase; +import redis.clients.jedis.search.FTProfileParams; +import redis.clients.jedis.search.aggr.FtAggregateIteration; +import redis.clients.jedis.search.schemafields.NumericField; +import redis.clients.jedis.search.schemafields.TextField; + +public class AggregationTest extends RedisModuleCommandsTestBase { + + private static final String index = "aggbindex"; + + @BeforeClass + public static void prepare() { + RedisModuleCommandsTestBase.prepare(); + } +// +// @AfterClass +// public static void tearDown() { +//// RedisModuleCommandsTestBase.tearDown(); +// } + + private void addDocument(Document doc) { + String key = doc.getId(); + Map map = new LinkedHashMap<>(); + doc.getProperties().forEach(entry -> map.put(entry.getKey(), String.valueOf(entry.getValue()))); + client.hset(key, map); + } + + private void addDocument(String key, Map objMap) { + Map strMap = new HashMap<>(); + objMap.entrySet().forEach(entry -> strMap.put(entry.getKey(), String.valueOf(entry.getValue()))); + client.hset(key, strMap); + } + + @Test + public void testAggregations() { + Schema sc = new Schema(); + sc.addSortableTextField("name", 1.0); + sc.addSortableNumericField("count"); + client.ftCreate(index, IndexOptions.defaultOptions(), sc); +// client.addDocument(new Document("data1").set("name", "abc").set("count", 10)); +// client.addDocument(new Document("data2").set("name", "def").set("count", 5)); +// client.addDocument(new Document("data3").set("name", "def").set("count", 25)); + addDocument(new Document("data1").set("name", "abc").set("count", 10)); + addDocument(new Document("data2").set("name", "def").set("count", 5)); + addDocument(new Document("data3").set("name", "def").set("count", 25)); + + AggregationBuilder r = new AggregationBuilder() + .groupBy("@name", Reducers.sum("@count").as("sum")) + .sortBy(10, SortedField.desc("@sum")); + + // actual search + AggregationResult res = client.ftAggregate(index, r); + assertEquals(2, res.getTotalResults()); + + Row r1 = res.getRow(0); + assertNotNull(r1); + assertEquals("def", r1.getString("name")); + assertEquals(30, r1.getLong("sum")); + assertEquals(30., r1.getDouble("sum"), 0); + + assertEquals(0L, r1.getLong("nosuchcol")); + assertEquals(0.0, r1.getDouble("nosuchcol"), 0); + assertEquals("", r1.getString("nosuchcol")); + + Row r2 = res.getRow(1); + assertNotNull(r2); + assertEquals("abc", r2.getString("name")); + assertEquals(10, r2.getLong("sum")); + } + + @Test + public void testAggregations2() { + Schema sc = new Schema(); + sc.addSortableTextField("name", 1.0); + sc.addSortableNumericField("count"); + client.ftCreate(index, IndexOptions.defaultOptions(), sc); + + addDocument(new Document("data1").set("name", "abc").set("count", 10)); + addDocument(new Document("data2").set("name", "def").set("count", 5)); + addDocument(new Document("data3").set("name", "def").set("count", 25)); + + AggregationBuilder r = new AggregationBuilder() + .groupBy("@name", Reducers.sum("@count").as("sum")) + .sortBy(10, SortedField.desc("@sum")); + + // actual search + AggregationResult res = client.ftAggregate(index, r); + assertEquals(2, res.getTotalResults()); + + List rows = res.getRows(); + assertEquals("def", rows.get(0).get("name")); + assertEquals("30", rows.get(0).get("sum")); + assertNull(rows.get(0).get("nosuchcol")); + + assertEquals("abc", rows.get(1).get("name")); + assertEquals("10", rows.get(1).get("sum")); + } + + @Test + public void testAggregations2Profile() { + Schema sc = new Schema(); + sc.addSortableTextField("name", 1.0); + sc.addSortableNumericField("count"); + client.ftCreate(index, IndexOptions.defaultOptions(), sc); + + addDocument(new Document("data1").set("name", "abc").set("count", 10)); + addDocument(new Document("data2").set("name", "def").set("count", 5)); + addDocument(new Document("data3").set("name", "def").set("count", 25)); + + AggregationBuilder aggr = new AggregationBuilder() + .groupBy("@name", Reducers.sum("@count").as("sum")) + .sortBy(10, SortedField.desc("@sum")); + + Map.Entry> reply + = client.ftProfileAggregate(index, FTProfileParams.profileParams(), aggr); + + // actual search + AggregationResult result = reply.getKey(); + assertEquals(2, result.getTotalResults()); + + List rows = result.getRows(); + assertEquals("def", rows.get(0).get("name")); + assertEquals("30", rows.get(0).get("sum")); + assertNull(rows.get(0).get("nosuchcol")); + + assertEquals("abc", rows.get(1).get("name")); + assertEquals("10", rows.get(1).get("sum")); + + // profile + Map profile = reply.getValue(); + + assertEquals(Arrays.asList("Index", "Grouper", "Sorter"), + ((List>) profile.get("Result processors profile")).stream() + .map(map -> map.get("Type")).collect(Collectors.toList())); + + if (protocol != RedisProtocol.RESP3) { + assertEquals("WILDCARD", ((Map) profile.get("Iterators profile")).get("Type")); + } else { + assertEquals(Arrays.asList("WILDCARD"), + ((List>) profile.get("Iterators profile")).stream() + .map(map -> map.get("Type")).collect(Collectors.toList())); + } + } + + @Test + public void testAggregationBuilderVerbatim() { + Schema sc = new Schema(); + sc.addSortableTextField("name", 1.0); + client.ftCreate(index, IndexOptions.defaultOptions(), sc); + addDocument(new Document("data1").set("name", "hello kitty")); + + AggregationBuilder r = new AggregationBuilder("kitti"); + + AggregationResult res = client.ftAggregate(index, r); + assertEquals(1, res.getTotalResults()); + + r = new AggregationBuilder("kitti") + .verbatim(); + + res = client.ftAggregate(index, r); + assertEquals(0, res.getTotalResults()); + } + + @Test + public void testAggregationBuilderTimeout() { + Schema sc = new Schema(); + sc.addSortableTextField("name", 1.0); + sc.addSortableNumericField("count"); + client.ftCreate(index, IndexOptions.defaultOptions(), sc); + addDocument(new Document("data1").set("name", "abc").set("count", 10)); + addDocument(new Document("data2").set("name", "def").set("count", 5)); + addDocument(new Document("data3").set("name", "def").set("count", 25)); + + AggregationBuilder r = new AggregationBuilder() + .groupBy("@name", Reducers.sum("@count").as("sum")) + .timeout(5000); + + AggregationResult res = client.ftAggregate(index, r); + assertEquals(2, res.getTotalResults()); + } + + @Test + public void testAggregationBuilderParamsDialect() { + Schema sc = new Schema(); + sc.addSortableTextField("name", 1.0); + sc.addSortableNumericField("count"); + client.ftCreate(index, IndexOptions.defaultOptions(), sc); + addDocument(new Document("data1").set("name", "abc").set("count", 10)); + addDocument(new Document("data2").set("name", "def").set("count", 5)); + addDocument(new Document("data3").set("name", "def").set("count", 25)); + + Map params = new HashMap<>(); + params.put("name", "abc"); + + AggregationBuilder r = new AggregationBuilder("$name") + .groupBy("@name", Reducers.sum("@count").as("sum")) + .params(params) + .dialect(2); // From documentation - To use PARAMS, DIALECT must be set to 2 + + AggregationResult res = client.ftAggregate(index, r); + assertEquals(1, res.getTotalResults()); + + Row r1 = res.getRow(0); + assertNotNull(r1); + assertEquals("abc", r1.getString("name")); + assertEquals(10, r1.getLong("sum")); + } + + @Test + public void testApplyAndFilterAggregations() { + Schema sc = new Schema(); + sc.addSortableTextField("name", 1.0); + sc.addSortableNumericField("subj1"); + sc.addSortableNumericField("subj2"); + client.ftCreate(index, IndexOptions.defaultOptions(), sc); +// client.addDocument(new Document("data1").set("name", "abc").set("subj1", 20).set("subj2", 70)); +// client.addDocument(new Document("data2").set("name", "def").set("subj1", 60).set("subj2", 40)); +// client.addDocument(new Document("data3").set("name", "ghi").set("subj1", 50).set("subj2", 80)); +// client.addDocument(new Document("data4").set("name", "abc").set("subj1", 30).set("subj2", 20)); +// client.addDocument(new Document("data5").set("name", "def").set("subj1", 65).set("subj2", 45)); +// client.addDocument(new Document("data6").set("name", "ghi").set("subj1", 70).set("subj2", 70)); + addDocument(new Document("data1").set("name", "abc").set("subj1", 20).set("subj2", 70)); + addDocument(new Document("data2").set("name", "def").set("subj1", 60).set("subj2", 40)); + addDocument(new Document("data3").set("name", "ghi").set("subj1", 50).set("subj2", 80)); + addDocument(new Document("data4").set("name", "abc").set("subj1", 30).set("subj2", 20)); + addDocument(new Document("data5").set("name", "def").set("subj1", 65).set("subj2", 45)); + addDocument(new Document("data6").set("name", "ghi").set("subj1", 70).set("subj2", 70)); + + AggregationBuilder r = new AggregationBuilder().apply("(@subj1+@subj2)/2", "attemptavg") + .groupBy("@name", Reducers.avg("@attemptavg").as("avgscore")) + .filter("@avgscore>=50") + .sortBy(10, SortedField.asc("@name")); + + // actual search + AggregationResult res = client.ftAggregate(index, r); + assertEquals(3, res.getTotalResults()); + + Row r1 = res.getRow(0); + assertNotNull(r1); + assertEquals("def", r1.getString("name")); + assertEquals(52.5, r1.getDouble("avgscore"), 0); + + Row r2 = res.getRow(1); + assertNotNull(r2); + assertEquals("ghi", r2.getString("name")); + assertEquals(67.5, r2.getDouble("avgscore"), 0); + } + + @Test + public void load() { + Schema sc = new Schema(); + sc.addSortableTextField("name", 1.0); + sc.addSortableNumericField("subj1"); + sc.addSortableNumericField("subj2"); + client.ftCreate(index, IndexOptions.defaultOptions(), sc); +// client.addDocument(new Document("data1").set("name", "abc").set("subj1", 20).set("subj2", 70)); +// client.addDocument(new Document("data2").set("name", "def").set("subj1", 60).set("subj2", 40)); + addDocument(new Document("data1").set("name", "abc").set("subj1", 20).set("subj2", 70)); + addDocument(new Document("data2").set("name", "def").set("subj1", 60).set("subj2", 40)); + + AggregationBuilder builder = new AggregationBuilder() + .load(FieldName.of("@subj1").as("a"), FieldName.of("@subj2").as("b")) + .apply("(@a+@b)/2", "avg").sortByDesc("@avg"); + + AggregationResult result = client.ftAggregate(index, builder); + assertEquals(50.0, result.getRow(0).getDouble("avg"), 0d); + assertEquals(45.0, result.getRow(1).getDouble("avg"), 0d); + } + + @Test + public void loadAll() { + Schema sc = new Schema(); + sc.addSortableTextField("name", 1.0); + sc.addSortableNumericField("subj1"); + sc.addSortableNumericField("subj2"); + client.ftCreate(index, IndexOptions.defaultOptions(), sc); + addDocument(new Document("data1").set("name", "abc").set("subj1", 20).set("subj2", 70)); + addDocument(new Document("data2").set("name", "def").set("subj1", 60).set("subj2", 40)); + + AggregationBuilder builder = new AggregationBuilder() + .loadAll() + .apply("(@subj1+@subj2)/2", "avg").sortByDesc("@avg"); + + AggregationResult result = client.ftAggregate(index, builder); + assertEquals(50.0, result.getRow(0).getDouble("avg"), 0d); + assertEquals(45.0, result.getRow(1).getDouble("avg"), 0d); + } + + @Test + public void cursor() { + Schema sc = new Schema(); + sc.addSortableTextField("name", 1.0); + sc.addSortableNumericField("count"); + client.ftCreate(index, IndexOptions.defaultOptions(), sc); +// client.addDocument(new Document("data1").set("name", "abc").set("count", 10)); +// client.addDocument(new Document("data2").set("name", "def").set("count", 5)); +// client.addDocument(new Document("data3").set("name", "def").set("count", 25)); + addDocument(new Document("data1").set("name", "abc").set("count", 10)); + addDocument(new Document("data2").set("name", "def").set("count", 5)); + addDocument(new Document("data3").set("name", "def").set("count", 25)); + + AggregationBuilder r = new AggregationBuilder() + .groupBy("@name", Reducers.sum("@count").as("sum")) + .sortBy(10, SortedField.desc("@sum")) + .cursor(1, 3000); + + // actual search + AggregationResult res = client.ftAggregate(index, r); + assertEquals(2, res.getTotalResults()); + + Row row = res.getRow(0); + assertNotNull(row); + assertEquals("def", row.getString("name")); + assertEquals(30, row.getLong("sum")); + assertEquals(30., row.getDouble("sum"), 0); + + assertEquals(0L, row.getLong("nosuchcol")); + assertEquals(0.0, row.getDouble("nosuchcol"), 0); + assertEquals("", row.getString("nosuchcol")); + + res = client.ftCursorRead(index, res.getCursorId(), 1); + Row row2 = res.getRow(0); + assertNotNull(row2); + assertEquals("abc", row2.getString("name")); + assertEquals(10, row2.getLong("sum")); + + assertEquals("OK", client.ftCursorDel(index, res.getCursorId())); + + try { + client.ftCursorRead(index, res.getCursorId(), 1); + fail(); + } catch (JedisDataException e) { + } + } + + @Test + public void aggregateIteration() { + client.ftCreate(index, TextField.of("name").sortable(), NumericField.of("count")); + + addDocument(new Document("data1").set("name", "abc").set("count", 10)); + addDocument(new Document("data2").set("name", "def").set("count", 5)); + addDocument(new Document("data3").set("name", "def").set("count", 25)); + addDocument(new Document("data4").set("name", "ghi").set("count", 15)); + addDocument(new Document("data5").set("name", "jkl").set("count", 20)); + + AggregationBuilder agg = new AggregationBuilder() + .groupBy("@name", Reducers.sum("@count").as("sum")) + .sortBy(10, SortedField.desc("@sum")) + .cursor(2, 10000); + + FtAggregateIteration rr = client.ftAggregateIteration(index, agg); + int total = 0; + while (!rr.isIterationCompleted()) { + AggregationResult res = rr.nextBatch(); + int count = res.getRows().size(); + assertThat(count, Matchers.lessThanOrEqualTo(2)); + total += count; + } + assertEquals(4, total); + } + + @Test + public void aggregateIterationCollect() { + client.ftCreate(index, TextField.of("name").sortable(), NumericField.of("count")); + + addDocument(new Document("data1").set("name", "abc").set("count", 10)); + addDocument(new Document("data2").set("name", "def").set("count", 5)); + addDocument(new Document("data3").set("name", "def").set("count", 25)); + addDocument(new Document("data4").set("name", "ghi").set("count", 15)); + addDocument(new Document("data5").set("name", "jkl").set("count", 20)); + + AggregationBuilder agg = new AggregationBuilder() + .groupBy("@name", Reducers.sum("@count").as("sum")) + .sortBy(10, SortedField.desc("@sum")) + .cursor(2, 10000); + + assertEquals(4, client.ftAggregateIteration(index, agg).collect(new ArrayList<>()).size()); + } + + @Test + public void testWrongAggregation() throws InterruptedException { + Schema sc = new Schema() + .addTextField("title", 5.0) + .addTextField("body", 1.0) + .addTextField("state", 1.0) + .addNumericField("price"); + + client.ftCreate(index, IndexOptions.defaultOptions(), sc); + + // insert document(s) + Map fields = new HashMap<>(); + fields.put("title", "hello world"); + fields.put("state", "NY"); + fields.put("body", "lorem ipsum"); + fields.put("price", "1337"); +// client.addDocument("doc1", fields); + addDocument("doc1", fields); + + // wrong aggregation query + AggregationBuilder builder = new AggregationBuilder("hello") + .apply("@price/1000", "k") + .groupBy("@state", Reducers.avg("@k").as("avgprice")) + .filter("@avgprice>=2") + .sortBy(10, SortedField.asc("@state")); + + try { + client.ftAggregate(index, builder); + fail(); + } catch (JedisDataException e) { + // should throw JedisDataException on wrong aggregation query + } + } +} diff --git a/src/test/java/redis/clients/jedis/modules/search/DocumentTest.java b/src/test/java/redis/clients/jedis/modules/search/DocumentTest.java index faa03fe513..490837ebd4 100644 --- a/src/test/java/redis/clients/jedis/modules/search/DocumentTest.java +++ b/src/test/java/redis/clients/jedis/modules/search/DocumentTest.java @@ -1,6 +1,5 @@ package redis.clients.jedis.modules.search; -import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import java.io.ByteArrayInputStream; @@ -9,10 +8,11 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.HashMap; +import java.util.Locale; import java.util.Map; + import org.junit.Test; import redis.clients.jedis.search.Document; -import redis.clients.jedis.util.SafeEncoder; public class DocumentTest { @@ -23,8 +23,7 @@ public void serialize() throws IOException, ClassNotFoundException { Map map = new HashMap<>(); map.put("string", "c"); map.put("float", 12d); - byte[] payload = "1a".getBytes(); - Document document = new Document(id, map, score, payload); + Document document = new Document(id, map, score); ByteArrayOutputStream aos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(aos); @@ -39,9 +38,10 @@ public void serialize() throws IOException, ClassNotFoundException { assertEquals(id, read.getId()); assertEquals(score, read.getScore(), 0d); - assertArrayEquals(payload, read.getPayload()); - String exp = String.format("id:%s, score: %.1f, payload:%s, properties:%s", - id, score, SafeEncoder.encode(payload), "[string=c, float=12.0]") ; + + // use english language to make sure the decimal separator is the same as the toString + String exp = String.format(Locale.ENGLISH, "id:%s, score: %.1f, properties:%s", + id, score, "[string=c, float=12.0]"); assertEquals(exp, read.toString()); assertEquals("c", read.getString("string")); assertEquals(Double.valueOf(12d), read.get("float")); @@ -49,21 +49,6 @@ public void serialize() throws IOException, ClassNotFoundException { @Test public void toStringTest() { - String id = "9f"; - double score = 10d; - Map map = new HashMap<>(); - map.put("string", "c"); - map.put("float", 12d); - byte[] payload = "1a".getBytes(); - Document document = new Document(id, map, score, payload); - - String expected = String.format("id:%s, score: %.1f, payload:%s, properties:%s", - id, score, SafeEncoder.encode(payload), "[string=c, float=12.0]") ; - assertEquals(expected, document.toString()); - } - - @Test - public void toStringWithoutPayload() { String id = "9f"; double score = 10d; Map map = new HashMap<>(); @@ -71,8 +56,9 @@ public void toStringWithoutPayload() { map.put("float", 12d); Document document = new Document(id, map, score); - String expected = String.format("id:%s, score: %.1f, payload:%s, properties:%s", - id, score, null, "[string=c, float=12.0]") ; + // use english language to make sure the decimal separator is the same as the toString + String expected = String.format(Locale.ENGLISH, "id:%s, score: %.1f, properties:%s", + id, score, "[string=c, float=12.0]"); assertEquals(expected, document.toString()); } } diff --git a/src/test/java/redis/clients/jedis/modules/search/JsonSearchTest.java b/src/test/java/redis/clients/jedis/modules/search/JsonSearchTest.java index e426a0e40e..79485634d7 100644 --- a/src/test/java/redis/clients/jedis/modules/search/JsonSearchTest.java +++ b/src/test/java/redis/clients/jedis/modules/search/JsonSearchTest.java @@ -142,23 +142,22 @@ public void parseJson() { setJson(id, json); // query - SearchResult sr = client.ftSearch(index, new Query().setWithScores().setWithPayload()); + SearchResult sr = client.ftSearch(index, new Query().setWithScores()); assertEquals(1, sr.getTotalResults()); Document doc = sr.getDocuments().get(0); assertEquals(1.0, doc.getScore(), 0); - assertNull(doc.getPayload()); assertEquals(json.toString(), doc.get(JSON_ROOT)); // query repeat - sr = client.ftSearch(index, new Query().setWithScores().setWithPayload()); + sr = client.ftSearch(index, new Query().setWithScores()); doc = sr.getDocuments().get(0); JSONObject jsonRead = new JSONObject((String) doc.get(JSON_ROOT)); assertEquals(json.toString(), jsonRead.toString()); // query repeat - sr = client.ftSearch(index, new Query().setWithScores().setWithPayload()); + sr = client.ftSearch(index, new Query().setWithScores()); doc = sr.getDocuments().get(0); jsonRead = new JSONObject(doc.getString(JSON_ROOT)); diff --git a/src/test/java/redis/clients/jedis/modules/search/QueryBuilderTest.java b/src/test/java/redis/clients/jedis/modules/search/QueryBuilderTest.java index a63b625f50..7f152f8985 100644 --- a/src/test/java/redis/clients/jedis/modules/search/QueryBuilderTest.java +++ b/src/test/java/redis/clients/jedis/modules/search/QueryBuilderTest.java @@ -91,10 +91,10 @@ public void testIntersectionBasic() { @Test public void testIntersectionNested() { - Node n = intersect(). - add(union("name", value("mark"), value("dvir"))). - add("time", between(100, 200)). - add(disjunct("created", lt(1000))); + Node n = intersect() + .add(union("name", value("mark"), value("dvir"))) + .add("time", between(100, 200)) + .add(disjunct("created", lt(1000))); assertEquals("(@name:(mark|dvir) @time:[100 200] -@created:[-inf (1000])", n.toString()); } diff --git a/src/test/java/redis/clients/jedis/modules/search/SchemaTest.java b/src/test/java/redis/clients/jedis/modules/search/SchemaTest.java index e7917e3f48..c0153e258e 100644 --- a/src/test/java/redis/clients/jedis/modules/search/SchemaTest.java +++ b/src/test/java/redis/clients/jedis/modules/search/SchemaTest.java @@ -1,10 +1,10 @@ package redis.clients.jedis.modules.search; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertThrows; import java.util.Collections; -import org.hamcrest.CoreMatchers; -import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; import org.junit.Test; import redis.clients.jedis.search.FieldName; import redis.clients.jedis.search.Schema; @@ -31,9 +31,9 @@ public void printSchemaTest() throws Exception { .addVectorField(VECTOR, Schema.VectorField.VectorAlgo.HNSW, Collections.emptyMap()); String schemaPrint = sc.toString(); - MatcherAssert.assertThat(schemaPrint, CoreMatchers.startsWith("Schema{fields=[TextField{name='title'")); - MatcherAssert.assertThat(schemaPrint, CoreMatchers.containsString("{name='release_year', type=NUMERIC, sortable=true, noindex=false}")); - MatcherAssert.assertThat(schemaPrint, CoreMatchers.containsString("VectorField{name='vector', type=VECTOR, algorithm=HNSW")); + assertThat(schemaPrint, Matchers.startsWith("Schema{fields=[TextField{name='title'")); + assertThat(schemaPrint, Matchers.containsString("{name='release_year', type=NUMERIC, sortable=true, noindex=false}")); + assertThat(schemaPrint, Matchers.containsString("VectorField{name='vector', type=VECTOR, algorithm=HNSW")); } @Test diff --git a/src/test/java/redis/clients/jedis/modules/search/SearchConfigTest.java b/src/test/java/redis/clients/jedis/modules/search/SearchConfigTest.java index f89b081e60..bda3cbe4d1 100644 --- a/src/test/java/redis/clients/jedis/modules/search/SearchConfigTest.java +++ b/src/test/java/redis/clients/jedis/modules/search/SearchConfigTest.java @@ -2,13 +2,11 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; import java.util.Collections; import java.util.Map; import org.junit.BeforeClass; import org.junit.Test; -import redis.clients.jedis.exceptions.JedisDataException; import redis.clients.jedis.modules.RedisModuleCommandsTestBase; public class SearchConfigTest extends RedisModuleCommandsTestBase { @@ -25,12 +23,14 @@ public static void prepare() { @Test public void config() { - Map map = client.ftConfigGet("TIMEOUT"); + Map map = client.ftConfigGet("TIMEOUT"); assertEquals(1, map.size()); - String value = map.get("TIMEOUT"); - assertNotNull(value); - - assertEquals("OK", client.ftConfigSet("timeout", value)); + String value = (String) map.get("TIMEOUT"); + try { + assertNotNull(value); + } finally { + assertEquals("OK", client.ftConfigSet("timeout", value)); + } } @Test @@ -38,11 +38,14 @@ public void configOnTimeout() { // confirm default assertEquals(Collections.singletonMap("ON_TIMEOUT", "return"), client.ftConfigGet("ON_TIMEOUT")); - assertEquals("OK", client.ftConfigSet("ON_TIMEOUT", "fail")); - assertEquals(Collections.singletonMap("ON_TIMEOUT", "fail"), client.ftConfigGet("ON_TIMEOUT")); + try { + assertEquals("OK", client.ftConfigSet("ON_TIMEOUT", "fail")); + assertEquals(Collections.singletonMap("ON_TIMEOUT", "fail"), client.ftConfigGet("ON_TIMEOUT")); - // restore to default - assertEquals("OK", client.ftConfigSet("ON_TIMEOUT", "return")); + } finally { + // restore to default + assertEquals("OK", client.ftConfigSet("ON_TIMEOUT", "return")); + } } @Test @@ -50,10 +53,13 @@ public void dialectConfig() { // confirm default assertEquals(Collections.singletonMap("DEFAULT_DIALECT", "1"), client.ftConfigGet("DEFAULT_DIALECT")); - assertEquals("OK", client.ftConfigSet("DEFAULT_DIALECT", "2")); - assertEquals(Collections.singletonMap("DEFAULT_DIALECT", "2"), client.ftConfigGet("DEFAULT_DIALECT")); + try { + assertEquals("OK", client.ftConfigSet("DEFAULT_DIALECT", "2")); + assertEquals(Collections.singletonMap("DEFAULT_DIALECT", "2"), client.ftConfigGet("DEFAULT_DIALECT")); - // restore to default - assertEquals("OK", client.ftConfigSet("DEFAULT_DIALECT", "1")); + } finally { + // restore to default + assertEquals("OK", client.ftConfigSet("DEFAULT_DIALECT", "1")); + } } } diff --git a/src/test/java/redis/clients/jedis/modules/search/SearchDefaultDialectTest.java b/src/test/java/redis/clients/jedis/modules/search/SearchDefaultDialectTest.java new file mode 100644 index 0000000000..b803b1eceb --- /dev/null +++ b/src/test/java/redis/clients/jedis/modules/search/SearchDefaultDialectTest.java @@ -0,0 +1,194 @@ +package redis.clients.jedis.modules.search; + +import static org.junit.Assert.*; +import static redis.clients.jedis.util.AssertUtil.assertOK; + +import java.util.*; + +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import redis.clients.jedis.exceptions.JedisDataException; +import redis.clients.jedis.search.*; +import redis.clients.jedis.search.schemafields.NumericField; +import redis.clients.jedis.search.schemafields.TextField; +import redis.clients.jedis.modules.RedisModuleCommandsTestBase; +import redis.clients.jedis.search.aggr.AggregationBuilder; +import redis.clients.jedis.search.aggr.AggregationResult; +import redis.clients.jedis.search.aggr.Reducers; +import redis.clients.jedis.search.aggr.Row; + +public class SearchDefaultDialectTest extends RedisModuleCommandsTestBase { + + private static final String INDEX = "dialect-INDEX"; + private static final int DEFAULT_DIALECT = 2; + + @BeforeClass + public static void prepare() { + RedisModuleCommandsTestBase.prepare(); + } + + @Override + public void setUp() { + super.setUp(); + client.setDefaultSearchDialect(DEFAULT_DIALECT); + } +// +// @AfterClass +// public static void tearDown() { +//// RedisModuleCommandsTestBase.tearDown(); +// } + + private void addDocument(Document doc) { + String key = doc.getId(); + Map map = new LinkedHashMap<>(); + doc.getProperties().forEach(entry -> map.put(entry.getKey(), String.valueOf(entry.getValue()))); + client.hset(key, map); + } + + @Test + public void testQueryParams() { + Schema sc = new Schema().addNumericField("numval"); + assertEquals("OK", client.ftCreate(INDEX, IndexOptions.defaultOptions(), sc)); + + client.hset("1", "numval", "1"); + client.hset("2", "numval", "2"); + client.hset("3", "numval", "3"); + + Query query = new Query("@numval:[$min $max]").addParam("min", 1).addParam("max", 2); + assertEquals(2, client.ftSearch(INDEX, query).getTotalResults()); + } + + @Test + public void testQueryParamsWithParams() { + assertOK(client.ftCreate(INDEX, NumericField.of("numval"))); + + client.hset("1", "numval", "1"); + client.hset("2", "numval", "2"); + client.hset("3", "numval", "3"); + + assertEquals(2, client.ftSearch(INDEX, "@numval:[$min $max]", + FTSearchParams.searchParams().addParam("min", 1).addParam("max", 2)).getTotalResults()); + + Map paramValues = new HashMap<>(); + paramValues.put("min", 1); + paramValues.put("max", 2); + assertEquals(2, client.ftSearch(INDEX, "@numval:[$min $max]", + FTSearchParams.searchParams().params(paramValues)).getTotalResults()); + } + + @Test + public void testDialectsWithFTExplain() throws Exception { + Map attr = new HashMap<>(); + attr.put("TYPE", "FLOAT32"); + attr.put("DIM", 2); + attr.put("DISTANCE_METRIC", "L2"); + + Schema sc = new Schema() + .addFlatVectorField("v", attr) + .addTagField("title") + .addTextField("t1", 1.0) + .addTextField("t2", 1.0) + .addNumericField("num"); + assertEquals("OK", client.ftCreate(INDEX, IndexOptions.defaultOptions(), sc)); + + client.hset("1", "t1", "hello"); + + String q = "(*)"; + Query query = new Query(q).dialect(1); + try { + client.ftExplain(INDEX, query); + fail(); + } catch (JedisDataException e) { + assertTrue("Should contain 'Syntax error'", e.getMessage().contains("Syntax error")); + } + query = new Query(q); // dialect=default=2 + assertTrue("Should contain 'WILDCARD'", client.ftExplain(INDEX, query).contains("WILDCARD")); + + q = "$hello"; + query = new Query(q).dialect(1); + try { + client.ftExplain(INDEX, query); + fail(); + } catch (JedisDataException e) { + assertTrue("Should contain 'Syntax error'", e.getMessage().contains("Syntax error")); + } + query = new Query(q).addParam("hello", "hello"); // dialect=default=2 + assertTrue("Should contain 'UNION {\n hello\n +hello(expanded)\n}\n'", + client.ftExplain(INDEX, query).contains("UNION {\n hello\n +hello(expanded)\n}\n")); + + q = "@title:(@num:[0 10])"; + query = new Query(q).dialect(1); + assertTrue("Should contain 'NUMERIC {0.000000 <= @num <= 10.000000}'", + client.ftExplain(INDEX, query).contains("NUMERIC {0.000000 <= @num <= 10.000000}")); + query = new Query(q); // dialect=default=2 + try { + client.ftExplain(INDEX, query); + fail(); + } catch (JedisDataException e) { + assertTrue("Should contain 'Syntax error'", e.getMessage().contains("Syntax error")); + } + + q = "@t1:@t2:@t3:hello"; + query = new Query(q).dialect(1); + assertTrue("Should contain '@NULL:UNION {\n @NULL:hello\n @NULL:+hello(expanded)\n}\n'", + client.ftExplain(INDEX, query).contains("@NULL:UNION {\n @NULL:hello\n @NULL:+hello(expanded)\n}\n")); + query = new Query(q); // dialect=default=2 + try { + client.ftExplain(INDEX, query); + fail(); + } catch (JedisDataException e) { + assertTrue("Should contain 'Syntax error'", e.getMessage().contains("Syntax error")); + } + + q = "@title:{foo}}}}}"; + query = new Query(q).dialect(1); + assertTrue("Should contain 'TAG:@title {\n foo\n}\n'", + client.ftExplain(INDEX, query).contains("TAG:@title {\n foo\n}\n")); + query = new Query(q); // dialect=default=2 + try { + client.ftExplain(INDEX, query); + fail(); + } catch (JedisDataException e) { + assertTrue("Should contain 'Syntax error'", e.getMessage().contains("Syntax error")); + } + } + + @Test + public void testAggregationBuilderParamsDialect() { + Schema sc = new Schema(); + sc.addSortableTextField("name", 1.0); + sc.addSortableNumericField("count"); + client.ftCreate(INDEX, IndexOptions.defaultOptions(), sc); + addDocument(new Document("data1").set("name", "abc").set("count", 10)); + addDocument(new Document("data2").set("name", "def").set("count", 5)); + addDocument(new Document("data3").set("name", "def").set("count", 25)); + + Map params = new HashMap<>(); + params.put("name", "abc"); + + AggregationBuilder r = new AggregationBuilder("$name") + .groupBy("@name", Reducers.sum("@count").as("sum")) + .params(params); + + AggregationResult res = client.ftAggregate(INDEX, r); + assertEquals(1, res.getTotalResults()); + + Row r1 = res.getRow(0); + assertNotNull(r1); + assertEquals("abc", r1.getString("name")); + assertEquals(10, r1.getLong("sum")); + } + + @Test + public void dialectBoundSpellCheck() { + client.ftCreate(INDEX, TextField.of("t")); + JedisDataException error = Assert.assertThrows(JedisDataException.class, + () -> client.ftSpellCheck(INDEX, "Tooni toque kerfuffle", + FTSpellCheckParams.spellCheckParams().dialect(0))); + MatcherAssert.assertThat(error.getMessage(), Matchers.containsString("DIALECT requires a non negative integer")); + } +} diff --git a/src/test/java/redis/clients/jedis/modules/search/SearchTest.java b/src/test/java/redis/clients/jedis/modules/search/SearchTest.java index 5805b6255a..b8656ff344 100644 --- a/src/test/java/redis/clients/jedis/modules/search/SearchTest.java +++ b/src/test/java/redis/clients/jedis/modules/search/SearchTest.java @@ -3,9 +3,13 @@ import static org.junit.Assert.*; import java.util.*; +import java.util.stream.Collectors; +import org.hamcrest.Matchers; +import org.junit.Assume; import org.junit.BeforeClass; import org.junit.Test; +import redis.clients.jedis.RedisProtocol; import redis.clients.jedis.exceptions.JedisDataException; import redis.clients.jedis.json.Path; import redis.clients.jedis.search.*; @@ -154,11 +158,6 @@ public void alterAdd() throws Exception { } SearchResult res2 = client.ftSearch(index, new Query("@tags:{tagA}")); assertEquals(100, res2.getTotalResults()); - - Map info = client.ftInfo(index); - assertEquals(index, info.get("index_name")); - assertEquals("identifier", ((List) ((List) info.get("attributes")).get(1)).get(0)); - assertEquals("attribute", ((List) ((List) info.get("attributes")).get(1)).get(2)); } @Test @@ -372,8 +371,13 @@ public void testQueryFlags() throws Exception { res = client.ftSearch(index, q); for (Document d : res.getDocuments()) { assertTrue(d.getId().startsWith("doc")); - assertEquals(1.0, d.getScore(), 0); - assertNull(d.get("title")); + if (protocol != RedisProtocol.RESP3) { + assertEquals(1.0, d.getScore(), 0); + assertNull(d.get("title")); + } else { + assertNull(d.getScore()); + assertThrows(NullPointerException.class, () -> d.get("title")); + } } // test verbatim vs. stemming @@ -643,8 +647,13 @@ public void info() throws Exception { Map info = client.ftInfo(index); assertEquals(index, info.get("index_name")); assertEquals(6, ((List) info.get("attributes")).size()); - assertEquals("global_idle", ((List) info.get("cursor_stats")).get(0)); - assertEquals(0L, ((List) info.get("cursor_stats")).get(1)); + if (protocol != RedisProtocol.RESP3) { + assertEquals("global_idle", ((List) info.get("cursor_stats")).get(0)); + assertEquals(0L, ((List) info.get("cursor_stats")).get(1)); + } else { + assertEquals(0L, ((Map) info.get("cursor_stats")).get("global_idle")); + assertEquals(128L, ((Map) info.get("cursor_stats")).get("index_capacity")); + } } @Test @@ -891,6 +900,8 @@ public void inKeys() throws Exception { @Test public void blobField() throws Exception { + Assume.assumeFalse(protocol == RedisProtocol.RESP3); // not supporting + Schema sc = new Schema().addTextField("field1", 1.0); assertEquals("OK", client.ftCreate(index, IndexOptions.defaultOptions(), sc)); @@ -1122,6 +1133,43 @@ public void testDialectsWithFTExplain() throws Exception { assertTrue("Should contain '{K=10 nearest vector'", client.ftExplain(index, query).contains("{K=10 nearest vector")); } + @Test + public void searchProfile() { + Schema sc = new Schema().addTextField("t1", 1.0).addTextField("t2", 1.0); + assertEquals("OK", client.ftCreate(index, IndexOptions.defaultOptions(), sc)); + + Map hash = new HashMap<>(); + hash.put("t1", "foo"); + hash.put("t2", "bar"); + client.hset("doc1", hash); + + Map.Entry> reply = client.ftProfileSearch(index, + FTProfileParams.profileParams(), new Query("foo")); + + SearchResult result = reply.getKey(); + assertEquals(1, result.getTotalResults()); + assertEquals(Collections.singletonList("doc1"), result.getDocuments().stream().map(Document::getId).collect(Collectors.toList())); + + Map profile = reply.getValue(); + Map iteratorsProfile; + if (protocol != RedisProtocol.RESP3) { + iteratorsProfile = (Map) profile.get("Iterators profile"); + } else { + List iteratorsProfileList = (List) profile.get("Iterators profile"); + assertEquals(1, iteratorsProfileList.size()); + iteratorsProfile = (Map) iteratorsProfileList.get(0); + } + assertEquals("TEXT", iteratorsProfile.get("Type")); + assertEquals("foo", iteratorsProfile.get("Term")); + assertEquals(1L, iteratorsProfile.get("Counter")); + assertEquals(1L, iteratorsProfile.get("Size")); + assertSame(Double.class, iteratorsProfile.get("Time").getClass()); + + assertEquals(Arrays.asList("Index", "Scorer", "Sorter", "Loader"), + ((List>) profile.get("Result processors profile")).stream() + .map(map -> map.get("Type")).collect(Collectors.toList())); + } + @Test public void testHNSWVVectorSimilarity() { Map attr = new HashMap<>(); @@ -1146,13 +1194,18 @@ public void testHNSWVVectorSimilarity() { assertEquals("0", doc1.get("__v_score")); // profile - Map.Entry> profile + Map.Entry> reply = client.ftProfileSearch(index, FTProfileParams.profileParams(), query); - doc1 = profile.getKey().getDocuments().get(0); + doc1 = reply.getKey().getDocuments().get(0); assertEquals("a", doc1.getId()); assertEquals("0", doc1.get("__v_score")); - Map iteratorsProfile = (Map) profile.getValue().get("Iterators profile"); - assertEquals("VECTOR", iteratorsProfile.get("Type")); + if (protocol != RedisProtocol.RESP3) { + assertEquals("VECTOR", ((Map) reply.getValue().get("Iterators profile")).get("Type")); + } else { + assertEquals(Arrays.asList("VECTOR"), + ((List>) reply.getValue().get("Iterators profile")).stream() + .map(map -> map.get("Type")).collect(Collectors.toList())); + } } @Test @@ -1179,33 +1232,42 @@ public void testFlatVectorSimilarity() { assertEquals("0", doc1.get("__v_score")); // profile - Map.Entry> profile + Map.Entry> reply = client.ftProfileSearch(index, FTProfileParams.profileParams(), query); - doc1 = profile.getKey().getDocuments().get(0); + doc1 = reply.getKey().getDocuments().get(0); assertEquals("a", doc1.getId()); assertEquals("0", doc1.get("__v_score")); - Map iteratorsProfile = (Map) profile.getValue().get("Iterators profile"); - assertEquals("VECTOR", iteratorsProfile.get("Type")); + if (protocol != RedisProtocol.RESP3) { + assertEquals("VECTOR", ((Map) reply.getValue().get("Iterators profile")).get("Type")); + } else { + assertEquals(Arrays.asList("VECTOR"), + ((List>) reply.getValue().get("Iterators profile")).stream() + .map(map -> map.get("Type")).collect(Collectors.toList())); + } } @Test - public void searchProfile() { - Schema sc = new Schema().addTextField("t1", 1.0).addTextField("t2", 1.0); - assertEquals("OK", client.ftCreate(index, IndexOptions.defaultOptions(), sc)); + public void searchIteration() throws Exception { + Schema sc = new Schema().addTextField("first", 1.0).addTextField("last", 1.0).addNumericField("age"); + IndexDefinition rule = new IndexDefinition(); + assertEquals("OK", client.ftCreate(index, IndexOptions.defaultOptions().setDefinition(rule), sc)); - Map map = new HashMap<>(); - map.put("t1", "foo"); - map.put("t2", "bar"); - client.hset("doc1", map); + client.hset("profesor:5555", toMap("first", "Albert", "last", "Blue", "age", "55")); + client.hset("student:1111", toMap("first", "Joe", "last", "Dod", "age", "18")); + client.hset("pupil:2222", toMap("first", "Jen", "last", "Rod", "age", "14")); + client.hset("student:3333", toMap("first", "El", "last", "Mark", "age", "17")); + client.hset("pupil:4444", toMap("first", "Pat", "last", "Shu", "age", "21")); + client.hset("student:5555", toMap("first", "Joen", "last", "Ko", "age", "20")); + client.hset("teacher:6666", toMap("first", "Pat", "last", "Rod", "age", "20")); - Map.Entry> profile = client.ftProfileSearch(index, - FTProfileParams.profileParams(), new Query("foo")); - // Iterators profile={Type=TEXT, Time=0.0, Term=foo, Counter=1, Size=1} - Map iteratorsProfile = (Map) profile.getValue().get("Iterators profile"); - assertEquals("TEXT", iteratorsProfile.get("Type")); - assertEquals("foo", iteratorsProfile.get("Term")); - assertEquals(1L, iteratorsProfile.get("Counter")); - assertEquals(1L, iteratorsProfile.get("Size")); - assertSame(Double.class, iteratorsProfile.get("Time").getClass()); + FtSearchIteration search = client.ftSearchIteration(3, index, new Query()); + int total = 0; + while (!search.isIterationCompleted()) { + SearchResult result = search.nextBatch(); + int count = result.getDocuments().size(); + assertThat(count, Matchers.lessThanOrEqualTo(3)); + total += count; + } + assertEquals(7, total); } } diff --git a/src/test/java/redis/clients/jedis/modules/search/SearchWithParamsTest.java b/src/test/java/redis/clients/jedis/modules/search/SearchWithParamsTest.java index 76d4201bc5..a81ceb7821 100644 --- a/src/test/java/redis/clients/jedis/modules/search/SearchWithParamsTest.java +++ b/src/test/java/redis/clients/jedis/modules/search/SearchWithParamsTest.java @@ -1,15 +1,25 @@ package redis.clients.jedis.modules.search; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.*; import static redis.clients.jedis.util.AssertUtil.assertOK; import java.util.*; -import java.util.function.Supplier; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; +import org.hamcrest.Matchers; import org.junit.BeforeClass; import org.junit.Test; +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.GeometryFactory; +import org.locationtech.jts.geom.Point; +import org.locationtech.jts.geom.Polygon; +import org.locationtech.jts.io.ParseException; +import org.locationtech.jts.io.WKTReader; + import redis.clients.jedis.GeoCoordinate; +import redis.clients.jedis.RedisProtocol; import redis.clients.jedis.args.GeoUnit; import redis.clients.jedis.args.SortingOrder; import redis.clients.jedis.exceptions.JedisDataException; @@ -163,11 +173,6 @@ public void alterAdd() { } SearchResult res2 = client.ftSearch(index, "@tags:{tagA}"); assertEquals(100, res2.getTotalResults()); - - Map info = client.ftInfo(index); - assertEquals(index, info.get("index_name")); - assertEquals("identifier", ((List) ((List) info.get("attributes")).get(1)).get(0)); - assertEquals("attribute", ((List) ((List) info.get("attributes")).get(1)).get(2)); } @Test @@ -337,6 +342,100 @@ public void geoFilterAndGeoCoordinateObject() { assertEquals(2, res.getTotalResults()); } + @Test + public void geoShapeFilterSpherical() throws ParseException { + final WKTReader reader = new WKTReader(); + final GeometryFactory factory = new GeometryFactory(); + + assertOK(client.ftCreate(index, GeoShapeField.of("geom", GeoShapeField.CoordinateSystem.SPHERICAL))); + + // polygon type + final Polygon small = factory.createPolygon(new Coordinate[]{new Coordinate(34.9001, 29.7001), + new Coordinate(34.9001, 29.7100), new Coordinate(34.9100, 29.7100), + new Coordinate(34.9100, 29.7001), new Coordinate(34.9001, 29.7001)}); + client.hset("small", "geom", small.toString()); + + final Polygon large = factory.createPolygon(new Coordinate[]{new Coordinate(34.9001, 29.7001), + new Coordinate(34.9001, 29.7200), new Coordinate(34.9200, 29.7200), + new Coordinate(34.9200, 29.7001), new Coordinate(34.9001, 29.7001)}); + client.hset("large", "geom", large.toString()); + + // within condition + final Polygon within = factory.createPolygon(new Coordinate[]{new Coordinate(34.9000, 29.7000), + new Coordinate(34.9000, 29.7150), new Coordinate(34.9150, 29.7150), + new Coordinate(34.9150, 29.7000), new Coordinate(34.9000, 29.7000)}); + + SearchResult res = client.ftSearch(index, "@geom:[within $poly]", + FTSearchParams.searchParams().addParam("poly", within).dialect(3)); + assertEquals(1, res.getTotalResults()); + assertEquals(1, res.getDocuments().size()); + assertEquals(small, reader.read(res.getDocuments().get(0).getString("geom"))); + + // contains condition + final Polygon contains = factory.createPolygon(new Coordinate[]{new Coordinate(34.9002, 29.7002), + new Coordinate(34.9002, 29.7050), new Coordinate(34.9050, 29.7050), + new Coordinate(34.9050, 29.7002), new Coordinate(34.9002, 29.7002)}); + + res = client.ftSearch(index, "@geom:[contains $poly]", + FTSearchParams.searchParams().addParam("poly", contains).dialect(3)); + assertEquals(2, res.getTotalResults()); + assertEquals(2, res.getDocuments().size()); + + // point type + final Point point = factory.createPoint(new Coordinate(34.9010, 29.7010)); + client.hset("point", "geom", point.toString()); + + res = client.ftSearch(index, "@geom:[within $poly]", + FTSearchParams.searchParams().addParam("poly", within).dialect(3)); + assertEquals(2, res.getTotalResults()); + assertEquals(2, res.getDocuments().size()); + } + + @Test + public void geoShapeFilterFlat() throws ParseException { + final WKTReader reader = new WKTReader(); + final GeometryFactory factory = new GeometryFactory(); + + assertOK(client.ftCreate(index, GeoShapeField.of("geom", GeoShapeField.CoordinateSystem.FLAT))); + + // polygon type + final Polygon small = factory.createPolygon(new Coordinate[]{new Coordinate(1, 1), + new Coordinate(1, 100), new Coordinate(100, 100), new Coordinate(100, 1), new Coordinate(1, 1)}); + client.hset("small", "geom", small.toString()); + + final Polygon large = factory.createPolygon(new Coordinate[]{new Coordinate(1, 1), + new Coordinate(1, 200), new Coordinate(200, 200), new Coordinate(200, 1), new Coordinate(1, 1)}); + client.hset("large", "geom", large.toString()); + + // within condition + final Polygon within = factory.createPolygon(new Coordinate[]{new Coordinate(0, 0), + new Coordinate(0, 150), new Coordinate(150, 150), new Coordinate(150, 0), new Coordinate(0, 0)}); + + SearchResult res = client.ftSearch(index, "@geom:[within $poly]", + FTSearchParams.searchParams().addParam("poly", within).dialect(3)); + assertEquals(1, res.getTotalResults()); + assertEquals(1, res.getDocuments().size()); + assertEquals(small, reader.read(res.getDocuments().get(0).getString("geom"))); + + // contains condition + final Polygon contains = factory.createPolygon(new Coordinate[]{new Coordinate(2, 2), + new Coordinate(2, 50), new Coordinate(50, 50), new Coordinate(50, 2), new Coordinate(2, 2)}); + + res = client.ftSearch(index, "@geom:[contains $poly]", + FTSearchParams.searchParams().addParam("poly", contains).dialect(3)); + assertEquals(2, res.getTotalResults()); + assertEquals(2, res.getDocuments().size()); + + // point type + final Point point = factory.createPoint(new Coordinate(10, 10)); + client.hset("point", "geom", point.toString()); + + res = client.ftSearch(index, "@geom:[within $poly]", + FTSearchParams.searchParams().addParam("poly", within).dialect(3)); + assertEquals(2, res.getTotalResults()); + assertEquals(2, res.getDocuments().size()); + } + @Test public void testQueryFlags() { assertOK(client.ftCreate(index, TextField.of("title"))); @@ -371,8 +470,13 @@ public void testQueryFlags() { FTSearchParams.searchParams().noContent()); for (Document d : res.getDocuments()) { assertTrue(d.getId().startsWith("doc")); - assertEquals(1.0, d.getScore(), 0); - assertNull(d.get("title")); + if (protocol != RedisProtocol.RESP3) { + assertEquals(1.0, d.getScore(), 0); + assertNull(d.get("title")); + } else { + assertNull(d.getScore()); + assertThrows(NullPointerException.class, () -> d.get("title")); + } } // test verbatim vs. stemming @@ -566,8 +670,12 @@ public void info() { Map info = client.ftInfo(index); assertEquals(index, info.get("index_name")); assertEquals(6, ((List) info.get("attributes")).size()); - assertEquals("global_idle", ((List) info.get("cursor_stats")).get(0)); - assertEquals(0L, ((List) info.get("cursor_stats")).get(1)); + if (protocol != RedisProtocol.RESP3) { + assertEquals("global_idle", ((List) info.get("cursor_stats")).get(0)); + assertEquals(0L, ((List) info.get("cursor_stats")).get(1)); + } else { + assertEquals(0L, ((Map) info.get("cursor_stats")).get("global_idle")); + } } @Test @@ -945,20 +1053,36 @@ public void testFlatVectorSimilarity() { public void searchProfile() { assertOK(client.ftCreate(index, TextField.of("t1"), TextField.of("t2"))); - Map map = new HashMap<>(); - map.put("t1", "foo"); - map.put("t2", "bar"); - client.hset("doc1", map); + Map hash = new HashMap<>(); + hash.put("t1", "foo"); + hash.put("t2", "bar"); + client.hset("doc1", hash); - Map.Entry> profile = client.ftProfileSearch(index, + Map.Entry> reply = client.ftProfileSearch(index, FTProfileParams.profileParams(), "foo", FTSearchParams.searchParams()); - // Iterators profile={Type=TEXT, Time=0.0, Term=foo, Counter=1, Size=1} - Map iteratorsProfile = (Map) profile.getValue().get("Iterators profile"); + + SearchResult result = reply.getKey(); + assertEquals(1, result.getTotalResults()); + assertEquals(Collections.singletonList("doc1"), result.getDocuments().stream().map(Document::getId).collect(Collectors.toList())); + + Map profile = reply.getValue(); + Map iteratorsProfile; + if (protocol != RedisProtocol.RESP3) { + iteratorsProfile = (Map) profile.get("Iterators profile"); + } else { + List iteratorsProfileList = (List) profile.get("Iterators profile"); + assertEquals(1, iteratorsProfileList.size()); + iteratorsProfile = (Map) iteratorsProfileList.get(0); + } assertEquals("TEXT", iteratorsProfile.get("Type")); assertEquals("foo", iteratorsProfile.get("Term")); assertEquals(1L, iteratorsProfile.get("Counter")); assertEquals(1L, iteratorsProfile.get("Size")); assertSame(Double.class, iteratorsProfile.get("Time").getClass()); + + assertEquals(Arrays.asList("Index", "Scorer", "Sorter", "Loader"), + ((List>) profile.get("Result processors profile")).stream() + .map(map -> map.get("Type")).collect(Collectors.toList())); } @Test @@ -976,109 +1100,140 @@ public void vectorSearchProfile() { FTSearchParams searchParams = FTSearchParams.searchParams().addParam("vec", "aaaaaaaa") .sortBy("__v_score", SortingOrder.ASC).noContent().dialect(2); - Map.Entry> profile = client.ftProfileSearch(index, + Map.Entry> reply = client.ftProfileSearch(index, FTProfileParams.profileParams(), "*=>[KNN 3 @v $vec]", searchParams); - assertEquals(3, profile.getKey().getTotalResults()); + assertEquals(3, reply.getKey().getTotalResults()); - assertEquals(Arrays.asList(4, 2, 1).toString(), profile.getKey().getDocuments() + assertEquals(Arrays.asList(4, 2, 1).toString(), reply.getKey().getDocuments() .stream().map(Document::getId).collect(Collectors.toList()).toString()); - Map iteratorsProfile = (Map) profile.getValue().get("Iterators profile"); - assertEquals("VECTOR", iteratorsProfile.get("Type")); - assertEquals(3L, iteratorsProfile.get("Counter")); + Map profile = reply.getValue(); + + if (protocol != RedisProtocol.RESP3) { + assertEquals("VECTOR", ((Map) profile.get("Iterators profile")).get("Type")); + } else { + assertEquals(Arrays.asList("VECTOR"), + ((List>) profile.get("Iterators profile")).stream() + .map(map -> map.get("Type")).collect(Collectors.toList())); + } - List> resultProcessorsProfile = (List>) profile.getValue().get("Result processors profile"); - assertEquals("Vector Similarity Scores Loader", resultProcessorsProfile.get(1).get("Type")); - assertEquals(3l, resultProcessorsProfile.get(1).get("Counter")); + List> resultProcessorsProfile + = (List>) reply.getValue().get("Result processors profile"); + assertEquals(3, resultProcessorsProfile.size()); + assertEquals("Index", resultProcessorsProfile.get(0).get("Type")); + assertEquals("Sorter", resultProcessorsProfile.get(2).get("Type")); } @Test public void maxPrefixExpansionSearchProfile() { final String configParam = "MAXPREFIXEXPANSIONS"; - String configValue = client.ftConfigGet(configParam).get(configParam); - client.ftConfigSet(configParam, "2"); - - assertOK(client.ftCreate(index, TextField.of("t"))); - client.hset("1", Collections.singletonMap("t", "foo1")); - client.hset("2", Collections.singletonMap("t", "foo2")); - client.hset("3", Collections.singletonMap("t", "foo3")); - - Map.Entry> profile = client.ftProfileSearch(index, - FTProfileParams.profileParams(), "foo*", FTSearchParams.searchParams().limit(0, 0)); - // Warning=Max prefix expansion reached - Map iteratorsProfile = (Map) profile.getValue().get("Iterators profile"); - assertEquals("Max prefix expansion reached", iteratorsProfile.get("Warning")); - - client.ftConfigSet(configParam, configValue); + String configValue = (String) client.ftConfigGet(configParam).get(configParam); + try { + client.ftConfigSet(configParam, "2"); + + assertOK(client.ftCreate(index, TextField.of("t"))); + client.hset("1", "t", "foo1"); + client.hset("2", "t", "foo2"); + client.hset("3", "t", "foo3"); + + Map.Entry> reply = client.ftProfileSearch(index, + FTProfileParams.profileParams(), "foo*", FTSearchParams.searchParams().limit(0, 0)); + // Warning=Max prefix expansion reached + if (protocol != RedisProtocol.RESP3) { + assertEquals("Max prefix expansion reached", + ((Map) reply.getValue().get("Iterators profile")).get("Warning")); + } else { + assertEquals("Max prefix expansion reached", + ((Map) ((List) reply.getValue().get("Iterators profile")).get(0)).get("Warning")); + } + } finally { + client.ftConfigSet(configParam, configValue); + } } @Test - public void notIteratorSearchProfile() { + public void noContentSearchProfile() { assertOK(client.ftCreate(index, TextField.of("t"))); - client.hset("1", Collections.singletonMap("t", "foo")); - client.hset("2", Collections.singletonMap("t", "bar")); + client.hset("1", "t", "foo"); + client.hset("2", "t", "bar"); Map.Entry> profile = client.ftProfileSearch(index, FTProfileParams.profileParams(), "foo -@t:baz", FTSearchParams.searchParams().noContent()); - Map depth0 = (Map) profile.getValue().get("Iterators profile"); + Map depth0 = protocol != RedisProtocol.RESP3 + ? (Map) profile.getValue().get("Iterators profile") + : ((List>) profile.getValue().get("Iterators profile")).get(0); + assertEquals("INTERSECT", depth0.get("Type")); List> depth0_children = (List>) depth0.get("Child iterators"); assertEquals("TEXT", depth0_children.get(0).get("Type")); Map depth1 = depth0_children.get(1); assertEquals("NOT", depth1.get("Type")); - List> depth1_children = (List>) depth1.get("Child iterators"); - assertEquals(1, depth1_children.size()); - assertEquals("EMPTY", depth1_children.get(0).get("Type")); + if (protocol != RedisProtocol.RESP3) { + List> depth1_children = (List>) depth1.get("Child iterators"); + assertEquals(1, depth1_children.size()); + assertEquals("EMPTY", depth1_children.get(0).get("Type")); + } else { + assertEquals("EMPTY", ((Map) depth1.get("Child iterator")).get("Type")); + } } @Test public void deepReplySearchProfile() { assertOK(client.ftCreate(index, TextField.of("t"))); - client.hset("1", Collections.singletonMap("t", "hello")); - client.hset("2", Collections.singletonMap("t", "world")); + client.hset("1", "t", "hello"); + client.hset("2", "t", "world"); Map.Entry> profile = client.ftProfileSearch(index, FTProfileParams.profileParams(), "hello(hello(hello(hello(hello(hello)))))", FTSearchParams.searchParams().noContent()); - Map depth0 = (Map) profile.getValue().get("Iterators profile"); - assertEquals("INTERSECT", depth0.get("Type")); - List> depth0_children = (List>) depth0.get("Child iterators"); - assertEquals("TEXT", depth0_children.get(0).get("Type")); - Map depth1 = depth0_children.get(1); - assertEquals("INTERSECT", depth1.get("Type")); - List> depth1_children = (List>) depth1.get("Child iterators"); - assertEquals("TEXT", depth1_children.get(0).get("Type")); - Map depth2 = depth1_children.get(1); - assertEquals("INTERSECT", depth2.get("Type")); - List> depth2_children = (List>) depth2.get("Child iterators"); - assertEquals("TEXT", depth2_children.get(0).get("Type")); - Map depth3 = depth2_children.get(1); - assertEquals("INTERSECT", depth3.get("Type")); - List> depth3_children = (List>) depth3.get("Child iterators"); - assertEquals("TEXT", depth3_children.get(0).get("Type")); - Map depth4 = depth3_children.get(1); - assertEquals("INTERSECT", depth4.get("Type")); - List> depth4_children = (List>) depth4.get("Child iterators"); - assertEquals("TEXT", depth4_children.get(0).get("Type")); - Map depth5 = depth4_children.get(1); - assertEquals("TEXT", depth5.get("Type")); - assertNull(depth5.get("Child iterators")); + Map depth0 = protocol != RedisProtocol.RESP3 + ? (Map) profile.getValue().get("Iterators profile") + : ((List>) profile.getValue().get("Iterators profile")).get(0); + + AtomicInteger intersectLevelCount = new AtomicInteger(); + AtomicInteger textLevelCount = new AtomicInteger(); + deepReplySearchProfile_assertProfile(depth0, intersectLevelCount, textLevelCount); + assertThat(intersectLevelCount.get(), Matchers.greaterThan(0)); + assertThat(textLevelCount.get(), Matchers.greaterThan(0)); + } + + private void deepReplySearchProfile_assertProfile(Map attr, + AtomicInteger intersectLevelCount, AtomicInteger textLevelCount) { + + String type = (String) attr.get("Type"); + assertThat(type, Matchers.not(Matchers.blankOrNullString())); + + switch (type) { + case "INTERSECT": + assertThat(attr, Matchers.hasKey("Child iterators")); + intersectLevelCount.incrementAndGet(); + deepReplySearchProfile_assertProfile((Map) ((List) attr.get("Child iterators")).get(0), + intersectLevelCount, textLevelCount); + break; + case "TEXT": + assertThat(attr, Matchers.hasKey("Term")); + textLevelCount.incrementAndGet(); + break; + } } @Test public void limitedSearchProfile() { assertOK(client.ftCreate(index, TextField.of("t"))); - client.hset("1", Collections.singletonMap("t", "hello")); - client.hset("2", Collections.singletonMap("t", "hell")); - client.hset("3", Collections.singletonMap("t", "help")); - client.hset("4", Collections.singletonMap("t", "helowa")); + client.hset("1", "t", "hello"); + client.hset("2", "t", "hell"); + client.hset("3", "t", "help"); + client.hset("4", "t", "helowa"); Map.Entry> profile = client.ftProfileSearch(index, FTProfileParams.profileParams().limited(), "%hell% hel*", FTSearchParams.searchParams().noContent()); - Map depth0 = (Map) profile.getValue().get("Iterators profile"); + Map depth0 = protocol != RedisProtocol.RESP3 + ? (Map) profile.getValue().get("Iterators profile") + : ((List>) profile.getValue().get("Iterators profile")).get(0); + assertEquals("INTERSECT", depth0.get("Type")); assertEquals(3L, depth0.get("Counter")); @@ -1087,15 +1242,19 @@ public void limitedSearchProfile() { for (Map depth1 : depth0_children) { assertEquals("UNION", depth1.get("Type")); assertNotNull(depth1.get("Query type")); - List depth1_children = (List) depth1.get("Child iterators"); - assertEquals(1, depth1_children.size()); - assertSame(String.class, depth1_children.get(0).getClass()); + if (protocol != RedisProtocol.RESP3) { + List depth1_children = (List) depth1.get("Child iterators"); + assertEquals(1, depth1_children.size()); + assertSame(String.class, depth1_children.get(0).getClass()); + } else { + assertSame(String.class, depth1.get("Child iterators").getClass()); + } } } @Test public void list() { - assertEquals(Collections.emptyList(), client.ftList()); + assertEquals(Collections.emptySet(), client.ftList()); final int count = 20; Set names = new HashSet<>(); @@ -1104,13 +1263,97 @@ public void list() { assertOK(client.ftCreate(name, TextField.of("t" + i))); names.add(name); } - assertEquals(names, new HashSet<>(client.ftList())); + assertEquals(names, client.ftList()); } @Test public void broadcast() { - Map> reply = client.broadcast().ftCreate(index, TextField.of("t")); - assertEquals(1, reply.size()); - assertOK(reply.values().stream().findFirst().get().get()); + String reply = client.ftCreate(index, TextField.of("t")); + assertOK(reply); + } + + @Test + public void searchIteration() { + assertOK(client.ftCreate(index, FTCreateParams.createParams(), + TextField.of("first"), TextField.of("last"), NumericField.of("age"))); + + client.hset("profesor:5555", toMap("first", "Albert", "last", "Blue", "age", "55")); + client.hset("student:1111", toMap("first", "Joe", "last", "Dod", "age", "18")); + client.hset("pupil:2222", toMap("first", "Jen", "last", "Rod", "age", "14")); + client.hset("student:3333", toMap("first", "El", "last", "Mark", "age", "17")); + client.hset("pupil:4444", toMap("first", "Pat", "last", "Shu", "age", "21")); + client.hset("student:5555", toMap("first", "Joen", "last", "Ko", "age", "20")); + client.hset("teacher:6666", toMap("first", "Pat", "last", "Rod", "age", "20")); + + FtSearchIteration search = client.ftSearchIteration(3, index, "*", FTSearchParams.searchParams()); + int total = 0; + while (!search.isIterationCompleted()) { + SearchResult result = search.nextBatch(); + int count = result.getDocuments().size(); + assertThat(count, Matchers.lessThanOrEqualTo(3)); + total += count; + } + assertEquals(7, total); + } + + @Test + public void searchIterationCollect() { + assertOK(client.ftCreate(index, FTCreateParams.createParams(), + TextField.of("first"), TextField.of("last"), NumericField.of("age"))); + + client.hset("profesor:5555", toMap("first", "Albert", "last", "Blue", "age", "55")); + client.hset("student:1111", toMap("first", "Joe", "last", "Dod", "age", "18")); + client.hset("pupil:2222", toMap("first", "Jen", "last", "Rod", "age", "14")); + client.hset("student:3333", toMap("first", "El", "last", "Mark", "age", "17")); + client.hset("pupil:4444", toMap("first", "Pat", "last", "Shu", "age", "21")); + client.hset("student:5555", toMap("first", "Joen", "last", "Ko", "age", "20")); + client.hset("teacher:6666", toMap("first", "Pat", "last", "Rod", "age", "20")); + + ArrayList collect = new ArrayList<>(); + client.ftSearchIteration(3, index, "*", FTSearchParams.searchParams()).collect(collect); + assertEquals(7, collect.size()); + assertEquals(Arrays.asList("profesor:5555", "student:1111", "pupil:2222", "student:3333", + "pupil:4444", "student:5555", "teacher:6666").stream().collect(Collectors.toSet()), + collect.stream().map(Document::getId).collect(Collectors.toSet())); + } + + @Test + public void escapeUtil() { + assertOK(client.ftCreate(index, TextField.of("txt"))); + + client.hset("doc1", "txt", RediSearchUtil.escape("hello-world")); + assertNotEquals("hello-world", client.hget("doc1", "txt")); + assertEquals("hello-world", RediSearchUtil.unescape(client.hget("doc1", "txt"))); + + SearchResult resultNoEscape = client.ftSearch(index, "hello-world"); + assertEquals(0, resultNoEscape.getTotalResults()); + + SearchResult resultEscaped = client.ftSearch(index, RediSearchUtil.escapeQuery("hello-world")); + assertEquals(1, resultEscaped.getTotalResults()); + } + + @Test + public void escapeMapUtil() { + client.hset("doc2", RediSearchUtil.toStringMap(Collections.singletonMap("txt", "hello-world"), true)); + assertNotEquals("hello-world", client.hget("doc2", "txt")); + assertEquals("hello-world", RediSearchUtil.unescape(client.hget("doc2", "txt"))); + } + + @Test + public void hsetObject() { + float[] floats = new float[]{0.2f}; + assertEquals(1L, client.hsetObject("obj", "floats", floats)); + assertArrayEquals(RediSearchUtil.toByteArray(floats), + client.hget("obj".getBytes(), "floats".getBytes())); + + GeoCoordinate geo = new GeoCoordinate(-0.441, 51.458); + Map fields = new HashMap<>(); + fields.put("title", "hello world"); + fields.put("loc", geo); + assertEquals(2L, client.hsetObject("obj", fields)); + Map stringMap = client.hgetAll("obj"); + assertEquals(3, stringMap.size()); + assertEquals("hello world", stringMap.get("title")); + assertEquals(geo.getLongitude() + "," + geo.getLatitude(), stringMap.get("loc")); } } diff --git a/src/test/java/redis/clients/jedis/modules/search/SpellCheckTest.java b/src/test/java/redis/clients/jedis/modules/search/SpellCheckTest.java index ae1ec64334..508ff4441a 100644 --- a/src/test/java/redis/clients/jedis/modules/search/SpellCheckTest.java +++ b/src/test/java/redis/clients/jedis/modules/search/SpellCheckTest.java @@ -1,9 +1,6 @@ package redis.clients.jedis.modules.search; -import static org.hamcrest.CoreMatchers.containsString; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertThrows; import java.util.Arrays; import java.util.Collections; @@ -11,6 +8,9 @@ import java.util.HashSet; import java.util.Map; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; +import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; @@ -52,7 +52,8 @@ public void dictionary() { @Test public void dictionaryBySampleKey() { assertEquals(3L, client.ftDictAddBySampleKey(index, "dict", "foo", "bar", "hello world")); - assertEquals(new HashSet<>(Arrays.asList("foo", "bar", "hello world")), client.ftDictDumpBySampleKey(index, "dict")); + assertEquals(new HashSet<>(Arrays.asList("foo", "bar", "hello world")), + client.ftDictDumpBySampleKey(index, "dict")); assertEquals(3L, client.ftDictDelBySampleKey(index, "dict", "foo", "bar", "hello world")); assertEquals(Collections.emptySet(), client.ftDictDumpBySampleKey(index, "dict")); } @@ -61,8 +62,8 @@ public void dictionaryBySampleKey() { public void basicSpellCheck() { client.ftCreate(index, TextField.of("name"), TextField.of("body")); client.hset("doc1", toMap("name", "name1", "body", "body1")); - client.hset("doc1", toMap("name", "name2", "body", "body2")); - client.hset("doc1", toMap("name", "name2", "body", "name2")); + client.hset("doc2", toMap("name", "name2", "body", "body2")); + client.hset("doc3", toMap("name", "name2", "body", "name2")); Map> reply = client.ftSpellCheck(index, "name"); assertEquals(Collections.singleton("name"), reply.keySet()); @@ -74,7 +75,8 @@ public void crossTermDictionary() { client.ftCreate(index, TextField.of("report")); client.ftDictAdd("slang", "timmies", "toque", "toonie", "serviette", "kerfuffle", "chesterfield"); - Map> expected = Collections.singletonMap("tooni", Collections.singletonMap("toonie", 0d)); + Map> expected = Collections.singletonMap("tooni", + Collections.singletonMap("toonie", 0d)); assertEquals(expected, client.ftSpellCheck(index, "Tooni toque kerfuffle", FTSpellCheckParams.spellCheckParams().includeTerm("slang").excludeTerm("slang"))); } @@ -82,16 +84,17 @@ public void crossTermDictionary() { @Test public void distanceBound() { client.ftCreate(index, TextField.of("name"), TextField.of("body")); - assertThrows(JedisDataException.class, () -> client.ftSpellCheck(index, "name", + Assert.assertThrows(JedisDataException.class, () -> client.ftSpellCheck(index, "name", FTSpellCheckParams.spellCheckParams().distance(0))); } @Test public void dialectBound() { client.ftCreate(index, TextField.of("t")); - JedisDataException error = assertThrows(JedisDataException.class, + JedisDataException error = Assert.assertThrows(JedisDataException.class, () -> client.ftSpellCheck(index, "Tooni toque kerfuffle", FTSpellCheckParams.spellCheckParams().dialect(0))); - assertThat(error.getMessage(), containsString("DIALECT requires a non negative integer")); + MatcherAssert.assertThat(error.getMessage(), + Matchers.containsString("DIALECT requires a non negative integer")); } } diff --git a/src/test/java/redis/clients/jedis/modules/search/UtilTest.java b/src/test/java/redis/clients/jedis/modules/search/UtilTest.java new file mode 100644 index 0000000000..830b52565a --- /dev/null +++ b/src/test/java/redis/clients/jedis/modules/search/UtilTest.java @@ -0,0 +1,32 @@ +package redis.clients.jedis.modules.search; + +import static org.junit.Assert.assertEquals; + +import org.junit.Assert; +import org.junit.Test; + +import redis.clients.jedis.search.RediSearchUtil; + +import redis.clients.jedis.search.schemafields.NumericField; +import redis.clients.jedis.search.schemafields.SchemaField; + +public class UtilTest { + + @Test + public void floatArrayToByteArray() { + float[] floats = new float[]{0.2f}; + byte[] bytes = RediSearchUtil.toByteArray(floats); + byte[] expected = new byte[]{-51, -52, 76, 62}; + Assert.assertArrayEquals(expected, bytes); + } + + @Test + public void getSchemaFieldName() { + SchemaField field = NumericField.of("$.num").as("num"); + + assertEquals("$.num", field.getFieldName().getName()); + assertEquals("num", field.getFieldName().getAttribute()); + + assertEquals("$.num", field.getName()); + } +} diff --git a/src/test/java/redis/clients/jedis/modules/timeseries/TimeSeriesTest.java b/src/test/java/redis/clients/jedis/modules/timeseries/TimeSeriesTest.java index f0b8c2b99a..12c424f9e1 100644 --- a/src/test/java/redis/clients/jedis/modules/timeseries/TimeSeriesTest.java +++ b/src/test/java/redis/clients/jedis/modules/timeseries/TimeSeriesTest.java @@ -6,10 +6,12 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static redis.clients.jedis.util.AssertUtil.assertEqualsByProtocol; import java.util.*; import org.junit.BeforeClass; import org.junit.Test; +import redis.clients.jedis.RedisProtocol; import redis.clients.jedis.exceptions.JedisDataException; import redis.clients.jedis.modules.RedisModuleCommandsTestBase; @@ -199,7 +201,7 @@ public void testAdd() { assertEquals(expectedOverallMaxValues, values); // MRANGE - assertEquals(Collections.emptyList(), client.tsMRange(TSMRangeParams.multiRangeParams().filter("l=v"))); + assertEquals(Collections.emptyMap(), client.tsMRange(TSMRangeParams.multiRangeParams().filter("l=v"))); try { client.tsMRange(TSMRangeParams.multiRangeParams(500L, 4600L).aggregation(AggregationType.COUNT, 1)); fail(); @@ -214,11 +216,11 @@ public void testAdd() { } catch (IllegalArgumentException e) { } - List ranges = client.tsMRange(TSMRangeParams.multiRangeParams(500L, 4600L) + Map ranges = client.tsMRange(TSMRangeParams.multiRangeParams(500L, 4600L) .aggregation(AggregationType.COUNT, 1).filter("l1=v1")); assertEquals(1, ranges.size()); - TSKeyedElements range = ranges.get(0); + TSMRangeElements range = ranges.values().stream().findAny().get(); assertEquals("seriesAdd", range.getKey()); assertEquals(Collections.emptyMap(), range.getLabels()); @@ -234,10 +236,12 @@ public void testAdd() { labels2.put("l3", "v3"); labels2.put("l4", "v4"); assertEquals(1000L, client.tsAdd("seriesAdd2", 1000L, 1.1, TSCreateParams.createParams().retention(10000).labels(labels2))); - List ranges2 = client.tsMRange(TSMRangeParams.multiRangeParams(500L, 4600L) + Map ranges2 = client.tsMRange(TSMRangeParams.multiRangeParams(500L, 4600L) .aggregation(AggregationType.COUNT, 1).withLabels().filter("l4=v4")); assertEquals(1, ranges2.size()); - assertEquals(labels2, ranges2.get(0).getLabels()); + TSMRangeElements elements2 = ranges2.values().stream().findAny().get(); + assertEquals(labels2, elements2.getLabels()); + assertEqualsByProtocol(protocol, null, Arrays.asList(AggregationType.COUNT), elements2.getAggregators()); Map labels3 = new HashMap<>(); labels3.put("l3", "v33"); @@ -245,13 +249,16 @@ public void testAdd() { assertEquals(1000L, client.tsAdd("seriesAdd3", 1000L, 1.1, TSCreateParams.createParams().labels(labels3))); assertEquals(2000L, client.tsAdd("seriesAdd3", 2000L, 1.1, TSCreateParams.createParams().labels(labels3))); assertEquals(3000L, client.tsAdd("seriesAdd3", 3000L, 1.1, TSCreateParams.createParams().labels(labels3))); - List ranges3 = client.tsMRange(TSMRangeParams.multiRangeParams(500L, 4600L) + Map ranges3 = client.tsMRange(TSMRangeParams.multiRangeParams(500L, 4600L) .aggregation(AggregationType.AVG, 1L).withLabels(true).count(2).filter("l4=v4")); assertEquals(2, ranges3.size()); - assertEquals(1, ranges3.get(0).getValue().size()); - assertEquals(labels2, ranges3.get(0).getLabels()); - assertEquals(2, ranges3.get(1).getValue().size()); - assertEquals(labels3, ranges3.get(1).getLabels()); + ArrayList ranges3List = new ArrayList<>(ranges3.values()); + assertEquals(1, ranges3List.get(0).getValue().size()); + assertEquals(labels2, ranges3List.get(0).getLabels()); + assertEqualsByProtocol(protocol, null, Arrays.asList(AggregationType.AVG), ranges3List.get(0).getAggregators()); + assertEquals(2, ranges3List.get(1).getValue().size()); + assertEquals(labels3, ranges3List.get(1).getLabels()); + assertEqualsByProtocol(protocol, null, Arrays.asList(AggregationType.AVG), ranges3List.get(1).getAggregators()); assertEquals(800L, client.tsAdd("seriesAdd", 800L, 1.1)); assertEquals(700L, client.tsAdd("seriesAdd", 700L, 1.1, TSCreateParams.createParams().retention(10000))); @@ -487,50 +494,58 @@ public void mrangeFilterBy() { client.tsAdd("ts1", rawValues[3].getTimestamp(), rawValues[3].getValue()); // MRANGE - List range = client.tsMRange(0L, 5000L, filter); - assertEquals("ts1", range.get(0).getKey()); - assertEquals(Arrays.asList(rawValues[0], rawValues[3]), range.get(0).getValue()); - assertEquals("ts2", range.get(1).getKey()); - assertEquals(Arrays.asList(rawValues[1], rawValues[2]), range.get(1).getValue()); + Map range = client.tsMRange(0L, 5000L, filter); + ArrayList rangeList = new ArrayList<>(range.values()); + assertEquals("ts1", rangeList.get(0).getKey()); + assertEquals(Arrays.asList(rawValues[0], rawValues[3]), rangeList.get(0).getValue()); + assertEquals("ts2", rangeList.get(1).getKey()); + assertEquals(Arrays.asList(rawValues[1], rawValues[2]), rangeList.get(1).getValue()); range = client.tsMRange(TSMRangeParams.multiRangeParams(0L, 5000L).filterByTS(1000L, 2000L).filter(filter)); - assertEquals("ts1", range.get(0).getKey()); - assertEquals(Arrays.asList(rawValues[0]), range.get(0).getValue()); - assertEquals("ts2", range.get(1).getKey()); - assertEquals(Arrays.asList(rawValues[1]), range.get(1).getValue()); + rangeList = new ArrayList<>(range.values()); + assertEquals("ts1", rangeList.get(0).getKey()); + assertEquals(Arrays.asList(rawValues[0]), rangeList.get(0).getValue()); + assertEquals("ts2", rangeList.get(1).getKey()); + assertEquals(Arrays.asList(rawValues[1]), rangeList.get(1).getValue()); range = client.tsMRange(TSMRangeParams.multiRangeParams(0L, 5000L).filterByValues(1.0, 1.2).filter(filter)); - assertEquals("ts1", range.get(0).getKey()); - assertEquals(Arrays.asList(rawValues[0]), range.get(0).getValue()); - assertEquals("ts2", range.get(1).getKey()); - assertEquals(Arrays.asList(rawValues[2]), range.get(1).getValue()); + rangeList = new ArrayList<>(range.values()); + assertEquals("ts1", rangeList.get(0).getKey()); + assertEquals(Arrays.asList(rawValues[0]), rangeList.get(0).getValue()); + assertEquals("ts2", rangeList.get(1).getKey()); + assertEquals(Arrays.asList(rawValues[2]), rangeList.get(1).getValue()); range = client.tsMRange(TSMRangeParams.multiRangeParams(0L, 5000L) .filterByTS(1000L, 2000L).filterByValues(1.0, 1.2).filter(filter)); - assertEquals(Arrays.asList(rawValues[0]), range.get(0).getValue()); + rangeList = new ArrayList<>(range.values()); + assertEquals(Arrays.asList(rawValues[0]), rangeList.get(0).getValue()); // MREVRANGE range = client.tsMRevRange(0L, 5000L, filter); - assertEquals("ts1", range.get(0).getKey()); - assertEquals(Arrays.asList(rawValues[3], rawValues[0]), range.get(0).getValue()); - assertEquals("ts2", range.get(1).getKey()); - assertEquals(Arrays.asList(rawValues[2], rawValues[1]), range.get(1).getValue()); + rangeList = new ArrayList<>(range.values()); + assertEquals("ts1", rangeList.get(0).getKey()); + assertEquals(Arrays.asList(rawValues[3], rawValues[0]), rangeList.get(0).getValue()); + assertEquals("ts2", rangeList.get(1).getKey()); + assertEquals(Arrays.asList(rawValues[2], rawValues[1]), rangeList.get(1).getValue()); range = client.tsMRevRange(TSMRangeParams.multiRangeParams(0L, 5000L).filterByTS(1000L, 2000L).filter(filter)); - assertEquals("ts1", range.get(0).getKey()); - assertEquals(Arrays.asList(rawValues[0]), range.get(0).getValue()); - assertEquals("ts2", range.get(1).getKey()); - assertEquals(Arrays.asList(rawValues[1]), range.get(1).getValue()); + rangeList = new ArrayList<>(range.values()); + assertEquals("ts1", rangeList.get(0).getKey()); + assertEquals(Arrays.asList(rawValues[0]), rangeList.get(0).getValue()); + assertEquals("ts2", rangeList.get(1).getKey()); + assertEquals(Arrays.asList(rawValues[1]), rangeList.get(1).getValue()); range = client.tsMRevRange(TSMRangeParams.multiRangeParams(0L, 5000L).filterByValues(1.0, 1.2).filter(filter)); - assertEquals("ts1", range.get(0).getKey()); - assertEquals(Arrays.asList(rawValues[0]), range.get(0).getValue()); - assertEquals("ts2", range.get(1).getKey()); - assertEquals(Arrays.asList(rawValues[2]), range.get(1).getValue()); + rangeList = new ArrayList<>(range.values()); + assertEquals("ts1", rangeList.get(0).getKey()); + assertEquals(Arrays.asList(rawValues[0]), rangeList.get(0).getValue()); + assertEquals("ts2", rangeList.get(1).getKey()); + assertEquals(Arrays.asList(rawValues[2]), rangeList.get(1).getValue()); range = client.tsMRevRange(TSMRangeParams.multiRangeParams(0L, 5000L) .filterByTS(1000L, 2000L).filterByValues(1.0, 1.2).filter(filter)); - assertEquals(Arrays.asList(rawValues[0]), range.get(0).getValue()); + rangeList = new ArrayList<>(range.values()); + assertEquals(Arrays.asList(rawValues[0]), rangeList.get(0).getValue()); } @Test @@ -544,21 +559,32 @@ public void groupByReduce() { // List range = client.tsMRange(TSMRangeParams.multiGetParams(0L, 100L).withLabels() // .groupByReduce("metric_name", "max"), "metric=cpu"); - List range = client.tsMRange(TSMRangeParams.multiRangeParams(0L, 100L).withLabels() + Map range = client.tsMRange(TSMRangeParams.multiRangeParams(0L, 100L).withLabels() .filter("metric=cpu").groupBy("metric_name", "max")); assertEquals(2, range.size()); - - assertEquals("metric_name=system", range.get(0).getKey()); - assertEquals("system", range.get(0).getLabels().get("metric_name")); - assertEquals("max", range.get(0).getLabels().get("__reducer__")); - assertEquals("ts1", range.get(0).getLabels().get("__source__")); - assertEquals(Arrays.asList(new TSElement(1, 90), new TSElement(2, 45)), range.get(0).getValue()); - - assertEquals("metric_name=user", range.get(1).getKey()); - assertEquals("user", range.get(1).getLabels().get("metric_name")); - assertEquals("max", range.get(1).getLabels().get("__reducer__")); - assertEquals("ts2", range.get(1).getLabels().get("__source__")); - assertEquals(Arrays.asList(new TSElement(2, 99)), range.get(1).getValue()); + ArrayList rangeList = new ArrayList<>(range.values()); + + assertEquals("metric_name=system", rangeList.get(0).getKey()); + assertEquals("system", rangeList.get(0).getLabels().get("metric_name")); + if (protocol != RedisProtocol.RESP3) { + assertEquals("max", rangeList.get(0).getLabels().get("__reducer__")); + assertEquals("ts1", rangeList.get(0).getLabels().get("__source__")); + } else { + assertEquals(Arrays.asList("max"), rangeList.get(0).getReducers()); + assertEquals(Arrays.asList("ts1"), rangeList.get(0).getSources()); + } + assertEquals(Arrays.asList(new TSElement(1, 90), new TSElement(2, 45)), rangeList.get(0).getValue()); + + assertEquals("metric_name=user", rangeList.get(1).getKey()); + assertEquals("user", rangeList.get(1).getLabels().get("metric_name")); + if (protocol != RedisProtocol.RESP3) { + assertEquals("max", rangeList.get(1).getLabels().get("__reducer__")); + assertEquals("ts2", rangeList.get(1).getLabels().get("__source__")); + } else { + assertEquals(Arrays.asList("max"), rangeList.get(1).getReducers()); + assertEquals(Arrays.asList("ts2"), rangeList.get(1).getSources()); + } + assertEquals(Arrays.asList(new TSElement(2, 99)), rangeList.get(1).getValue()); } private Map convertMap(String... array) { @@ -604,24 +630,26 @@ public void testMGet() { .retention(100 * 1000 /*100sec retentionTime*/).labels(labels))); // Test for empty result - List> ranges1 = client.tsMGet(TSMGetParams.multiGetParams().withLabels(false), "l1=v2"); + Map ranges1 = client.tsMGet(TSMGetParams.multiGetParams().withLabels(false), "l1=v2"); assertEquals(0, ranges1.size()); // Test for empty ranges - List> ranges2 = client.tsMGet(TSMGetParams.multiGetParams().withLabels(true), "l1=v1"); + Map ranges2 = client.tsMGet(TSMGetParams.multiGetParams().withLabels(true), "l1=v1"); assertEquals(2, ranges2.size()); - assertEquals(labels, ranges2.get(0).getLabels()); - assertEquals(labels, ranges2.get(1).getLabels()); - assertNull(ranges2.get(0).getValue()); + ArrayList ranges2List = new ArrayList<>(ranges2.values()); + assertEquals(labels, ranges2List.get(0).getLabels()); + assertEquals(labels, ranges2List.get(1).getLabels()); + assertNull(ranges2List.get(0).getValue()); // Test for returned result on MGet client.tsAdd("seriesMGet1", 1500, 1.3); - List> ranges3 = client.tsMGet(TSMGetParams.multiGetParams().withLabels(false), "l1=v1"); + Map ranges3 = client.tsMGet(TSMGetParams.multiGetParams().withLabels(false), "l1=v1"); assertEquals(2, ranges3.size()); - assertEquals(Collections.emptyMap(), ranges3.get(0).getLabels()); - assertEquals(Collections.emptyMap(), ranges3.get(1).getLabels()); - assertEquals(new TSElement(1500, 1.3), ranges3.get(0).getValue()); - assertNull(ranges3.get(1).getValue()); + ArrayList ranges3List = new ArrayList<>(ranges3.values()); + assertEquals(Collections.emptyMap(), ranges3List.get(0).getLabels()); + assertEquals(Collections.emptyMap(), ranges3List.get(1).getLabels()); + assertEquals(new TSElement(1500, 1.3), ranges3List.get(0).getValue()); + assertNull(ranges3List.get(1).getValue()); } @Test @@ -746,7 +774,7 @@ public void testRevRange() { @Test public void testMRevRange() { - assertEquals(Collections.emptyList(), client.tsMRevRange(TSMRangeParams.multiRangeParams().filter("l=v"))); + assertEquals(Collections.emptyMap(), client.tsMRevRange(TSMRangeParams.multiRangeParams().filter("l=v"))); Map labels1 = new HashMap<>(); labels1.put("l3", "v3"); @@ -755,11 +783,12 @@ public void testMRevRange() { TSCreateParams.createParams().retention(10000).labels(labels1))); assertEquals(2222L, client.tsAdd("seriesMRevRange1", 2222L, 3.1, TSCreateParams.createParams().retention(10000).labels(labels1))); - List ranges1 = client.tsMRevRange(TSMRangeParams.multiRangeParams(500L, 4600L) + Map ranges1 = client.tsMRevRange(TSMRangeParams.multiRangeParams(500L, 4600L) .aggregation(AggregationType.COUNT, 1).withLabels().filter("l4=v4")); assertEquals(1, ranges1.size()); - assertEquals(labels1, ranges1.get(0).getLabels()); - assertEquals(Arrays.asList(new TSElement(2222L, 1.0), new TSElement(1000L, 1.0)), ranges1.get(0).getValue()); + ArrayList ranges1List = new ArrayList<>(ranges1.values()); + assertEquals(labels1, ranges1List.get(0).getLabels()); + assertEquals(Arrays.asList(new TSElement(2222L, 1.0), new TSElement(1000L, 1.0)), ranges1List.get(0).getValue()); Map labels2 = new HashMap<>(); labels2.put("l3", "v3"); @@ -768,12 +797,13 @@ public void testMRevRange() { TSCreateParams.createParams().retention(10000).labels(labels2))); assertEquals(1111L, client.tsAdd("seriesMRevRange2", 1111L, 99.99, TSCreateParams.createParams().retention(10000).labels(labels2))); - List ranges2 = client.tsMRevRange(500L, 4600L, "l3=v3"); + Map ranges2 = client.tsMRevRange(500L, 4600L, "l3=v3"); assertEquals(2, ranges2.size()); - assertEquals(Collections.emptyMap(), ranges2.get(0).getLabels()); - assertEquals(Arrays.asList(new TSElement(2222L, 3.1), new TSElement(1000L, 1.1)), ranges2.get(0).getValue()); - assertEquals(Collections.emptyMap(), ranges2.get(0).getLabels()); - assertEquals(Arrays.asList(new TSElement(1111L, 99.99), new TSElement(1000L, 8.88)), ranges2.get(1).getValue()); + ArrayList ranges2List = new ArrayList<>(ranges2.values()); + assertEquals(Collections.emptyMap(), ranges2List.get(0).getLabels()); + assertEquals(Arrays.asList(new TSElement(2222L, 3.1), new TSElement(1000L, 1.1)), ranges2List.get(0).getValue()); + assertEquals(Collections.emptyMap(), ranges2List.get(0).getLabels()); + assertEquals(Arrays.asList(new TSElement(1111L, 99.99), new TSElement(1000L, 8.88)), ranges2List.get(1).getValue()); Map labels3 = new HashMap<>(); labels3.put("l3", "v33"); @@ -781,13 +811,14 @@ public void testMRevRange() { assertEquals(2200L, client.tsAdd("seriesMRevRange3", 2200L, -1.1, TSCreateParams.createParams().labels(labels3))); assertEquals(2400L, client.tsAdd("seriesMRevRange3", 2400L, 1.1, TSCreateParams.createParams().labels(labels3))); assertEquals(3300L, client.tsAdd("seriesMRevRange3", 3300L, -33, TSCreateParams.createParams().labels(labels3))); - List ranges3 = client.tsMRevRange(TSMRangeParams.multiRangeParams(500L, 4600L) + Map ranges3 = client.tsMRevRange(TSMRangeParams.multiRangeParams(500L, 4600L) .aggregation(AggregationType.AVG, 500).withLabels().count(5).filter("l4=v4")); assertEquals(2, ranges3.size()); - assertEquals(labels1, ranges3.get(0).getLabels()); - assertEquals(Arrays.asList(new TSElement(2000L, 3.1), new TSElement(1000L, 1.1)), ranges3.get(0).getValue()); - assertEquals(labels3, ranges3.get(1).getLabels()); - assertEquals(Arrays.asList(new TSElement(3000L, -33.0), new TSElement(2000L, 0.0)), ranges3.get(1).getValue()); + ArrayList ranges3List = new ArrayList<>(ranges3.values()); + assertEquals(labels1, ranges3List.get(0).getLabels()); + assertEquals(Arrays.asList(new TSElement(2000L, 3.1), new TSElement(1000L, 1.1)), ranges3List.get(0).getValue()); + assertEquals(labels3, ranges3List.get(1).getLabels()); + assertEquals(Arrays.asList(new TSElement(3000L, -33.0), new TSElement(2000L, 0.0)), ranges3List.get(1).getValue()); } @Test @@ -837,27 +868,35 @@ public void latestMulti() { final TSElement latest = new TSElement(10, 8); // mget - assertEquals(Arrays.asList(new TSKeyValue<>("ts2", null, compact)), + assertEquals(makeSingletonMap(new TSMGetElement("ts2", null, compact)), client.tsMGet(TSMGetParams.multiGetParams(), "compact=true")); - assertEquals(Arrays.asList(new TSKeyValue<>("ts2", null, latest)), + assertEquals(makeSingletonMap(new TSMGetElement("ts2", null, latest)), client.tsMGet(TSMGetParams.multiGetParams().latest(), "compact=true")); // mrange - assertEquals(Arrays.asList(new TSKeyedElements("ts2", null, Arrays.asList(compact))), + assertEquals(makeSingletonMap(new TSMRangeElements("ts2", null, Arrays.asList(compact))), client.tsMRange(TSMRangeParams.multiRangeParams().filter("compact=true"))); - assertEquals(Arrays.asList(new TSKeyedElements("ts2", null, Arrays.asList(compact, latest))), + assertEquals(makeSingletonMap(new TSMRangeElements("ts2", null, Arrays.asList(compact, latest))), client.tsMRange(TSMRangeParams.multiRangeParams().latest().filter("compact=true"))); // mrevrange - assertEquals(Arrays.asList(new TSKeyedElements("ts2", null, Arrays.asList(compact))), + assertEquals(makeSingletonMap(new TSMRangeElements("ts2", null, Arrays.asList(compact))), client.tsMRevRange(TSMRangeParams.multiRangeParams().filter("compact=true"))); - assertEquals(Arrays.asList(new TSKeyedElements("ts2", null, Arrays.asList(latest, compact))), + assertEquals(makeSingletonMap(new TSMRangeElements("ts2", null, Arrays.asList(latest, compact))), client.tsMRevRange(TSMRangeParams.multiRangeParams().latest().filter("compact=true"))); } + private Map makeSingletonMap(TSMGetElement value) { + return Collections.singletonMap(value.getKey(), value); + } + + private Map makeSingletonMap(TSMRangeElements value) { + return Collections.singletonMap(value.getKey(), value); + } + @Test public void empty() { client.tsCreate("ts", TSCreateParams.createParams().label("l", "v")); @@ -881,22 +920,30 @@ public void empty() { assertNotNull(range.get(1).getValue()); // any parsable value // mrange - List mrange = client.tsMRange(TSMRangeParams.multiRangeParams().aggregation(AggregationType.MIN, 5).filter("l=v")); + Map mrange = client.tsMRange(TSMRangeParams.multiRangeParams() + .aggregation(AggregationType.MIN, 5).filter("l=v")); assertEquals(1, mrange.size()); - assertEquals(2, mrange.get(0).getValue().size()); - mrange = client.tsMRange(TSMRangeParams.multiRangeParams().aggregation(AggregationType.MIN, 5).empty().filter("l=v")); + ArrayList mrangeList = new ArrayList<>(mrange.values()); + assertEquals(2, mrangeList.get(0).getValue().size()); + mrange = client.tsMRange(TSMRangeParams.multiRangeParams() + .aggregation(AggregationType.MIN, 5).empty().filter("l=v")); assertEquals(1, mrange.size()); - assertEquals(3, mrange.get(0).getValue().size()); - assertNotNull(mrange.get(0).getValue().get(1).getValue()); // any parsable value + mrangeList = new ArrayList<>(mrange.values()); + assertEquals(3, mrangeList.get(0).getValue().size()); + assertNotNull(mrangeList.get(0).getValue().get(1).getValue()); // any parsable value // mrevrange - mrange = client.tsMRevRange(TSMRangeParams.multiRangeParams().aggregation(AggregationType.MAX, 5).filter("l=v")); + mrange = client.tsMRevRange(TSMRangeParams.multiRangeParams() + .aggregation(AggregationType.MAX, 5).filter("l=v")); assertEquals(1, mrange.size()); - assertEquals(2, mrange.get(0).getValue().size()); - mrange = client.tsMRevRange(TSMRangeParams.multiRangeParams().aggregation(AggregationType.MAX, 5).empty().filter("l=v")); + mrangeList = new ArrayList<>(mrange.values()); + assertEquals(2, mrangeList.get(0).getValue().size()); + mrange = client.tsMRevRange(TSMRangeParams.multiRangeParams() + .aggregation(AggregationType.MAX, 5).empty().filter("l=v")); assertEquals(1, mrange.size()); - assertEquals(3, mrange.get(0).getValue().size()); - assertNotNull(mrange.get(0).getValue().get(1).getValue()); // any parsable value + mrangeList = new ArrayList<>(mrange.values()); + assertEquals(3, mrangeList.get(0).getValue().size()); + assertNotNull(mrangeList.get(0).getValue().get(1).getValue()); // any parsable value } @Test @@ -918,16 +965,21 @@ public void bucketTimestamp() { .aggregation(AggregationType.TWA, 10).bucketTimestamp("mid")).get(0).getTimestamp()); // mrange / mrevrange - assertEquals(0, client.tsMRange(TSMRangeParams.multiRangeParams().aggregation(AggregationType.STD_P, 10) - .bucketTimestampLow().filter("l=v")).get(0).getValue().get(0).getTimestamp()); - assertEquals(10, client.tsMRange(TSMRangeParams.multiRangeParams().aggregation(AggregationType.STD_S, 10) - .bucketTimestampHigh().filter("l=v")).get(0).getValue().get(0).getTimestamp()); - assertEquals(5, client.tsMRange(TSMRangeParams.multiRangeParams().aggregation(AggregationType.TWA, 10) - .bucketTimestampMid().filter("l=v")).get(0).getValue().get(0).getTimestamp()); - assertEquals(5, client.tsMRange(TSMRangeParams.multiRangeParams().aggregation(AggregationType.VAR_P, 10) - .bucketTimestampMid().filter("l=v")).get(0).getValue().get(0).getTimestamp()); - assertEquals(5, client.tsMRange(TSMRangeParams.multiRangeParams().aggregation(AggregationType.VAR_S, 10) - .bucketTimestamp("~").filter("l=v")).get(0).getValue().get(0).getTimestamp()); + assertEquals(0, client.tsMRange(TSMRangeParams.multiRangeParams() + .aggregation(AggregationType.STD_P, 10).bucketTimestampLow().filter("l=v")) + .values().stream().findAny().get().getValue().get(0).getTimestamp()); + assertEquals(10, client.tsMRange(TSMRangeParams.multiRangeParams() + .aggregation(AggregationType.STD_S, 10).bucketTimestampHigh().filter("l=v")) + .values().stream().findAny().get().getValue().get(0).getTimestamp()); + assertEquals(5, client.tsMRange(TSMRangeParams.multiRangeParams() + .aggregation(AggregationType.TWA, 10).bucketTimestampMid().filter("l=v")) + .values().stream().findAny().get().getValue().get(0).getTimestamp()); + assertEquals(5, client.tsMRange(TSMRangeParams.multiRangeParams() + .aggregation(AggregationType.VAR_P, 10).bucketTimestampMid().filter("l=v")) + .values().stream().findAny().get().getValue().get(0).getTimestamp()); + assertEquals(5, client.tsMRange(TSMRangeParams.multiRangeParams() + .aggregation(AggregationType.VAR_S, 10).bucketTimestamp("~").filter("l=v")) + .values().stream().findAny().get().getValue().get(0).getTimestamp()); } @Test diff --git a/src/test/java/redis/clients/jedis/params/ParamsTest.java b/src/test/java/redis/clients/jedis/params/ParamsTest.java deleted file mode 100644 index 6f4dd098de..0000000000 --- a/src/test/java/redis/clients/jedis/params/ParamsTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package redis.clients.jedis.params; - -import static org.hamcrest.MatcherAssert.assertThat; - -import org.hamcrest.CoreMatchers; -import org.junit.Test; -import redis.clients.jedis.args.ClientType; - -public class ParamsTest { - - @Test - public void toStringTest() { - - ClientKillParams clientKillParams = ClientKillParams.clientKillParams() - .addr("127.0.0.1", 6379) - .id("12".getBytes()) - .type(ClientType.NORMAL); - - String toStringResult = clientKillParams.toString(); - assertThat(toStringResult, CoreMatchers.containsString("ID, 12")); - assertThat(toStringResult, CoreMatchers.containsString("TYPE, NORMAL")); - assertThat(toStringResult, CoreMatchers.containsString("127.0.0.1:6379")); - } - -} diff --git a/src/test/java/redis/clients/jedis/providers/MultiClusterPooledConnectionProviderTest.java b/src/test/java/redis/clients/jedis/providers/MultiClusterPooledConnectionProviderTest.java new file mode 100644 index 0000000000..7cf7d3323b --- /dev/null +++ b/src/test/java/redis/clients/jedis/providers/MultiClusterPooledConnectionProviderTest.java @@ -0,0 +1,134 @@ +package redis.clients.jedis.providers; + +import io.github.resilience4j.circuitbreaker.CircuitBreaker; +import org.junit.Before; +import org.junit.Test; +import redis.clients.jedis.*; +import redis.clients.jedis.MultiClusterClientConfig.ClusterConfig; +import redis.clients.jedis.exceptions.JedisConnectionException; +import redis.clients.jedis.exceptions.JedisValidationException; + +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.junit.Assert.*; + +/** + * @see MultiClusterPooledConnectionProvider + */ +public class MultiClusterPooledConnectionProviderTest { + + private final HostAndPort hostAndPort1 = HostAndPorts.getRedisServers().get(0); + private final HostAndPort hostAndPort2 = HostAndPorts.getRedisServers().get(1); + + private MultiClusterPooledConnectionProvider provider; + + @Before + public void setUp() { + + ClusterConfig[] clusterConfigs = new ClusterConfig[2]; + clusterConfigs[0] = new ClusterConfig(hostAndPort1, DefaultJedisClientConfig.builder().build()); + clusterConfigs[1] = new ClusterConfig(hostAndPort2, DefaultJedisClientConfig.builder().build()); + + provider = new MultiClusterPooledConnectionProvider(new MultiClusterClientConfig.Builder(clusterConfigs).build()); + } + + @Test + public void testCircuitBreakerForcedTransitions() { + + CircuitBreaker circuitBreaker = provider.getClusterCircuitBreaker(1); + circuitBreaker.getState(); + + if (CircuitBreaker.State.FORCED_OPEN.equals(circuitBreaker.getState())) + circuitBreaker.transitionToClosedState(); + + circuitBreaker.transitionToForcedOpenState(); + assertEquals(CircuitBreaker.State.FORCED_OPEN, circuitBreaker.getState()); + + circuitBreaker.transitionToClosedState(); + assertEquals(CircuitBreaker.State.CLOSED, circuitBreaker.getState()); + } + + @Test + public void testIncrementActiveMultiClusterIndex() { + int index = provider.incrementActiveMultiClusterIndex(); + assertEquals(2, index); + } + + @Test(expected = JedisConnectionException.class) + public void testIncrementActiveMultiClusterIndexOutOfRange() { + provider.setActiveMultiClusterIndex(1); + + int index = provider.incrementActiveMultiClusterIndex(); + assertEquals(2, index); + + provider.incrementActiveMultiClusterIndex(); // Should throw an exception + } + + @Test + public void testIsLastClusterCircuitBreakerForcedOpen() { + provider.setActiveMultiClusterIndex(1); + + try { + provider.incrementActiveMultiClusterIndex(); + } catch (Exception e) {} + + // This should set the isLastClusterCircuitBreakerForcedOpen to true + try { + provider.incrementActiveMultiClusterIndex(); + } catch (Exception e) {} + + assertEquals(true, provider.isLastClusterCircuitBreakerForcedOpen()); + } + + @Test + public void testRunClusterFailoverPostProcessor() { + ClusterConfig[] clusterConfigs = new ClusterConfig[2]; + clusterConfigs[0] = new ClusterConfig(new HostAndPort("purposefully-incorrect", 0000), + DefaultJedisClientConfig.builder().build()); + clusterConfigs[1] = new ClusterConfig(new HostAndPort("purposefully-incorrect", 0001), + DefaultJedisClientConfig.builder().build()); + + MultiClusterClientConfig.Builder builder = new MultiClusterClientConfig.Builder(clusterConfigs); + + // Configures a single failed command to trigger an open circuit on the next subsequent failure + builder.circuitBreakerSlidingWindowSize(1); + builder.circuitBreakerSlidingWindowMinCalls(1); + + AtomicBoolean isValidTest = new AtomicBoolean(false); + + MultiClusterPooledConnectionProvider localProvider = new MultiClusterPooledConnectionProvider(builder.build()); + localProvider.setClusterFailoverPostProcessor(a -> { isValidTest.set(true); }); + + try (UnifiedJedis jedis = new UnifiedJedis(localProvider)) { + + // This should fail after 3 retries and meet the requirements to open the circuit on the next iteration + try { + jedis.get("foo"); + } catch (Exception e) {} + + // This should fail after 3 retries and open the circuit which will trigger the post processor + try { + jedis.get("foo"); + } catch (Exception e) {} + + } + + assertEquals(true, isValidTest.get()); + } + + @Test(expected = JedisValidationException.class) + public void testSetActiveMultiClusterIndexEqualsZero() { + provider.setActiveMultiClusterIndex(0); // Should throw an exception + } + + @Test(expected = JedisValidationException.class) + public void testSetActiveMultiClusterIndexLessThanZero() { + provider.setActiveMultiClusterIndex(-1); // Should throw an exception + } + + @Test(expected = JedisValidationException.class) + public void testSetActiveMultiClusterIndexOutOfRange() { + provider.setActiveMultiClusterIndex(3); // Should throw an exception + } + +} \ No newline at end of file diff --git a/src/test/java/redis/clients/jedis/resps/ResponsesToStringTest.java b/src/test/java/redis/clients/jedis/resps/ResponsesToStringTest.java deleted file mode 100644 index efa9d6c346..0000000000 --- a/src/test/java/redis/clients/jedis/resps/ResponsesToStringTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package redis.clients.jedis.resps; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.*; - -import org.hamcrest.CoreMatchers; -import org.junit.Test; -import redis.clients.jedis.GeoCoordinate; - -public class ResponsesToStringTest { - - @Test - public void KeyedListElementTest() { - // test equals - KeyedListElement elem = new KeyedListElement("key-name", "elem"); - KeyedListElement elem_copy = new KeyedListElement("key-name", "elem"); - assertEquals(elem, elem); - assertEquals(elem, elem_copy); - assertNotEquals(elem, new Object()); - - // test toString - String toStringResult = elem.toString(); - assertThat(toStringResult, CoreMatchers.containsString("key-name")); - assertThat(toStringResult, CoreMatchers.containsString("elem")); - - // test hashCode - assertEquals(elem.hashCode(), elem_copy.hashCode()); - } - - @Test - public void KeyedZSetElementTest() { - // test equals - KeyedZSetElement elem = new KeyedZSetElement("key-name", "elem", 1d); - KeyedZSetElement elem_copy = new KeyedZSetElement("key-name", "elem", 1d); - assertEquals(elem, elem); - assertEquals(elem, elem_copy); - assertNotEquals(elem, new Object()); - - // test toString - String toStringResult = elem.toString(); - assertThat(toStringResult, CoreMatchers.containsString("key=key-name")); - assertThat(toStringResult, CoreMatchers.containsString("elem")); - assertThat(toStringResult, CoreMatchers.containsString("1")); - - // test hashCode - assertEquals(elem.hashCode(), elem_copy.hashCode()); - } - - @Test - public void GeoRadiusResponse() { - byte[] member = { 0x01, 0x02, 0x03, 0x04 }; - - GeoRadiusResponse response = new GeoRadiusResponse(member); - response.setDistance(5); - response.setCoordinate(new GeoCoordinate(2,3)); - response.setRawScore(10); - - GeoRadiusResponse response_copy = new GeoRadiusResponse(member); - response_copy.setDistance(5); - response_copy.setCoordinate(new GeoCoordinate(2,3)); - response_copy.setRawScore(10); - - assertEquals(response, response); - assertEquals(response, response_copy); - assertNotEquals(response, new Object()); - } -} diff --git a/src/test/java/redis/clients/jedis/util/AssertUtil.java b/src/test/java/redis/clients/jedis/util/AssertUtil.java index aaf3fff59c..5d2ca5518d 100644 --- a/src/test/java/redis/clients/jedis/util/AssertUtil.java +++ b/src/test/java/redis/clients/jedis/util/AssertUtil.java @@ -9,7 +9,9 @@ import java.util.List; import java.util.Objects; import java.util.Set; + import org.junit.ComparisonFailure; +import redis.clients.jedis.RedisProtocol; public class AssertUtil { @@ -17,7 +19,24 @@ public static void assertOK(String str) { assertEquals("OK", str); } - public static boolean assertCollectionContains(Collection array, byte[] expected) { + public static void assertEqualsByProtocol(RedisProtocol protocol, Object expectedResp2, Object expectedResp3, Object actual) { + if (protocol != RedisProtocol.RESP3) { + assertEquals(expectedResp2, actual); + } else { + assertEquals(expectedResp3, actual); + } + } + + public static boolean assertCollectionContains(Collection array, T expected) { + for (T element : array) { + if (Objects.equals(element, expected)) { + return true; + } + } + throw new ComparisonFailure("element is missing", Objects.toString(expected), array.toString()); + } + + public static boolean assertByteArrayCollectionContains(Collection array, byte[] expected) { for (byte[] bytes : array) { if (Arrays.equals(bytes, expected)) { return true; @@ -29,7 +48,7 @@ public static boolean assertCollectionContains(Collection array, byte[] public static void assertByteArrayListEquals(List expected, List actual) { assertEquals(expected.size(), actual.size()); for (int n = 0; n < expected.size(); n++) { - assertArrayEquals(expected.get(n), actual.get(n)); + assertArrayEquals(n + "'th elements don't match", expected.get(n), actual.get(n)); } } diff --git a/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java b/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java index 0a6f743842..be4fded987 100644 --- a/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java +++ b/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java @@ -1,5 +1,7 @@ package redis.clients.jedis.util; +import static redis.clients.jedis.util.JedisURIHelper.*; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; @@ -7,6 +9,7 @@ import java.net.URI; import java.net.URISyntaxException; import org.junit.Test; +import redis.clients.jedis.RedisProtocol; public class JedisURIHelperTest { @@ -57,4 +60,17 @@ public void shouldValidateInvalidURIs() throws URISyntaxException { assertFalse(JedisURIHelper.isValid(new URI("redis://host/0"))); } + @Test + public void shouldGetDefaultProtocolWhenNotDefined() { + assertNull(getRedisProtocol(URI.create("redis://host:1234"))); + assertNull(getRedisProtocol(URI.create("redis://host:1234/1"))); + } + + @Test + public void shouldGetProtocolFromDefinition() { + assertEquals(RedisProtocol.RESP3, getRedisProtocol(URI.create("redis://host:1234?protocol=3"))); + assertEquals(RedisProtocol.RESP3, getRedisProtocol(URI.create("redis://host:1234/?protocol=3"))); + assertEquals(RedisProtocol.RESP3, getRedisProtocol(URI.create("redis://host:1234/1?protocol=3"))); + assertEquals(RedisProtocol.RESP3, getRedisProtocol(URI.create("redis://host:1234/1/?protocol=3"))); + } } diff --git a/src/test/java/redis/clients/jedis/util/JsonObjectMapperTestUtil.java b/src/test/java/redis/clients/jedis/util/JsonObjectMapperTestUtil.java new file mode 100644 index 0000000000..cfec1496b2 --- /dev/null +++ b/src/test/java/redis/clients/jedis/util/JsonObjectMapperTestUtil.java @@ -0,0 +1,92 @@ +package redis.clients.jedis.util; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.google.gson.*; +import redis.clients.jedis.exceptions.JedisException; +import redis.clients.jedis.json.JsonObjectMapper; + +import java.lang.reflect.Type; +import java.time.Instant; +import java.time.format.DateTimeFormatter; +import java.time.temporal.TemporalAccessor; + +public class JsonObjectMapperTestUtil { + public static CustomJacksonObjectMapper getCustomJacksonObjectMapper() { + ObjectMapper om = new ObjectMapper(); + om.registerModule(new JavaTimeModule()); + om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + return new CustomJacksonObjectMapper(om); + } + + public static CustomGsonObjectMapper getCustomGsonObjectMapper() { + final class InstantAdapter implements JsonSerializer, JsonDeserializer { + DateTimeFormatter format = DateTimeFormatter.ISO_INSTANT; + + @Override + public Instant deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + JsonPrimitive primitive = json.getAsJsonPrimitive(); + if (!primitive.isJsonNull()) { + String asString = primitive.getAsString(); + TemporalAccessor temporalAccessor = format.parse(asString); + return Instant.from(temporalAccessor); + } + return null; + } + + @Override + public JsonElement serialize(Instant src, Type typeOfSrc, JsonSerializationContext context) { + return new JsonPrimitive(format.format(src)); + } + } + return new CustomGsonObjectMapper( + new GsonBuilder().registerTypeAdapter(Instant.class, new InstantAdapter()).create()); + } + + public static class CustomJacksonObjectMapper implements JsonObjectMapper { + private final ObjectMapper om; + + CustomJacksonObjectMapper(ObjectMapper om) { + this.om = om; + } + + @Override + public T fromJson(String value, Class valueType) { + try { + return om.readValue(value, valueType); + } catch (JsonProcessingException e) { + throw new JedisException(e); + } + } + + @Override + public String toJson(Object value) { + try { + return om.writeValueAsString(value); + } catch (JsonProcessingException e) { + throw new JedisException(e); + } + } + } + + public static class CustomGsonObjectMapper implements JsonObjectMapper { + private final Gson gson; + + public CustomGsonObjectMapper(Gson gson) { + this.gson = gson; + } + + @Override + public T fromJson(String value, Class valueType) { + return gson.fromJson(value, valueType); + } + + @Override + public String toJson(Object value) { + return gson.toJson(value); + } + } +} diff --git a/src/test/java/redis/clients/jedis/util/RedisProtocolUtil.java b/src/test/java/redis/clients/jedis/util/RedisProtocolUtil.java new file mode 100644 index 0000000000..71f52b42a3 --- /dev/null +++ b/src/test/java/redis/clients/jedis/util/RedisProtocolUtil.java @@ -0,0 +1,21 @@ +package redis.clients.jedis.util; + +import redis.clients.jedis.RedisProtocol; + +public class RedisProtocolUtil { + + public static RedisProtocol getRedisProtocol() { +// return RedisProtocol.RESP2; +// return RedisProtocol.RESP3; + String ver = System.getProperty("jedisProtocol"); + if (ver != null && !ver.isEmpty()) { + for (RedisProtocol proto : RedisProtocol.values()) { + if (proto.version().equals(ver)) { + return proto; + } + } + throw new IllegalArgumentException("Unknown protocol " + ver); + } + return null; + } +} diff --git a/src/test/resources/functions/keyspaceTriggers.js b/src/test/resources/functions/keyspaceTriggers.js new file mode 100644 index 0000000000..2bca56b4dc --- /dev/null +++ b/src/test/resources/functions/keyspaceTriggers.js @@ -0,0 +1,12 @@ +#!js api_version=1.0 name=keyspaceTriggers + +redis.registerKeySpaceTrigger("consumer", "", function(client, data){ + if (client.call("type", data.key) != "hash") { + // key is not a hash, do not touch it. + return; + } + // get the current time in ms + var curr_time = client.call("time")[0]; + // set '__last_updated__' with the current time value + client.call('hset', data.key, '__last_updated__', curr_time); +}); \ No newline at end of file diff --git a/src/test/resources/functions/pingpong.js b/src/test/resources/functions/pingpong.js new file mode 100644 index 0000000000..511013ce16 --- /dev/null +++ b/src/test/resources/functions/pingpong.js @@ -0,0 +1,7 @@ +#!js api_version=1.0 name=pingpong + +function answer(client, data) { + return client.call('ping'); +} + +redis.registerFunction('playPingPong', answer, {description: 'You PING, we PONG'}); \ No newline at end of file diff --git a/src/test/resources/functions/streamTriggers.js b/src/test/resources/functions/streamTriggers.js new file mode 100644 index 0000000000..9d39020d1e --- /dev/null +++ b/src/test/resources/functions/streamTriggers.js @@ -0,0 +1,14 @@ +#!js api_version=1.0 name=streamTriggers + +redis.registerStreamTrigger( + "consumer", // consumer name + "stream", // streams prefix + function(c, data) { + // callback to run on each element added to the stream + redis.log(JSON.stringify(data, (key, value) => + typeof value === 'bigint' + ? value.toString() + : value // return everything else unchanged + )); + } +); \ No newline at end of file diff --git a/src/test/resources/functions/withConfig.js b/src/test/resources/functions/withConfig.js new file mode 100644 index 0000000000..c06944864f --- /dev/null +++ b/src/test/resources/functions/withConfig.js @@ -0,0 +1,16 @@ +#!js api_version=1.0 name=withConfig + +var last_modified_field_name = "__last_modified__" + +if (redis.config.last_modified_field_name !== undefined) { + if (typeof redis.config.last_modified_field_name != 'string') { + throw "last_modified_field_name must be a string"; + } + last_modified_field_name = redis.config.last_modified_field_name +} + +redis.registerFunction("hset", function(client, key, field, val){ + // get the current time in ms + var curr_time = client.call("time")[0]; + return client.call('hset', key, field, val, last_modified_field_name, curr_time); +}); \ No newline at end of file diff --git a/src/test/resources/functions/withFlags.js b/src/test/resources/functions/withFlags.js new file mode 100644 index 0000000000..f4f9f05e1f --- /dev/null +++ b/src/test/resources/functions/withFlags.js @@ -0,0 +1,9 @@ +#!js api_version=1.0 name=withFlags +redis.registerFunction("my_set", + (c, key, val) => { + return c.call("set", key, val); + }, + { + flags: [redis.functionFlags.RAW_ARGUMENTS] + } +); \ No newline at end of file diff --git a/src/test/resources/functions/workingWIthHashes.js b/src/test/resources/functions/workingWIthHashes.js new file mode 100644 index 0000000000..6b99c51655 --- /dev/null +++ b/src/test/resources/functions/workingWIthHashes.js @@ -0,0 +1,8 @@ +#!js api_version=1.0 name=hashitout + +redis.registerFunction('hashy', function(client, key_name){ + if (client.call('type', key_name) == 'hash') { + return client.call('hgetall', key_name); + } + throw "Oops, that wasn't a Hash!"; +}); \ No newline at end of file