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/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE index 25318670b1..ef15b4a903 100644 --- a/.github/ISSUE_TEMPLATE +++ b/.github/ISSUE_TEMPLATE @@ -1,3 +1,12 @@ + + ### Expected behavior Write here what you're expecting ... diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..069e8c5a55 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 + +updates: + - package-ecosystem: "maven" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/release-drafter-config.yml b/.github/release-drafter-config.yml index c0e1399db6..edc2911f43 100644 --- a/.github/release-drafter-config.yml +++ b/.github/release-drafter-config.yml @@ -1,23 +1,26 @@ -name-template: '$NEXT_MAJOR_VERSION' -tag-template: 'v$NEXT_MAJOR_VERSION' +name-template: '$NEXT_MINOR_VERSION' +tag-template: 'v$NEXT_MINOR_VERSION' autolabeler: - - label: 'chore' + - label: 'maintenance' files: - '*.md' - '.github/*' - label: 'bug' branch: - '/bug-.+' - - label: 'chore' + - label: 'maintenance' branch: - - '/chore-.+' + - '/maintenance-.+' - label: 'feature' branch: - '/feature-.+' categories: - - title: 'Breaking Changes' + - title: '๐Ÿ”ฅ Breaking Changes' labels: - 'breakingchange' + - title: '๐Ÿงช Experimental Features' + labels: + - 'experimental' - title: '๐Ÿš€ New Features' labels: - 'feature' @@ -29,12 +32,15 @@ categories: - 'bug' - 'BUG' - title: '๐Ÿงฐ Maintenance' - label: 'chore' + labels: + - 'maintenance' + - 'dependencies' + - 'testing' change-template: '- $TITLE (#$NUMBER)' exclude-labels: - 'skip-changelog' template: | - ## Changes + # Changes $CHANGES 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 c192d0c122..84da5938f6 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -10,11 +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: @@ -28,10 +33,10 @@ jobs: with: java-version: '8' distribution: 'temurin' - - name: stunnel + - name: System setup run: | - sudo apt-get update - sudo apt-get install -y stunnel make + sudo apt update + sudo apt install -y stunnel make make system-setup - name: Cache dependencies uses: actions/cache@v2 @@ -40,19 +45,36 @@ jobs: ~/.m2/repository /var/cache/apt key: jedis-${{hashFiles('**/pom.xml')}} - - name: mvn offline + - name: Maven offline run: | mvn -q dependency:go-offline - - name: run tests + - 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 --name mod -p 52567:6379 -d redislabs/redismod:edge - - name: run tests - run: mvn -q -DmodulesDocker="mod:52567" -Dtest="redis.clients.jedis.modules.**" test - - name: codecov + - 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 7ffb64166c..8a409b8331 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -3,12 +3,11 @@ name: Publish Snapshot on: - workflow_run: - workflows: [Integration] - types: [completed] + push: branches: - master - - '[0-9].[0-9]' + - '[0-9].x' + workflow_dispatch: jobs: 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 481a421ed0..2987ad80dd 100644 --- a/Makefile +++ b/Makefile @@ -464,10 +464,7 @@ release: make stop system-setup: - sudo apt-get install -y gcc-8 g++-8 - cd /usr/bin ;\ - sudo ln -sf gcc-8 gcc ;\ - sudo ln -sf g++-8 g++ + sudo apt install -y gcc g++ [ ! -e redis-git ] && git clone https://github.com/redis/redis.git --branch unstable --single-branch redis-git || true $(MAKE) -C redis-git clean $(MAKE) -C redis-git diff --git a/README.md b/README.md index 4cb96c704c..2bea11911a 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,6 @@ [![Javadocs](https://www.javadoc.io/badge/redis.clients/jedis.svg)](https://www.javadoc.io/doc/redis.clients/jedis) [![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) -[![Language grade: Java](https://img.shields.io/lgtm/grade/java/g/redis/jedis.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/redis/jedis/context:java) [![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) @@ -13,14 +12,39 @@ Jedis is a Java client for [Redis](https://github.com/redis/redis "Redis") designed for performance and ease of use. -## Contributing +Are you looking for a high-level library to handle object mapping? See [redis-om-spring](https://github.com/redis/redis-om-spring)! -We'd love your contributions! +## How do I Redis? -**Bug reports** are always welcome! [You can open a bug report on GitHub](https://github.com/redis/jedis/issues/new). +[Learn for free at Redis University](https://university.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. +[Build faster with the Redis Launchpad](https://launchpad.redis.com/) + +[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 @@ -30,11 +54,19 @@ To get started with Jedis, first add it as a dependency in your Java project. If redis.clients jedis - 4.2.0 + 5.0.0 ``` -Next, you'll need to connect to Redis. For many applications, it's best to use a connection pool. You can instantiate a Jedis connection pool like so: +To use the cutting-edge Jedis, check [here](/docs/jedis-maven.md). + +Next, you'll need to connect to Redis. Consider installing a redis-stack docker: + +```bash +docker run -p 6379:6379 -it redis/redis-stack:latest +``` + +For many applications, it's best to use a connection pool. You can instantiate a Jedis connection pool like so: ```java JedisPool pool = new JedisPool("localhost", 6379); @@ -58,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); @@ -90,29 +122,49 @@ jedis.sadd("planets", "Mars"); ## Using Redis modules -Jedis provides support for some of the [Redis modules](https://redis.io/docs/modules/), most notably +Jedis includes support for [Redis modules](https://redis.io/docs/modules/) such as [RedisJSON](https://oss.redis.com/redisjson/) and [RediSearch](https://oss.redis.com/redisearch/). 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 1ce4120367..6466b1ef3a 100644 --- a/docs/jedis-maven.md +++ b/docs/jedis-maven.md @@ -6,7 +6,7 @@ redis.clients jedis - 4.0.0 + 5.0.0 ``` @@ -28,7 +28,7 @@ and redis.clients jedis - 4.1.0-SNAPSHOT + 5.1.0-SNAPSHOT ``` diff --git a/docs/redisjson.md b/docs/redisjson.md index 86a1be96c6..6409e726f9 100644 --- a/docs/redisjson.md +++ b/docs/redisjson.md @@ -53,14 +53,23 @@ private class Student { } ``` -Now we can create some students and store them in Redis as JSON": +Now we can create some students and store them in Redis as JSON: ```java +final Gson gson = new Gson(); + Student maya = new Student("Maya", "Jayavant"); -client.jsonSet("student:111", maya); +client.jsonSet("student:111", gson.toJson(maya)); Student oliwia = new Student("Oliwia", "Jagoda"); -client.jsonSet("student:112", oliwia); +client.jsonSet("student:112", gson.toJson(oliwia)); +``` + +Some of other ways to store POJOs as JSON: + +``` +client.jsonSetLegacy("student:111", maya); +client.jsonSetWithEscape("student:112", oliwia); ``` ## Querying and indexing JSON diff --git a/pom.xml b/pom.xml index 062bd4a55a..fedcb8d1bc 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ jar redis.clients jedis - 4.3.0-SNAPSHOT + 5.1.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,9 @@ github - 1.7.32 + 1.7.36 redis.clients.jedis + 1.7.1 @@ -59,25 +60,46 @@ org.apache.commons commons-pool2 - 2.11.1 + 2.12.0 org.json json - 20211205 + 20231013 com.google.code.gson gson - 2.8.9 + 2.10.1 + + + com.kohlschutter.junixsocket + junixsocket-core + 2.8.1 + pom + test + + + + org.locationtech.jts + jts-core + 1.19.0 + test + junit junit 4.13.2 test + + org.hamcrest + hamcrest + 2.2 + test + org.slf4j slf4j-simple @@ -85,18 +107,41 @@ test - com.kohlschutter.junixsocket - junixsocket-core - 2.4.0 - pom + org.mockito + mockito-inline + 4.11.0 test - org.mockito - mockito-inline - 3.12.4 + com.fasterxml.jackson.core + jackson-databind + 2.14.2 test + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + 2.14.2 + 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 + @@ -111,6 +156,12 @@ + + + src/main/resources + true + + org.jacoco @@ -133,7 +184,7 @@ maven-compiler-plugin - 3.8.1 + 3.11.0 1.8 1.8 @@ -141,17 +192,20 @@ maven-surefire-plugin - 2.22.2 + 3.1.2 ${redis-hosts} + + **/examples/*Example.java + maven-source-plugin - 3.2.1 + 3.3.0 true @@ -166,10 +220,12 @@ maven-javadoc-plugin - 2.10.4 + 3.6.0 - true - -Xdoclint:none + 8 + false + + @@ -182,12 +238,12 @@ maven-release-plugin - 2.5.3 + 3.0.1 org.sonatype.plugins nexus-staging-maven-plugin - 1.6.8 + 1.6.13 true ossrh @@ -205,7 +261,7 @@ maven-jar-plugin - 3.0.2 + 3.3.0 ${project.build.outputDirectory}/META-INF/MANIFEST.MF @@ -218,7 +274,7 @@ org.apache.felix maven-bundle-plugin - 4.2.1 + 5.1.9 bundle-manifest @@ -239,7 +295,7 @@ maven-gpg-plugin - 3.0.1 + 3.1.0 --pinentry-mode @@ -259,5 +315,19 @@ + + doctests + + + + maven-surefire-plugin + 3.1.2 + + **/examples/*Example.java + + + + + 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/BuilderFactory.java b/src/main/java/redis/clients/jedis/BuilderFactory.java index abc92b95d5..095f3c36c3 100644 --- a/src/main/java/redis/clients/jedis/BuilderFactory.java +++ b/src/main/java/redis/clients/jedis/BuilderFactory.java @@ -3,20 +3,12 @@ import java.io.Serializable; import java.util.*; import java.util.stream.Collectors; -import org.json.JSONArray; -import org.json.JSONObject; -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; import redis.clients.jedis.util.SafeEncoder; @@ -71,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, 1); - 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) { @@ -117,15 +96,9 @@ public String toString() { public static final Builder DOUBLE = new Builder() { @Override public Double build(Object data) { - String string = STRING.build(data); - if (string == null) return null; - try { - return Double.valueOf(string); - } catch (NumberFormatException e) { - if (string.equals("inf") || string.equals("+inf")) return Double.POSITIVE_INFINITY; - if (string.equals("-inf")) return Double.NEGATIVE_INFINITY; - throw e; - } + if (data == null) return null; + else if (data instanceof Double) return (Double) data; + else return DoublePrecision.parseFloatingPointNumber(STRING.build(data)); } @Override @@ -138,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 @@ -159,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; } @@ -172,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 @@ -193,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 @@ -219,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) { @@ -289,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>"; } }; @@ -319,94 +260,266 @@ public String build(Object data) { public String toString() { return "String"; } - }; public static final Builder> STRING_LIST = new Builder>() { @Override @SuppressWarnings("unchecked") public List build(Object data) { - if (null == data) { - return null; - } - List l = (List) data; - final ArrayList result = new ArrayList<>(l.size()); - for (final byte[] barray : l) { - if (barray == null) { - result.add(null); - } else { - result.add(SafeEncoder.encode(barray)); - } - } - return result; + if (null == data) return null; + return ((List) data).stream().map(STRING::build).collect(Collectors.toList()); } @Override public String toString() { return "List"; } - }; public static final Builder> STRING_SET = new Builder>() { @Override @SuppressWarnings("unchecked") public Set build(Object data) { - if (null == data) { - return null; - } - List l = (List) data; - final Set result = new HashSet<>(l.size(), 1); - for (final byte[] barray : l) { - if (barray == null) { - result.add(null); - } else { - result.add(SafeEncoder.encode(barray)); - } - } - return result; + if (null == data) return null; + return ((List) data).stream().map(STRING::build).collect(Collectors.toSet()); } @Override public String toString() { return "Set"; } + }; + public static final Builder> BINARY_MAP = new Builder>() { + @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 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 "Map"; + } }; public static final Builder> STRING_MAP = new Builder>() { @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, 1); + 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> STRING_LONG_MAP = new Builder>() { + @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 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_LIST_ELEMENT = new Builder() { + public static final Builder> KEYED_ELEMENT = new Builder>() { @Override @SuppressWarnings("unchecked") - public KeyedListElement build(Object data) { + 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 "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 "KeyedListElement"; + 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"; } }; @@ -426,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 @@ -466,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"; } }; @@ -508,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") @@ -530,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 @@ -679,7 +844,7 @@ public ScanResult build(Object data) { @SuppressWarnings("unchecked") public Map build(Object data) { final List flatHash = (List) data; - final Map hash = new HashMap<>(flatHash.size() / 2, 1); + final Map hash = new HashMap<>(flatHash.size() / 2, 1f); final Iterator iterator = flatHash.iterator(); while (iterator.hasNext()) { hash.put(SafeEncoder.encode((byte[]) iterator.next()), (Long) iterator.next()); @@ -784,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()); - - 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; } }; @@ -841,6 +1012,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); @@ -856,83 +1032,27 @@ public String toString() { }; /** - * Create a AccessControlUser object from the ACL GETUSER < > result + * 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(); @@ -944,8 +1064,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; } @@ -962,7 +1085,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; @@ -1028,7 +1152,7 @@ public StreamEntry build(Object data) { List hash = (List) objectList.get(1); Iterator hashIterator = hash.iterator(); - Map map = new HashMap<>(hash.size() / 2); + Map map = new HashMap<>(hash.size() / 2, 1f); while (hashIterator.hasNext()) { map.put(SafeEncoder.encode(hashIterator.next()), SafeEncoder.encode(hashIterator.next())); } @@ -1063,9 +1187,13 @@ public List build(Object data) { String entryIdString = SafeEncoder.encode((byte[]) res.get(0)); StreamEntryID entryID = new StreamEntryID(entryIdString); List hash = (List) res.get(1); + if (hash == null) { + responses.add(new StreamEntry(entryID, null)); + continue; + } Iterator hashIterator = hash.iterator(); - Map map = new HashMap<>(hash.size() / 2); + Map map = new HashMap<>(hash.size() / 2, 1f); while (hashIterator.hasNext()) { map.put(SafeEncoder.encode(hashIterator.next()), SafeEncoder.encode(hashIterator.next())); } @@ -1101,7 +1229,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") @@ -1121,24 +1249,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 @@ -1259,7 +1399,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(); @@ -1267,8 +1412,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; } @@ -1305,7 +1449,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(); @@ -1333,7 +1523,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; @@ -1345,7 +1536,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(); @@ -1377,8 +1569,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); } @@ -1391,7 +1583,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(); @@ -1427,6 +1619,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") @@ -1453,24 +1651,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 - } } } @@ -1496,47 +1716,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; } @@ -1546,165 +1792,66 @@ public String toString() { } }; - public static final Builder> LIBRARY_LIST = 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()); - } - }; - - public static final Builder> JSON_TYPE = new Builder>() { + public static final Builder> ENCODED_OBJECT_MAP_FROM_PAIRS = new Builder>() { @Override - public Class build(Object data) { - if (data == null) return null; - String str = STRING.build(data); - switch (str) { - case "null": - return null; - case "boolean": - return boolean.class; - case "integer": - return int.class; - case "number": - return float.class; - case "string": - return String.class; - case "object": - return Object.class; - case "array": - return List.class; - default: - throw new JedisException("Unknown type: " + str); - } - } - - @Override - public String toString() { - return "Class"; - } - }; + @SuppressWarnings("unchecked") + public Map build(Object data) { + final List list = (List) data; + if (list.isEmpty()) return Collections.emptyMap(); - public static final Builder>> JSON_TYPE_LIST = new Builder>>() { - @Override - public List> build(Object data) { - List list = (List) data; - List> classes = new ArrayList<>(list.size()); - for (Object elem : list) { - try { - classes.add(JSON_TYPE.build(elem)); - } catch (JedisException je) { - classes.add(null); - } + if (list.get(0) instanceof KeyValue) { + return ((List) list).stream() + .collect(Collectors.toMap(kv -> STRING.build(kv.getKey()), + kv -> ENCODED_OBJECT.build(kv.getValue()))); } - return classes; - } - }; - - public static final Builder JSON_OBJECT = new Builder() { - @Override - public Object build(Object data) { - if (data == null) return null; - if (!(data instanceof byte[])) return data; - - String str = STRING.build(data); - if (str.charAt(0) == '{') { - try { - return new JSONObject(str); - } catch (Exception ex) { } - } else if (str.charAt(0) == '[') { - try { - return new JSONArray(str); - } catch (Exception ex) { } + 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 str; - } - }; - - public static final Builder JSON_ARRAY = new Builder() { - @Override - public JSONArray build(Object data) { - if (data == null) return null; - return new JSONArray(STRING.build(data)); - } - }; - - public static final Builder> JSON_ARRAY_LIST = new Builder>() { - @Override - public List build(Object data) { - if (data == null) return null; - List list = (List) data; - return list.stream().map(o -> JSON_ARRAY.build(o)).collect(Collectors.toList()); - } - }; - - public static final Builder SEARCH_AGGREGATION_RESULT = new Builder() { - @Override - public AggregationResult build(Object data) { - return new AggregationResult(data); + return map; } - }; - 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 String toString() { + return "Map"; } }; - public static final Builder>> SEARCH_SYNONYM_GROUPS = new Builder>>() { - @Override - public Map> build(Object data) { - List list = (List) data; - Map> dump = new HashMap<>(list.size() / 2); - for (int i = 0; i < list.size(); i += 2) { - dump.put(STRING.build(list.get(i)), STRING_LIST.build(list.get(i + 1))); - } - return dump; - } - }; + /** + * @deprecated Use {@link LibraryInfo#LIBRARY_INFO_LIST}. + */ + @Deprecated + public static final Builder> LIBRARY_LIST = LibraryInfo.LIBRARY_INFO_LIST; - public static final Builder TIMESERIES_ELEMENT = new Builder() { + public static final Builder>> STRING_LIST_LIST = new Builder>>() { @Override - public TSElement build(Object data) { - List list = (List) data; - if (list == null || list.isEmpty()) return null; - return new TSElement(LONG.build(list.get(0)), DOUBLE.build(list.get(1))); + @SuppressWarnings("unchecked") + public List> build(Object data) { + if (null == data) return null; + return ((List) data).stream().map(STRING_LIST::build).collect(Collectors.toList()); } - }; - public static final Builder> TIMESERIES_ELEMENT_LIST = new Builder>() { @Override - public List build(Object data) { - return ((List) data).stream().map((pairObject) -> (List) pairObject) - .map((pairList) -> new TSElement(LONG.build(pairList.get(0)), - DOUBLE.build(pairList.get(1)))) - .collect(Collectors.toList()); + public String toString() { + return "List>"; } }; - public static final Builder> TIMESERIES_MRANGE_RESPONSE = new Builder>() { + public static final Builder>> ENCODED_OBJECT_LIST_LIST = new Builder>>() { @Override - public List build(Object data) { - return ((List) data).stream().map((tsObject) -> (List) tsObject) - .map((tsList) -> new TSKeyedElements(STRING.build(tsList.get(0)), - STRING_MAP_FROM_PAIRS.build(tsList.get(1)), - TIMESERIES_ELEMENT_LIST.build(tsList.get(2)))) - .collect(Collectors.toList()); + @SuppressWarnings("unchecked") + public List> build(Object data) { + if (null == data) return null; + return ((List) data).stream().map(ENCODED_OBJECT_LIST::build).collect(Collectors.toList()); } - }; - public static final Builder>> TIMESERIES_MGET_RESPONSE - = new Builder>>() { @Override - public List> build(Object data) { - return ((List) data).stream().map((tsObject) -> (List) tsObject) - .map((tsList) -> new TSKeyValue<>(STRING.build(tsList.get(0)), - STRING_MAP_FROM_PAIRS.build(tsList.get(1)), - TIMESERIES_ELEMENT.build(tsList.get(2)))) - .collect(Collectors.toList()); + public String toString() { + return "List>"; } }; @@ -1713,7 +1860,6 @@ public List> build(Object data) { * values. The resulting set displays the same ordering, concurrency, and performance * characteristics as the backing list. This class should be used only for Redis commands which * return Set result. - * @param */ protected static class SetFromList extends AbstractSet implements Serializable { private static final long serialVersionUID = -2850347066962734052L; @@ -1818,5 +1964,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 c1bb7e9db4..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,121 +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 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..e70db767f9 100644 --- a/src/main/java/redis/clients/jedis/ClusterPipeline.java +++ b/src/main/java/redis/clients/jedis/ClusterPipeline.java @@ -11,21 +11,33 @@ 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(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 8b125cd2b5..1cdb4838bb 100644 --- a/src/main/java/redis/clients/jedis/CommandArguments.java +++ b/src/main/java/redis/clients/jedis/CommandArguments.java @@ -28,7 +28,9 @@ 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)); @@ -37,9 +39,6 @@ public CommandArguments add(Object arg) { } else if (arg instanceof Boolean) { args.add(RawableFactory.from(Integer.toString((Boolean) arg ? 1 : 0))); } else { - if (arg == null) { - throw new IllegalArgumentException("null is not a valid argument."); - } args.add(RawableFactory.from(String.valueOf(arg))); } return this; @@ -53,16 +52,7 @@ public CommandArguments addObjects(Object... args) { } public CommandArguments addObjects(Collection args) { - for (Object arg : args) { - add(arg); - } - return this; - } - - public CommandArguments addObjects(int[] ints) { - for (int i : ints) { - add(i); - } + args.forEach(arg -> add(arg)); return this; } @@ -92,6 +82,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 b4fa339496..0cca329106 100644 --- a/src/main/java/redis/clients/jedis/CommandObjects.java +++ b/src/main/java/redis/clients/jedis/CommandObjects.java @@ -3,11 +3,9 @@ import static redis.clients.jedis.Protocol.Command.*; import static redis.clients.jedis.Protocol.Keyword.*; -import com.google.gson.Gson; -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; @@ -18,27 +16,73 @@ 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.*; -import redis.clients.jedis.search.SearchProtocol.SearchCommand; -import redis.clients.jedis.search.SearchProtocol.SearchKeyword; +import redis.clients.jedis.search.SearchProtocol.*; import redis.clients.jedis.search.SearchResult.SearchResultBuilder; 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.timeseries.TimeSeriesProtocol.TimeSeriesCommand; -import redis.clients.jedis.timeseries.TimeSeriesProtocol.TimeSeriesKeyword; +import redis.clients.jedis.timeseries.TimeSeriesProtocol.*; import redis.clients.jedis.util.KeyValue; public class CommandObjects { + private RedisProtocol protocol; + + protected void setProtocol(RedisProtocol proto) { + this.protocol = proto; + } + + 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); @@ -57,11 +101,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) { @@ -396,6 +440,15 @@ 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); + } + public final CommandObject getDel(String key) { return new CommandObject<>(commandArguments(Command.GETDEL).key(key), BuilderFactory.STRING); } @@ -408,6 +461,15 @@ 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); + } + public final CommandObject getDel(byte[] key) { return new CommandObject<>(commandArguments(Command.GETDEL).key(key), BuilderFactory.BINARY); } @@ -632,26 +694,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); } - /** - * @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); - } - - /** - * @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); @@ -820,20 +862,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) { @@ -844,20 +886,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) { @@ -908,12 +950,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); @@ -929,12 +971,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); @@ -1058,8 +1100,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) { @@ -1074,8 +1117,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) { @@ -1334,6 +1378,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); } @@ -1342,6 +1394,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); } @@ -1351,7 +1411,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) { @@ -1363,7 +1423,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) { @@ -1395,7 +1455,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) { @@ -1403,7 +1463,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) { @@ -1411,7 +1471,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) { @@ -1419,23 +1479,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) { @@ -1464,12 +1528,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) { @@ -1477,7 +1541,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) { @@ -1522,42 +1586,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) { @@ -1570,12 +1634,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) { @@ -1583,7 +1647,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) { @@ -1628,42 +1692,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) { @@ -1750,51 +1814,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_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> zdiff(byte[]... keys) { - return new CommandObject<>(commandArguments(ZDIFF).add(keys.length).keys((Object[]) keys), BuilderFactory.BINARY_SET); + 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> zdiffWithScores(byte[]... keys) { + 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) { 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_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) { @@ -1827,14 +1909,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) { @@ -1847,14 +1929,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_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) { @@ -1867,14 +1949,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) { @@ -1887,12 +1969,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); } @@ -1907,15 +1989,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 @@ -1944,7 +2034,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) { @@ -1972,7 +2063,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) { @@ -2310,24 +2402,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) { @@ -2426,18 +2518,6 @@ public final CommandObject xpending(String key, String gro BuilderFactory.STREAM_PENDING_SUMMARY); } - /** - * @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); @@ -2448,18 +2528,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); @@ -2492,7 +2560,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, @@ -2532,11 +2600,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) { @@ -2547,28 +2615,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); } @@ -2594,7 +2660,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()); @@ -2602,10 +2668,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) @@ -2616,39 +2682,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) { @@ -2666,49 +2726,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) { @@ -2726,19 +2774,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) { @@ -2746,10 +2792,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); } @@ -2758,6 +2814,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); } @@ -2783,20 +2845,20 @@ 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(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) { @@ -2804,21 +2866,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) { @@ -2850,19 +2912,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) { @@ -2911,20 +2967,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); @@ -3037,6 +3079,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); } @@ -3044,103 +3098,305 @@ 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) + 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 -> field.addParams(args)); + schema.fields.forEach(field -> args.addParams(field)); + return new CommandObject<>(args, BuilderFactory.STRING); + } + + public final CommandObject ftCreate(String indexName, FTCreateParams createParams, + Iterable schemaFields) { + 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 -> field.addParams(args)); + schema.fields.forEach(field -> args.addParams(field)); return new CommandObject<>(args, 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 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 final CommandObject ftAliasAdd(String aliasName, String indexName) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.ALIASADD, aliasName, indexName), BuilderFactory.STRING); + } + + public final CommandObject ftAliasUpdate(String aliasName, String indexName) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.ALIASUPDATE, aliasName, indexName), BuilderFactory.STRING); + } + + public final CommandObject ftAliasDel(String aliasName) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.ALIASDEL, aliasName), BuilderFactory.STRING); + } + + public final CommandObject ftDropIndex(String indexName) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.DROPINDEX, indexName), BuilderFactory.STRING); + } + + public final CommandObject ftDropIndexDD(String indexName) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.DROPINDEX, indexName).add(SearchKeyword.DD), + BuilderFactory.STRING); + } + + public final CommandObject ftSearch(String indexName, String query) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.SEARCH, indexName).add(query), + getSearchResultBuilder(() -> new SearchResultBuilder(true, false, true))); + } + + 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 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))); } - 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)); + @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 CommandObject ftExplain(String indexName, Query query) { - return new CommandObject<>(commandArguments(SearchCommand.EXPLAIN).add(indexName).addParams(query), BuilderFactory.STRING); + public final CommandObject ftExplain(String indexName, Query query) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.EXPLAIN, indexName) + .addParams(query.dialectOptional(searchDialect.get())), 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> ftExplainCLI(String indexName, Query query) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.EXPLAINCLI, indexName) + .addParams(query.dialectOptional(searchDialect.get())), BuilderFactory.STRING_LIST); } - public CommandObject ftAggregate(String indexName, AggregationBuilder aggr) { - return new CommandObject<>(commandArguments(SearchCommand.AGGREGATE).add(indexName).addObjects(aggr.getArgs()), - !aggr.isWithCursor() ? BuilderFactory.SEARCH_AGGREGATION_RESULT : BuilderFactory.SEARCH_AGGREGATION_RESULT_WITH_CURSOR); + 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 CommandObject ftCursorRead(String indexName, long cursorId, int count) { + 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), BuilderFactory.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 final CommandObject>> ftProfileAggregate( + String indexName, FTProfileParams profileParams, AggregationBuilder aggr) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.PROFILE, indexName) + .add(SearchKeyword.AGGREGATE).addParams(profileParams).add(SearchKeyword.QUERY) + .addParams(aggr.dialectOptional(searchDialect.get())), new SearchProfileResponseBuilder<>( + !aggr.isWithCursor() ? AggregationResult.SEARCH_AGGREGATION_RESULT + : AggregationResult.SEARCH_AGGREGATION_RESULT_WITH_CURSOR)); + } + + public final CommandObject>> ftProfileSearch( + String indexName, FTProfileParams profileParams, Query query) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.PROFILE, indexName) + .add(SearchKeyword.SEARCH).addParams(profileParams).add(SearchKeyword.QUERY) + .addParams(query.dialectOptional(searchDialect.get())), new SearchProfileResponseBuilder<>( + getSearchResultBuilder(() -> new SearchResultBuilder(!query.getNoContent(), query.getWithScores(), true)))); } - public CommandObject ftDropIndex(String indexName) { - return new CommandObject<>(commandArguments(SearchCommand.DROPINDEX).add(indexName), BuilderFactory.STRING); + public final CommandObject>> ftProfileSearch( + String indexName, FTProfileParams profileParams, String query, FTSearchParams searchParams) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.PROFILE, indexName) + .add(SearchKeyword.SEARCH).addParams(profileParams).add(SearchKeyword.QUERY).add(query) + .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), BuilderFactory.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); + } + + public final CommandObject ftDictDel(String dictionary, String... terms) { + return new CommandObject<>(commandArguments(SearchCommand.DICTDEL).add(dictionary).addObjects((Object[]) terms), + BuilderFactory.LONG); } - public CommandObject> ftInfo(String indexName) { - return new CommandObject<>(commandArguments(SearchCommand.INFO).add(indexName), BuilderFactory.ENCODED_OBJECT_MAP); + public final CommandObject> ftDictDump(String dictionary) { + return new CommandObject<>(commandArguments(SearchCommand.DICTDUMP).add(dictionary), BuilderFactory.STRING_SET); } - public CommandObject ftAliasAdd(String aliasName, String indexName) { - return new CommandObject<>(commandArguments(SearchCommand.ALIASADD).add(aliasName).add(indexName), BuilderFactory.STRING); + public final CommandObject ftDictAddBySampleKey(String indexName, String dictionary, String... terms) { + return directSearchCommand(ftDictAdd(dictionary, terms), indexName); } - public CommandObject ftAliasUpdate(String aliasName, String indexName) { - return new CommandObject<>(commandArguments(SearchCommand.ALIASUPDATE).add(aliasName).add(indexName), BuilderFactory.STRING); + public final CommandObject ftDictDelBySampleKey(String indexName, String dictionary, String... terms) { + return directSearchCommand(ftDictDel(dictionary, terms), indexName); } - public CommandObject ftAliasDel(String aliasName) { - return new CommandObject<>(commandArguments(SearchCommand.ALIASDEL).add(aliasName), BuilderFactory.STRING); + public final CommandObject> ftDictDumpBySampleKey(String indexName, String dictionary) { + return directSearchCommand(ftDictDump(dictionary), indexName); } - 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>> ftSpellCheck(String index, String query) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.SPELLCHECK, index).add(query), + SearchBuilderFactory.SEARCH_SPELLCHECK_RESPONSE); } - public CommandObject> ftConfigGet(String indexName, String option) { - return ftConfigGet(option); + public final CommandObject>> ftSpellCheck(String index, String query, + FTSpellCheckParams spellCheckParams) { + return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.SPELLCHECK, index).add(query) + .addParams(spellCheckParams.dialectOptional(searchDialect.get())), SearchBuilderFactory.SEARCH_SPELLCHECK_RESPONSE); + } + + 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 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), + protocol == RedisProtocol.RESP3 ? BuilderFactory.AGGRESSIVE_ENCODED_OBJECT_MAP : BuilderFactory.ENCODED_OBJECT_MAP_FROM_PAIRS); + } + + 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) { + return new CommandObject<>(commandArguments(SearchCommand.SUGADD).key(key).add(string).add(score), BuilderFactory.LONG); + } + + public final CommandObject ftSugAddIncr(String key, String string, double score) { + return new CommandObject<>(commandArguments(SearchCommand.SUGADD).key(key).add(string).add(score).add(SearchKeyword.INCR), BuilderFactory.LONG); + } + + public final CommandObject> ftSugGet(String key, String prefix) { + return new CommandObject<>(commandArguments(SearchCommand.SUGGET).key(key).add(prefix), BuilderFactory.STRING_LIST); + } + + public final CommandObject> ftSugGet(String key, String prefix, boolean fuzzy, int max) { + CommandArguments args = commandArguments(SearchCommand.SUGGET).key(key).add(prefix); + if (fuzzy) args.add(SearchKeyword.FUZZY); + args.add(SearchKeyword.MAX).add(max); + return new CommandObject<>(args, BuilderFactory.STRING_LIST); + } + + public final CommandObject> ftSugGetWithScores(String key, String prefix) { + 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) { + CommandArguments args = commandArguments(SearchCommand.SUGGET).key(key).add(prefix); + if (fuzzy) args.add(SearchKeyword.FUZZY); + args.add(SearchKeyword.MAX).add(max); + args.add(SearchKeyword.WITHSCORES); + return new CommandObject<>(args, BuilderFactory.TUPLE_LIST); + } + + public final CommandObject ftSugDel(String key, String string) { + return new CommandObject<>(commandArguments(SearchCommand.SUGDEL).key(key).add(string), BuilderFactory.BOOLEAN); + } + + 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_SET); } // RediSearch commands @@ -3150,13 +3406,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(GSON.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(GSON.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); } @@ -3166,43 +3426,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(GSON.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(GSON.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), BuilderFactory.JSON_OBJECT); + 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), BuilderFactory.JSON_ARRAY_LIST); + 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) { @@ -3213,6 +3492,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); } @@ -3225,6 +3505,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); } @@ -3233,34 +3514,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), BuilderFactory.JSON_TYPE); + 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), BuilderFactory.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), BuilderFactory.JSON_TYPE); + 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(GSON.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(GSON.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(GSON.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); } @@ -3269,14 +3560,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), BuilderFactory.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); } @@ -3297,15 +3591,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(GSON.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(GSON.toJson(pojo)); + args.add(getJsonObjectMapper().toJson(pojo)); } return new CommandObject<>(args, BuilderFactory.LONG); } @@ -3315,11 +3610,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(GSON.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(GSON.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) { @@ -3330,51 +3628,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(GSON.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(GSON.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); } @@ -3383,6 +3689,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); } @@ -3391,21 +3698,52 @@ 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); } - public final CommandObject jsonDebugMemory(String key) { - return new CommandObject<>(commandArguments(JsonCommand.DEBUG).add("MEMORY").key(key), BuilderFactory.LONG); + @Deprecated + public final CommandObject jsonObjLen(String key) { + return new CommandObject<>(commandArguments(JsonCommand.OBJLEN).key(key), BuilderFactory.LONG); } - public final CommandObject> jsonDebugMemory(String key, Path2 path) { - return new CommandObject<>(commandArguments(JsonCommand.DEBUG).add("MEMORY").key(key).add(path), BuilderFactory.LONG_LIST); + @Deprecated + public final CommandObject jsonObjLen(String key, Path path) { + return new CommandObject<>(commandArguments(JsonCommand.OBJLEN).key(key).add(path), BuilderFactory.LONG); } + 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); + } + + public final CommandObject>> jsonObjKeys(String key, Path2 path) { + 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); } + + public final CommandObject> jsonDebugMemory(String key, Path2 path) { + return new CommandObject<>(commandArguments(JsonCommand.DEBUG).add("MEMORY").key(key).add(path), BuilderFactory.LONG_LIST); + } // RedisJSON commands // RedisTimeSeries commands @@ -3467,61 +3805,73 @@ public final CommandObject tsDecrBy(String key, double value, long timesta public final CommandObject> tsRange(String key, long fromTimestamp, long toTimestamp) { return new CommandObject<>(commandArguments(TimeSeriesCommand.RANGE).key(key) - .add(fromTimestamp).add(toTimestamp), BuilderFactory.TIMESERIES_ELEMENT_LIST); + .add(fromTimestamp).add(toTimestamp), TimeSeriesBuilderFactory.TIMESERIES_ELEMENT_LIST); } public final CommandObject> tsRange(String key, TSRangeParams rangeParams) { return new CommandObject<>(commandArguments(TimeSeriesCommand.RANGE).key(key) - .addParams(rangeParams), BuilderFactory.TIMESERIES_ELEMENT_LIST); + .addParams(rangeParams), TimeSeriesBuilderFactory.TIMESERIES_ELEMENT_LIST); } public final CommandObject> tsRevRange(String key, long fromTimestamp, long toTimestamp) { return new CommandObject<>(commandArguments(TimeSeriesCommand.REVRANGE).key(key) - .add(fromTimestamp).add(toTimestamp), BuilderFactory.TIMESERIES_ELEMENT_LIST); + .add(fromTimestamp).add(toTimestamp), TimeSeriesBuilderFactory.TIMESERIES_ELEMENT_LIST); } public final CommandObject> tsRevRange(String key, TSRangeParams rangeParams) { return new CommandObject<>(commandArguments(TimeSeriesCommand.REVRANGE).key(key) - .addParams(rangeParams), BuilderFactory.TIMESERIES_ELEMENT_LIST); + .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), - BuilderFactory.TIMESERIES_MRANGE_RESPONSE); + getTimeseriesMultiRangeResponseBuilder()); } - public final CommandObject> tsMRange(TSMRangeParams multiRangeParams) { + public final CommandObject> tsMRange(TSMRangeParams multiRangeParams) { return new CommandObject<>(commandArguments(TimeSeriesCommand.MRANGE) - .addParams(multiRangeParams), BuilderFactory.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), - BuilderFactory.TIMESERIES_MRANGE_RESPONSE); + getTimeseriesMultiRangeResponseBuilder()); } - public final CommandObject> tsMRevRange(TSMRangeParams multiRangeParams) { + public final CommandObject> tsMRevRange(TSMRangeParams multiRangeParams) { return new CommandObject<>(commandArguments(TimeSeriesCommand.MREVRANGE).addParams(multiRangeParams), - BuilderFactory.TIMESERIES_MRANGE_RESPONSE); + getTimeseriesMultiRangeResponseBuilder()); } public final CommandObject tsGet(String key) { - return new CommandObject<>(commandArguments(TimeSeriesCommand.GET).key(key), BuilderFactory.TIMESERIES_ELEMENT); + return new CommandObject<>(commandArguments(TimeSeriesCommand.GET).key(key), TimeSeriesBuilderFactory.TIMESERIES_ELEMENT); + } + + 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), BuilderFactory.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, long timeBucket) { + public final CommandObject tsCreateRule(String sourceKey, String destKey, AggregationType aggregationType, + long timeBucket) { return new CommandObject<>(commandArguments(TimeSeriesCommand.CREATERULE).key(sourceKey).key(destKey) .add(TimeSeriesKeyword.AGGREGATION).add(aggregationType).add(timeBucket), BuilderFactory.STRING); } + public final CommandObject tsCreateRule(String sourceKey, String destKey, AggregationType aggregationType, + long bucketDuration, long alignTimestamp) { + return new CommandObject<>(commandArguments(TimeSeriesCommand.CREATERULE).key(sourceKey).key(destKey) + .add(TimeSeriesKeyword.AGGREGATION).add(aggregationType).add(bucketDuration).add(alignTimestamp), BuilderFactory.STRING); + } + public final CommandObject tsDeleteRule(String sourceKey, String destKey) { return new CommandObject<>(commandArguments(TimeSeriesCommand.DELETERULE).key(sourceKey).key(destKey), BuilderFactory.STRING); } @@ -3530,6 +3880,24 @@ public final CommandObject> tsQueryIndex(String... filters) { return new CommandObject<>(commandArguments(TimeSeriesCommand.QUERYINDEX) .addObjects((Object[]) filters), BuilderFactory.STRING_LIST); } + + public final CommandObject tsInfo(String key) { + 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), + 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 // RedisBloom commands @@ -3549,7 +3917,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) { @@ -3571,6 +3939,18 @@ public final CommandObject> bfMExists(String key, String... items) addObjects((Object[]) items), BuilderFactory.BOOLEAN_LIST); } + public final CommandObject> bfScanDump(String key, long iterator) { + return new CommandObject<>(commandArguments(BloomFilterCommand.SCANDUMP).key(key).add(iterator), BLOOM_SCANDUMP_RESPONSE); + } + + public final CommandObject bfLoadChunk(String key, long iterator, byte[] data) { + return new CommandObject<>(commandArguments(BloomFilterCommand.LOADCHUNK).key(key).add(iterator).add(data), BuilderFactory.STRING); + } + + public final CommandObject bfCard(String key) { + return new CommandObject<>(commandArguments(BloomFilterCommand.CARD).key(key), BuilderFactory.LONG); + } + public final CommandObject> bfInfo(String key) { return new CommandObject<>(commandArguments(BloomFilterCommand.INFO).key(key), BuilderFactory.ENCODED_OBJECT_MAP); } @@ -3628,16 +4008,26 @@ public final CommandObject cfCount(String key, String item) { return new CommandObject<>(commandArguments(CuckooFilterCommand.COUNT).key(key).add(item), BuilderFactory.LONG); } + public final CommandObject> cfScanDump(String key, long iterator) { + return new CommandObject<>(commandArguments(CuckooFilterCommand.SCANDUMP).key(key).add(iterator), BLOOM_SCANDUMP_RESPONSE); + } + + public final CommandObject cfLoadChunk(String key, long iterator, byte[] data) { + return new CommandObject<>(commandArguments(CuckooFilterCommand.LOADCHUNK).key(key).add(iterator).add(data), BuilderFactory.STRING); + } + public final CommandObject> cfInfo(String key) { return new CommandObject<>(commandArguments(CuckooFilterCommand.INFO).key(key), BuilderFactory.ENCODED_OBJECT_MAP); } 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) { @@ -3647,7 +4037,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) { @@ -3691,40 +4082,241 @@ 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); } + + public final CommandObject tdigestCreate(String key) { + return new CommandObject<>(commandArguments(TDigestCommand.CREATE).key(key), BuilderFactory.STRING); + } + + public final CommandObject tdigestCreate(String key, int compression) { + return new CommandObject<>(commandArguments(TDigestCommand.CREATE).key(key).add(RedisBloomKeyword.COMPRESSION) + .add(compression), BuilderFactory.STRING); + } + + public final CommandObject tdigestReset(String key) { + return new CommandObject<>(commandArguments(TDigestCommand.RESET).key(key), BuilderFactory.STRING); + } + + public final CommandObject tdigestMerge(String destinationKey, String... sourceKeys) { + return new CommandObject<>(commandArguments(TDigestCommand.MERGE).key(destinationKey) + .add(sourceKeys.length).keys((Object[]) sourceKeys), BuilderFactory.STRING); + } + + public final CommandObject tdigestMerge(TDigestMergeParams mergeParams, + String destinationKey, String... sourceKeys) { + return new CommandObject<>(commandArguments(TDigestCommand.MERGE).key(destinationKey) + .add(sourceKeys.length).keys((Object[]) sourceKeys).addParams(mergeParams), BuilderFactory.STRING); + } + + public final CommandObject> tdigestInfo(String key) { + return new CommandObject<>(commandArguments(TDigestCommand.INFO).key(key), BuilderFactory.ENCODED_OBJECT_MAP); + } + + public final CommandObject tdigestAdd(String key, double... values) { + return new CommandObject<>(addFlatArgs(commandArguments(TDigestCommand.ADD).key(key), values), + BuilderFactory.STRING); + } + + public final CommandObject> tdigestCDF(String key, double... values) { + return new CommandObject<>(addFlatArgs(commandArguments(TDigestCommand.CDF).key(key), values), + BuilderFactory.DOUBLE_LIST); + } + + public final CommandObject> tdigestQuantile(String key, double... quantiles) { + return new CommandObject<>(addFlatArgs(commandArguments(TDigestCommand.QUANTILE).key(key), + quantiles), BuilderFactory.DOUBLE_LIST); + } + + public final CommandObject tdigestMin(String key) { + return new CommandObject<>(commandArguments(TDigestCommand.MIN).key(key), BuilderFactory.DOUBLE); + } + + public final CommandObject tdigestMax(String key) { + return new CommandObject<>(commandArguments(TDigestCommand.MAX).key(key), BuilderFactory.DOUBLE); + } + + public final CommandObject tdigestTrimmedMean(String key, double lowCutQuantile, double highCutQuantile) { + return new CommandObject<>(commandArguments(TDigestCommand.TRIMMED_MEAN).key(key).add(lowCutQuantile) + .add(highCutQuantile), BuilderFactory.DOUBLE); + } + + public final CommandObject> tdigestRank(String key, double... values) { + return new CommandObject<>(addFlatArgs(commandArguments(TDigestCommand.RANK).key(key), + values), BuilderFactory.LONG_LIST); + } + + public final CommandObject> tdigestRevRank(String key, double... values) { + return new CommandObject<>(addFlatArgs(commandArguments(TDigestCommand.REVRANK).key(key), + values), BuilderFactory.LONG_LIST); + } + + public final CommandObject> tdigestByRank(String key, long... ranks) { + return new CommandObject<>(addFlatArgs(commandArguments(TDigestCommand.BYRANK).key(key), + ranks), BuilderFactory.DOUBLE_LIST); + } + + public final CommandObject> tdigestByRevRank(String key, long... ranks) { + return new CommandObject<>(addFlatArgs(commandArguments(TDigestCommand.BYREVRANK).key(key), + ranks), BuilderFactory.DOUBLE_LIST); + } // RedisBloom commands - private static final Gson GSON = new Gson(); + // 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); + } + + @Deprecated + public final CommandObject>> graphSlowlog(String graphName) { + return new CommandObject<>(commandArguments(GraphCommand.SLOWLOG).key(graphName), BuilderFactory.ENCODED_OBJECT_LIST_LIST); + } - private class GsonObjectBuilder extends Builder { + @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) { + this.replyBuilder = replyBuilder; + } + + @Override + public Map.Entry> build(Object 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 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 GSON.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; } @@ -3734,8 +4326,30 @@ public List build(Object data) { return null; } List list = BuilderFactory.STRING_LIST.build(data); - return list.stream().map(s -> GSON.fromJson(s, clazz)).collect(Collectors.toList()); + return list.stream().map(s -> getJsonObjectMapper().fromJson(s, clazz)).collect(Collectors.toList()); + } + } + + private static final Builder> BLOOM_SCANDUMP_RESPONSE = new Builder>() { + @Override + public Map.Entry build(Object data) { + List list = (List) data; + return new KeyValue<>(BuilderFactory.LONG.build(list.get(0)), BuilderFactory.BINARY.build(list.get(1))); + } + }; + + private CommandArguments addFlatArgs(CommandArguments args, long... values) { + for (long value : values) { + args.add(value); + } + return args; + } + + private CommandArguments addFlatArgs(CommandArguments args, double... values) { + for (double value : values) { + args.add(value); } + return args; } private CommandArguments addFlatKeyValueArgs(CommandArguments args, String... keyvalues) { diff --git a/src/main/java/redis/clients/jedis/Connection.java b/src/main/java/redis/clients/jedis/Connection.java index 868ea26eba..5cb276a2c6 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 + "}"; } + 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/ConnectionPool.java b/src/main/java/redis/clients/jedis/ConnectionPool.java index 26a3fe2a85..5899b22260 100644 --- a/src/main/java/redis/clients/jedis/ConnectionPool.java +++ b/src/main/java/redis/clients/jedis/ConnectionPool.java @@ -6,20 +6,21 @@ public class ConnectionPool extends Pool { - public ConnectionPool(HostAndPort hostAndPort, JedisClientConfig clientConfig, - GenericObjectPoolConfig poolConfig) { - this(new ConnectionFactory(hostAndPort, clientConfig), poolConfig); - } - public ConnectionPool(HostAndPort hostAndPort, JedisClientConfig clientConfig) { this(new ConnectionFactory(hostAndPort, clientConfig)); } public ConnectionPool(PooledObjectFactory factory) { - this(factory, new GenericObjectPoolConfig()); + super(factory); } - public ConnectionPool(PooledObjectFactory factory, GenericObjectPoolConfig poolConfig) { + public ConnectionPool(HostAndPort hostAndPort, JedisClientConfig clientConfig, + GenericObjectPoolConfig poolConfig) { + this(new ConnectionFactory(hostAndPort, clientConfig), poolConfig); + } + + public ConnectionPool(PooledObjectFactory factory, + GenericObjectPoolConfig poolConfig) { super(factory, poolConfig); } 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/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/Jedis.java b/src/main/java/redis/clients/jedis/Jedis.java index 3d289c59b4..6db8c99328 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). @@ -387,8 +465,11 @@ public String set(final byte[] key, final byte[] value) { * GB). * @param key * @param value - * @param params - * @return OK + * @param params NX|XX, NX -- Only set the key if it does not already exist. XX -- Only set the + * key if it already exists. EX|PX, expire time units: EX = seconds; PX = milliseconds + * @return simple-string-reply {@code OK} if {@code SET} was executed correctly, or {@code null} + * if the {@code SET} operation was not performed because the user specified the NX or XX option + * but the condition was not met. */ @Override public String set(final byte[] key, final byte[] value, final SetParams params) { @@ -411,6 +492,18 @@ 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(); + return connection.executeCommand(commandObjects.setGet(key, value, params)); + } + /** * Get the value of key and delete the key. This command is similar to GET, except for the fact * that it also deletes the key on success (if and only if the key's value type is a string). @@ -431,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) @@ -485,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. @@ -522,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 @@ -648,9 +709,7 @@ public long dbSize() { * @see Expire Command * @param key * @param seconds - * @return 1: the timeout was set. 0: the timeout was not set since - * the key already has an associated timeout (this may happen only in Redis versions < - * 2.1.3, Redis >= 2.1.3 will happily update the timeout), or the key does not exist. + * @return 1: the timeout was set. 0: the timeout was not set. */ @Override public long expire(final byte[] key, final long seconds) { @@ -681,9 +740,7 @@ public long expire(final byte[] key, final long seconds, final ExpiryOption expi * @see PEXPIRE Command * @param key * @param milliseconds - * @return 1: the timeout was set. 0: the timeout was not set since - * the key already has an associated timeout (this may happen only in Redis versions < - * 2.1.3, Redis >= 2.1.3 will happily update the timeout), or the key does not exist. + * @return 1: the timeout was set. 0: the timeout was not set. */ @Override public long pexpire(final byte[] key, final long milliseconds) { @@ -709,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 @@ -788,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 @@ -827,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 @@ -916,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. *

@@ -964,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) @@ -988,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) @@ -1011,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) @@ -1060,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) @@ -1213,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 @@ -1363,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)); } @@ -2123,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(); @@ -2497,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)); } @@ -2568,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)); } @@ -2585,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)); } @@ -2611,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. @@ -2653,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). @@ -3013,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)); } @@ -3109,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)); } @@ -3122,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)); } @@ -3255,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)); } @@ -3343,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. */ @@ -3360,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)); @@ -3547,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(CONFIG, Keyword.GET.getRaw(), pattern); - return connection.getBinaryMultiBulkReply(); + connection.sendCommand(Command.CONFIG, Keyword.GET.getRaw(), pattern); + return BuilderFactory.BINARY_MAP.build(connection.getOne()); } @Override - public List configGet(byte[]... patterns) { + public Map configGet(byte[]... patterns) { checkIsInMultiOrPipeline(); - connection.sendCommand(CONFIG, joinParameters(Keyword.GET.getRaw(), patterns)); - return connection.getBinaryMultiBulkReply(); + connection.sendCommand(Command.CONFIG, joinParameters(Keyword.GET.getRaw(), patterns)); + return BuilderFactory.BINARY_MAP.build(connection.getOne()); } /** @@ -3566,7 +3591,7 @@ public List configGet(byte[]... patterns) { @Override public String configResetStat() { checkIsInMultiOrPipeline(); - connection.sendCommand(CONFIG, Keyword.RESETSTAT); + connection.sendCommand(Command.CONFIG, Keyword.RESETSTAT); return connection.getStatusCodeReply(); } @@ -3592,14 +3617,14 @@ 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() { checkIsInMultiOrPipeline(); - connection.sendCommand(CONFIG, Keyword.REWRITE); + connection.sendCommand(Command.CONFIG, Keyword.REWRITE); return connection.getStatusCodeReply(); } @@ -3635,41 +3660,30 @@ public String configRewrite() { @Override public String configSet(final byte[] parameter, final byte[] value) { checkIsInMultiOrPipeline(); - connection.sendCommand(CONFIG, Keyword.SET.getRaw(), parameter, value); + connection.sendCommand(Command.CONFIG, Keyword.SET.getRaw(), parameter, value); return connection.getStatusCodeReply(); } @Override public String configSet(final byte[]... parameterValues) { checkIsInMultiOrPipeline(); - connection.sendCommand(CONFIG, joinParameters(Keyword.SET.getRaw(), parameterValues)); + connection.sendCommand(Command.CONFIG, joinParameters(Keyword.SET.getRaw(), parameterValues)); return connection.getStatusCodeReply(); } @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 @@ -3882,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 @@ -4106,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) { - checkIsInMultiOrPipeline(); - connection.sendCommand(ACL, DELUSER.getRaw(), name); - return connection.getIntegerReply(); - } - - @Override - public long aclDelUser(byte[] name, byte[]... names) { + public long aclDelUser(byte[]... names) { checkIsInMultiOrPipeline(); - connection.sendCommand(ACL, joinParameters(DELUSER.getRaw(), name, names)); + connection.sendCommand(ACL, joinParameters(DELUSER.getRaw(), names)); return connection.getIntegerReply(); } @@ -4176,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(); } @@ -4226,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(); @@ -4277,20 +4289,41 @@ public String clientPause(final long timeout, final ClientPauseMode mode) { return connection.getBulkReply(); } + @Override + public String clientUnpause() { + checkIsInMultiOrPipeline(); + connection.sendCommand(CLIENT, UNPAUSE); + return connection.getBulkReply(); + } + @Override public String clientNoEvictOn() { checkIsInMultiOrPipeline(); - connection.sendCommand(CLIENT,"NO-EVICT", "ON"); + connection.sendCommand(CLIENT, "NO-EVICT", "ON"); return connection.getBulkReply(); } @Override public String clientNoEvictOff() { checkIsInMultiOrPipeline(); - connection.sendCommand(CLIENT,"NO-EVICT", "OFF"); + connection.sendCommand(CLIENT, "NO-EVICT", "OFF"); 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); @@ -4330,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(); @@ -4606,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)); @@ -4631,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)); } @@ -4708,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(); @@ -4777,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(); @@ -4845,7 +4867,7 @@ public boolean copy(String srcKey, String dstKey, boolean replace) { } /** - * Works same as ping() but returns argument message instead of PONG. + * Works same as {@link #ping()} but returns argument message instead of PONG. * @param message * @return message */ @@ -4878,7 +4900,9 @@ public String set(final String key, final String value) { * @param value * @param params NX|XX, NX -- Only set the key if it does not already exist. XX -- Only set the * key if it already exists. EX|PX, expire time units: EX = seconds; PX = milliseconds - * @return OK + * @return simple-string-reply {@code OK} if {@code SET} was executed correctly, or {@code null} + * if the {@code SET} operation was not performed because the user specified the NX or XX option + * but the condition was not met. */ @Override public String set(final String key, final String value, final SetParams params) { @@ -4901,6 +4925,18 @@ 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(); + return connection.executeCommand(commandObjects.setGet(key, value, params)); + } + /** * Get the value of key and delete the key. This command is similar to GET, except for the fact * that it also deletes the key on success (if and only if the key's value type is a string). @@ -4966,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. @@ -5326,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. *

@@ -5348,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. *

@@ -5373,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) @@ -5397,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) @@ -5420,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) @@ -5465,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) @@ -5618,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 @@ -5667,13 +5703,15 @@ public boolean hexists(final String key, final String field) { } /** - * Remove the specified field from an hash stored at key. + * Remove the specified field(s) from a hash stored at key. Specified fields that do not exist + * within this hash are ignored. *

* Time complexity: O(1) * @param key * @param fields - * @return If the field was present in the hash it is deleted and 1 is returned, otherwise 0 is - * returned and no operation is performed. + * @return The number of fields that were removed from the hash, not including specified but + * non-existing fields. If key does not exist, it is treated as an empty hash and this + * command returns 0. */ @Override public long hdel(final String key, final String... fields) { @@ -5770,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)); } @@ -6219,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 @@ -6233,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 @@ -6405,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(); @@ -6516,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(); @@ -6871,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)); } @@ -6945,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)); } @@ -6963,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)); } @@ -6993,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)); } @@ -7005,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)); } @@ -7371,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)); } @@ -7384,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)); } @@ -7470,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)); } @@ -7483,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)); } @@ -7624,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)); } @@ -7641,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 @@ -7825,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(CONFIG, Keyword.GET.name(), pattern); - return connection.getMultiBulkReply(); + connection.sendCommand(Command.CONFIG, Keyword.GET.name(), pattern); + return BuilderFactory.STRING_MAP.build(connection.getOne()); } @Override - public List configGet(String... patterns) { + public Map configGet(String... patterns) { checkIsInMultiOrPipeline(); - connection.sendCommand(CONFIG, joinParameters(Keyword.GET.name(), patterns)); - return connection.getMultiBulkReply(); + connection.sendCommand(Command.CONFIG, joinParameters(Keyword.GET.name(), patterns)); + return BuilderFactory.STRING_MAP.build(connection.getOne()); } /** @@ -7870,14 +7911,23 @@ public List configGet(String... patterns) { @Override public String configSet(final String parameter, final String value) { checkIsInMultiOrPipeline(); - connection.sendCommand(CONFIG, Keyword.SET.name(), parameter, value); + connection.sendCommand(Command.CONFIG, Keyword.SET.name(), parameter, value); return connection.getStatusCodeReply(); } @Override public String configSet(final String... parameterValues) { checkIsInMultiOrPipeline(); - connection.sendCommand(CONFIG, joinParameters(Keyword.SET.name(), parameterValues)); + connection.sendCommand(Command.CONFIG, joinParameters(Keyword.SET.name(), 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(); } @@ -7919,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(); @@ -8303,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) { + public long aclDelUser(final String... names) { checkIsInMultiOrPipeline(); - connection.sendCommand(ACL, DELUSER.name(), name); - return connection.getIntegerReply(); - } - - @Override - public long aclDelUser(final String name, String... names) { - checkIsInMultiOrPipeline(); - connection.sendCommand(ACL, joinParameters(DELUSER.name(), name, names)); + connection.sendCommand(ACL, joinParameters(DELUSER.name(), names)); return connection.getIntegerReply(); } @@ -8327,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 @@ -8355,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 @@ -8492,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(); @@ -8718,7 +8786,7 @@ public String clusterSetConfigEpoch(long configEpoch) { public String clusterBumpEpoch() { checkIsInMultiOrPipeline(); connection.sendCommand(CLUSTER, ClusterKeyword.BUMPEPOCH); - return connection.getStatusCodeReply(); + return connection.getBulkReply(); } @Override @@ -8771,6 +8839,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(); @@ -9095,6 +9170,14 @@ public String moduleLoad(String path, String... args) { return connection.getStatusCodeReply(); } + @Override + public String moduleLoadEx(String path, ModuleLoadExParams params) { + checkIsInMultiOrPipeline(); + connection.sendCommand(new CommandArguments(Command.MODULE).add(LOADEX).add(path) + .addParams(params)); + return connection.getStatusCodeReply(); + } + @Override public String moduleUnload(final String name) { checkIsInMultiOrPipeline(); @@ -9106,7 +9189,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 @@ -9182,6 +9265,13 @@ public String reset() { return connection.getStatusCodeReply(); } + @Override + public String latencyDoctor() { + checkIsInMultiOrPipeline(); + connection.sendCommand(LATENCY, DOCTOR); + return connection.getBulkReply(); + } + @Override public StreamEntryID xadd(final String key, final StreamEntryID id, final Map hash) { checkIsInMultiOrPipeline(); @@ -9326,17 +9416,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(); @@ -9388,12 +9467,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)); @@ -9404,6 +9477,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/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 769aa5070c..e9bb606191 100644 --- a/src/main/java/redis/clients/jedis/JedisCluster.java +++ b/src/main/java/redis/clients/jedis/JedisCluster.java @@ -4,8 +4,11 @@ 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 { @@ -99,6 +102,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); } @@ -123,8 +132,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); @@ -138,9 +147,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); @@ -168,7 +177,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); } @@ -180,15 +190,57 @@ 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(ClusterConnectionProvider provider, int maxAttempts, + Duration maxTotalRetriesDuration) { + super(provider, maxAttempts, maxTotalRetriesDuration); + } + public Map getClusterNodes() { - return ((ClusterCommandExecutor) executor).provider.getNodes(); + return ((ClusterConnectionProvider) provider).getNodes(); } public Connection getConnectionFromSlot(int slot) { - return ((ClusterCommandExecutor) executor).provider.getConnectionFromSlot(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, (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 95309fd15e..a4cc2d1d63 100644 --- a/src/main/java/redis/clients/jedis/JedisClusterInfoCache.java +++ b/src/main/java/redis/clients/jedis/JedisClusterInfoCache.java @@ -1,6 +1,7 @@ package redis.clients.jedis; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -14,15 +15,15 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; -import redis.clients.jedis.exceptions.JedisConnectionException; +import redis.clients.jedis.exceptions.JedisClusterOperationException; import redis.clients.jedis.exceptions.JedisException; import redis.clients.jedis.util.SafeEncoder; public class JedisClusterInfoCache { 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,19 +36,8 @@ 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); - } - public JedisClusterInfoCache(final JedisClientConfig clientConfig, final Set startNodes) { - this(clientConfig, new GenericObjectPoolConfig(), startNodes); + this(clientConfig, null, startNodes); } public JedisClusterInfoCache(final JedisClientConfig clientConfig, @@ -59,6 +49,9 @@ public JedisClusterInfoCache(final JedisClientConfig clientConfig, public void discoverClusterNodesAndSlots(Connection jedis) { List slotsInfo = executeClusterSlots(jedis); + if (slotsInfo.isEmpty()) { + throw new JedisClusterOperationException("Cluster slots list is empty."); + } w.lock(); try { reset(); @@ -112,7 +105,7 @@ public void renewClusterSlots(Connection jedis) { try (Connection j = new Connection(hostAndPort, clientConfig)) { discoverClusterSlots(j); return; - } catch (JedisConnectionException e) { + } catch (JedisException e) { // try next nodes } } @@ -127,7 +120,7 @@ public void renewClusterSlots(Connection jedis) { } discoverClusterSlots(j); return; - } catch (JedisConnectionException e) { + } catch (JedisException e) { // try next nodes } } @@ -140,10 +133,13 @@ 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."); + } 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) { @@ -205,7 +201,8 @@ public ConnectionPool setupNodeIfNotExist(final HostAndPort node) { ConnectionPool existingPool = nodes.get(nodeKey); if (existingPool != null) return existingPool; - ConnectionPool nodePool = new ConnectionPool(node, clientConfig, poolConfig); + ConnectionPool nodePool = poolConfig == null ? new ConnectionPool(node, clientConfig) + : new ConnectionPool(node, clientConfig, poolConfig); nodes.put(nodeKey, nodePool); return nodePool; } finally { @@ -217,8 +214,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(); } @@ -229,8 +226,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(); @@ -253,7 +250,7 @@ public ConnectionPool getNode(HostAndPort node) { public ConnectionPool getSlotPool(int slot) { r.lock(); try { - return slots.get(slot); + return slots[slot]; } finally { r.unlock(); } @@ -262,7 +259,7 @@ public ConnectionPool getSlotPool(int slot) { public HostAndPort getSlotNode(int slot) { r.lock(); try { - return slotNodes.get(slot); + return slotNodes[slot]; } finally { r.unlock(); } @@ -304,8 +301,8 @@ public void reset() { } } nodes.clear(); - slots.clear(); - slotNodes.clear(); + Arrays.fill(slots, null); + Arrays.fill(slotNodes, null); } finally { w.unlock(); } diff --git a/src/main/java/redis/clients/jedis/JedisFactory.java b/src/main/java/redis/clients/jedis/JedisFactory.java index cd55e5168c..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; } } @@ -207,8 +184,18 @@ public void passivateObject(PooledObject pooledJedis) throws Exception { public boolean validateObject(PooledObject pooledJedis) { final Jedis jedis = pooledJedis.getObject(); try { - // check HostAndPort ?? - return jedis.getConnection().isConnected() && jedis.ping().equals("PONG"); + boolean targetHasNotChanged = true; + if (jedisSocketFactory instanceof DefaultJedisSocketFactory) { + HostAndPort targetAddress = ((DefaultJedisSocketFactory) jedisSocketFactory).getHostAndPort(); + HostAndPort objectAddress = jedis.getConnection().getHostAndPort(); + + targetHasNotChanged = targetAddress.getHost().equals(objectAddress.getHost()) + && targetAddress.getPort() == objectAddress.getPort(); + } + + return targetHasNotChanged + && jedis.getConnection().isConnected() + && jedis.ping().equals("PONG"); } catch (final Exception e) { logger.error("Error while validating pooled Jedis object.", e); return false; 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/JedisPool.java b/src/main/java/redis/clients/jedis/JedisPool.java index 913e46a4be..3cc9aad107 100644 --- a/src/main/java/redis/clients/jedis/JedisPool.java +++ b/src/main/java/redis/clients/jedis/JedisPool.java @@ -22,20 +22,11 @@ public JedisPool() { this(Protocol.DEFAULT_HOST, Protocol.DEFAULT_PORT); } - public JedisPool(final GenericObjectPoolConfig poolConfig, final String url) { - this(poolConfig, URI.create(url)); - } - - public JedisPool(String host, int port) { - this(new GenericObjectPoolConfig(), host, port); - } - /** - * WARNING: This constructor only accepts a uri string as {@code url}. - * {@link JedisURIHelper#isValid(java.net.URI)} can be used before this. + * WARNING: This constructor only accepts a uri string as {@code url}. {@link JedisURIHelper#isValid(java.net.URI)} + * can be used before this. *

- * To use a host string, {@link #JedisPool(java.lang.String, int)} can be used with - * {@link Protocol#DEFAULT_PORT}. + * To use a host string, {@link #JedisPool(java.lang.String, int)} can be used with {@link Protocol#DEFAULT_PORT}. * * @param url */ @@ -44,12 +35,12 @@ public JedisPool(final String url) { } /** - * WARNING: This constructor only accepts a uri string as {@code url}. - * {@link JedisURIHelper#isValid(java.net.URI)} can be used before this. + * WARNING: This constructor only accepts a uri string as {@code url}. {@link JedisURIHelper#isValid(java.net.URI)} + * can be used before this. *

* To use a host string, - * {@link #JedisPool(java.lang.String, int, boolean, javax.net.ssl.SSLSocketFactory, javax.net.ssl.SSLParameters, javax.net.ssl.HostnameVerifier)} - * can be used with {@link Protocol#DEFAULT_PORT} and {@code ssl=true}. + * {@link #JedisPool(java.lang.String, int, boolean, javax.net.ssl.SSLSocketFactory, javax.net.ssl.SSLParameters, + * javax.net.ssl.HostnameVerifier)} can be used with {@link Protocol#DEFAULT_PORT} and {@code ssl=true}. * * @param url * @param sslSocketFactory @@ -62,62 +53,51 @@ public JedisPool(final String url, final SSLSocketFactory sslSocketFactory, Protocol.DEFAULT_TIMEOUT, null, sslSocketFactory, sslParameters, hostnameVerifier)); } - public JedisPool(final URI uri) { - this(new GenericObjectPoolConfig(), uri); - } - - public JedisPool(final URI uri, final SSLSocketFactory sslSocketFactory, - final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { - this(new GenericObjectPoolConfig(), uri, sslSocketFactory, sslParameters, - hostnameVerifier); + public JedisPool(final String host, final int port) { + this(new HostAndPort(host, port), DefaultJedisClientConfig.builder().build()); } - public JedisPool(final URI uri, final int timeout) { - this(new GenericObjectPoolConfig(), uri, timeout); - } - - public JedisPool(final URI uri, final int timeout, final SSLSocketFactory sslSocketFactory, - final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { - this(new GenericObjectPoolConfig(), uri, timeout, sslSocketFactory, sslParameters, - hostnameVerifier); + public JedisPool(final String host, final int port, final boolean ssl) { + this(new HostAndPort(host, port), DefaultJedisClientConfig.builder().ssl(ssl).build()); } - public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String password) { - this(poolConfig, host, port, timeout, password, Protocol.DEFAULT_DATABASE); + public JedisPool(final String host, final int port, final boolean ssl, + final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters, + final HostnameVerifier hostnameVerifier) { + this(new HostAndPort(host, port), DefaultJedisClientConfig.builder().ssl(ssl) + .sslSocketFactory(sslSocketFactory).sslParameters(sslParameters) + .hostnameVerifier(hostnameVerifier).build()); } public JedisPool(final String host, int port, String user, final String password) { - this(new GenericObjectPoolConfig(), host, port, user, password); - } - - public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, - String user, final String password) { - this(poolConfig, host, port, Protocol.DEFAULT_TIMEOUT, user, password, - Protocol.DEFAULT_DATABASE); + this(new HostAndPort(host, port), DefaultJedisClientConfig.builder().user(user).password(password).build()); } - public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String user, final String password) { - this(poolConfig, host, port, timeout, user, password, Protocol.DEFAULT_DATABASE); + public JedisPool(final HostAndPort hostAndPort, final JedisClientConfig clientConfig) { + this(new JedisFactory(hostAndPort, clientConfig)); } - public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String password, final boolean ssl) { - this(poolConfig, host, port, timeout, password, Protocol.DEFAULT_DATABASE, ssl); + public JedisPool(PooledObjectFactory factory) { + super(factory); } - public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String user, final String password, final boolean ssl) { - this(poolConfig, host, port, timeout, user, password, Protocol.DEFAULT_DATABASE, ssl); + public JedisPool(final GenericObjectPoolConfig poolConfig) { + this(poolConfig, Protocol.DEFAULT_HOST, Protocol.DEFAULT_PORT); } - public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String password, final boolean ssl, - final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters, - final HostnameVerifier hostnameVerifier) { - this(poolConfig, host, port, timeout, password, Protocol.DEFAULT_DATABASE, ssl, - sslSocketFactory, sslParameters, hostnameVerifier); + /** + * WARNING: This constructor only accepts a uri string as {@code url}. {@link JedisURIHelper#isValid(java.net.URI)} + * can be used before this. + *

+ * To use a host string, + * {@link #JedisPool(org.apache.commons.pool2.impl.GenericObjectPoolConfig, java.lang.String, int)} can be used with + * {@link Protocol#DEFAULT_PORT}. + * + * @param poolConfig + * @param url + */ + public JedisPool(final GenericObjectPoolConfig poolConfig, final String url) { + this(poolConfig, URI.create(url)); } public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, @@ -137,6 +117,11 @@ public JedisPool(final GenericObjectPoolConfig poolConfig, final String h hostnameVerifier); } + public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, + String user, final String password) { + this(poolConfig, host, port, Protocol.DEFAULT_TIMEOUT, user, password, Protocol.DEFAULT_DATABASE); + } + public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, final int port, final int timeout) { this(poolConfig, host, port, timeout, null); @@ -156,23 +141,41 @@ public JedisPool(final GenericObjectPoolConfig poolConfig, final String h } public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String password, final int database) { - this(poolConfig, host, port, timeout, password, database, null); + int timeout, final String password) { + this(poolConfig, host, port, timeout, password, Protocol.DEFAULT_DATABASE); } public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String user, final String password, final int database) { - this(poolConfig, host, port, timeout, user, password, database, null); + int timeout, final String password, final boolean ssl) { + this(poolConfig, host, port, timeout, password, Protocol.DEFAULT_DATABASE, ssl); } public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String password, final int database, final boolean ssl) { - this(poolConfig, host, port, timeout, password, database, null, ssl); + int timeout, final String password, final boolean ssl, + final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters, + final HostnameVerifier hostnameVerifier) { + this(poolConfig, host, port, timeout, password, Protocol.DEFAULT_DATABASE, ssl, + sslSocketFactory, sslParameters, hostnameVerifier); } public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String user, final String password, final int database, final boolean ssl) { - this(poolConfig, host, port, timeout, user, password, database, null, ssl); + int timeout, final String user, final String password) { + this(poolConfig, host, port, timeout, user, password, Protocol.DEFAULT_DATABASE); + } + + public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, + int timeout, final String user, final String password, final boolean ssl) { + this(poolConfig, host, port, timeout, user, password, Protocol.DEFAULT_DATABASE, ssl); + } + + public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, + int timeout, final String password, final int database) { + this(poolConfig, host, port, timeout, password, database, null); + } + + public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, + int timeout, final String password, final int database, final boolean ssl) { + this(poolConfig, host, port, timeout, password, database, null, ssl); } public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, @@ -184,14 +187,18 @@ public JedisPool(final GenericObjectPoolConfig poolConfig, final String h } public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String password, final int database, final String clientName) { - this(poolConfig, host, port, timeout, timeout, password, database, clientName); + int timeout, final String user, final String password, final int database) { + this(poolConfig, host, port, timeout, user, password, database, null); } public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String user, final String password, final int database, - final String clientName) { - this(poolConfig, host, port, timeout, timeout, user, password, database, clientName); + int timeout, final String user, final String password, final int database, final boolean ssl) { + this(poolConfig, host, port, timeout, user, password, database, null, ssl); + } + + public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, + int timeout, final String password, final int database, final String clientName) { + this(poolConfig, host, port, timeout, timeout, password, database, clientName); } public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, @@ -200,6 +207,20 @@ public JedisPool(final GenericObjectPoolConfig poolConfig, final String h this(poolConfig, host, port, timeout, timeout, password, database, clientName, ssl); } + public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, + int timeout, final String password, final int database, final String clientName, + final boolean ssl, final SSLSocketFactory sslSocketFactory, + final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { + this(poolConfig, host, port, timeout, timeout, password, database, clientName, ssl, + sslSocketFactory, sslParameters, hostnameVerifier); + } + + public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, + int timeout, final String user, final String password, final int database, + final String clientName) { + this(poolConfig, host, port, timeout, timeout, user, password, database, clientName); + } + public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, int timeout, final String user, final String password, final int database, final String clientName, final boolean ssl) { @@ -207,11 +228,17 @@ public JedisPool(final GenericObjectPoolConfig poolConfig, final String h } public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String password, final int database, final String clientName, - final boolean ssl, final SSLSocketFactory sslSocketFactory, - final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { - this(poolConfig, host, port, timeout, timeout, password, database, clientName, ssl, - sslSocketFactory, sslParameters, hostnameVerifier); + final int connectionTimeout, final int soTimeout, final String password, final int database, + final String clientName) { + this(poolConfig, new JedisFactory(host, port, connectionTimeout, soTimeout, password, + database, clientName)); + } + + public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, + final int port, final int connectionTimeout, final int soTimeout, final String password, + final int database, final String clientName, final boolean ssl) { + this(poolConfig, host, port, connectionTimeout, soTimeout, password, database, clientName, ssl, + null, null, null); } public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, @@ -223,12 +250,17 @@ public JedisPool(final GenericObjectPoolConfig poolConfig, final String h } public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, - final int connectionTimeout, final int soTimeout, final int infiniteSoTimeout, - final String password, final int database, final String clientName, final boolean ssl, - final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters, - final HostnameVerifier hostnameVerifier) { - this(poolConfig, host, port, connectionTimeout, soTimeout, infiniteSoTimeout, null, password, - database, clientName, ssl, sslSocketFactory, sslParameters, hostnameVerifier); + final int connectionTimeout, final int soTimeout, final String user, final String password, + final int database, final String clientName) { + this(poolConfig, new JedisFactory(host, port, connectionTimeout, soTimeout, user, password, + database, clientName)); + } + + public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, + final int port, final int connectionTimeout, final int soTimeout, final String user, + final String password, final int database, final String clientName, final boolean ssl) { + this(poolConfig, host, port, connectionTimeout, soTimeout, user, password, database, + clientName, ssl, null, null, null); } public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, @@ -242,76 +274,48 @@ public JedisPool(final GenericObjectPoolConfig poolConfig, final String h public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, final int connectionTimeout, final int soTimeout, final int infiniteSoTimeout, - final String user, final String password, final int database, final String clientName, - final boolean ssl, final SSLSocketFactory sslSocketFactory, - final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { - this(poolConfig, new JedisFactory(host, port, connectionTimeout, soTimeout, infiniteSoTimeout, - user, password, database, clientName, ssl, sslSocketFactory, sslParameters, - hostnameVerifier)); - } - - public JedisPool(final HostAndPort hostAndPort, final JedisClientConfig clientConfig) { - this(new GenericObjectPoolConfig(), hostAndPort, clientConfig); - } - - public JedisPool(final GenericObjectPoolConfig poolConfig, final HostAndPort hostAndPort, - final JedisClientConfig clientConfig) { - this(poolConfig, new JedisFactory(hostAndPort, clientConfig)); - } - - public JedisPool(final GenericObjectPoolConfig poolConfig, final JedisSocketFactory jedisSocketFactory, - final JedisClientConfig clientConfig) { - this(poolConfig, new JedisFactory(jedisSocketFactory, clientConfig)); - } - - public JedisPool(final GenericObjectPoolConfig poolConfig) { - this(poolConfig, Protocol.DEFAULT_HOST, Protocol.DEFAULT_PORT); - } - - public JedisPool(final String host, final int port, final boolean ssl) { - this(new GenericObjectPoolConfig(), host, port, ssl); - } - - public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, - final int connectionTimeout, final int soTimeout, final String password, final int database, - final String clientName) { - this(poolConfig, new JedisFactory(host, port, connectionTimeout, soTimeout, password, - database, clientName)); + final String password, final int database, final String clientName, final boolean ssl, + final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters, + final HostnameVerifier hostnameVerifier) { + this(poolConfig, host, port, connectionTimeout, soTimeout, infiniteSoTimeout, null, password, + database, clientName, ssl, sslSocketFactory, sslParameters, hostnameVerifier); } public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, - final int connectionTimeout, final int soTimeout, final String user, final String password, - final int database, final String clientName) { - this(poolConfig, new JedisFactory(host, port, connectionTimeout, soTimeout, user, password, - database, clientName)); + final int connectionTimeout, final int soTimeout, final int infiniteSoTimeout, + final String user, final String password, final int database, final String clientName) { + this(poolConfig, new JedisFactory(host, port, connectionTimeout, soTimeout, infiniteSoTimeout, + user, password, database, clientName)); } public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, final int connectionTimeout, final int soTimeout, final int infiniteSoTimeout, - final String user, final String password, final int database, final String clientName) { + final String user, final String password, final int database, final String clientName, + final boolean ssl, final SSLSocketFactory sslSocketFactory, + final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { this(poolConfig, new JedisFactory(host, port, connectionTimeout, soTimeout, infiniteSoTimeout, - user, password, database, clientName)); + user, password, database, clientName, ssl, sslSocketFactory, sslParameters, + hostnameVerifier)); } - public JedisPool(final String host, final int port, final boolean ssl, - final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters, - final HostnameVerifier hostnameVerifier) { - this(new GenericObjectPoolConfig(), host, port, ssl, sslSocketFactory, sslParameters, + public JedisPool(final URI uri) { + this(new GenericObjectPoolConfig(), uri); + } + + public JedisPool(final URI uri, final SSLSocketFactory sslSocketFactory, + final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { + this(new GenericObjectPoolConfig(), uri, sslSocketFactory, sslParameters, hostnameVerifier); } - public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, - final int port, final int connectionTimeout, final int soTimeout, final String password, - final int database, final String clientName, final boolean ssl) { - this(poolConfig, host, port, connectionTimeout, soTimeout, password, database, clientName, ssl, - null, null, null); + public JedisPool(final URI uri, final int timeout) { + this(new GenericObjectPoolConfig(), uri, timeout); } - public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, - final int port, final int connectionTimeout, final int soTimeout, final String user, - final String password, final int database, final String clientName, final boolean ssl) { - this(poolConfig, host, port, connectionTimeout, soTimeout, user, password, database, - clientName, ssl, null, null, null); + public JedisPool(final URI uri, final int timeout, final SSLSocketFactory sslSocketFactory, + final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { + this(new GenericObjectPoolConfig(), uri, timeout, sslSocketFactory, sslParameters, + hostnameVerifier); } public JedisPool(final GenericObjectPoolConfig poolConfig, final URI uri) { @@ -355,6 +359,16 @@ public JedisPool(final GenericObjectPoolConfig poolConfig, final URI uri, sslSocketFactory, sslParameters, hostnameVerifier)); } + public JedisPool(final GenericObjectPoolConfig poolConfig, final HostAndPort hostAndPort, + final JedisClientConfig clientConfig) { + this(poolConfig, new JedisFactory(hostAndPort, clientConfig)); + } + + public JedisPool(final GenericObjectPoolConfig poolConfig, + final JedisSocketFactory jedisSocketFactory, final JedisClientConfig clientConfig) { + this(poolConfig, new JedisFactory(jedisSocketFactory, clientConfig)); + } + public JedisPool(GenericObjectPoolConfig poolConfig, PooledObjectFactory factory) { super(poolConfig, factory); } diff --git a/src/main/java/redis/clients/jedis/JedisPooled.java b/src/main/java/redis/clients/jedis/JedisPooled.java index 4d705b2164..bc751527ca 100644 --- a/src/main/java/redis/clients/jedis/JedisPooled.java +++ b/src/main/java/redis/clients/jedis/JedisPooled.java @@ -18,20 +18,11 @@ public JedisPooled() { this(Protocol.DEFAULT_HOST, Protocol.DEFAULT_PORT); } - public JedisPooled(final GenericObjectPoolConfig poolConfig, final String url) { - this(poolConfig, URI.create(url)); - } - - public JedisPooled(String host, int port) { - this(new GenericObjectPoolConfig(), host, port); - } - /** - * WARNING: This constructor only accepts a uri string as {@code url}. - * {@link JedisURIHelper#isValid(java.net.URI)} can be used before this. + * WARNING: This constructor only accepts a uri string as {@code url}. {@link JedisURIHelper#isValid(java.net.URI)} + * can be used before this. *

- * To use a host string, {@link #JedisPooled(java.lang.String, int)} can be used with - * {@link Protocol#DEFAULT_PORT}. + * To use a host string, {@link #JedisPooled(java.lang.String, int)} can be used with {@link Protocol#DEFAULT_PORT}. * * @param url */ @@ -40,12 +31,12 @@ public JedisPooled(final String url) { } /** - * WARNING: This constructor only accepts a uri string as {@code url}. - * {@link JedisURIHelper#isValid(java.net.URI)} can be used before this. + * WARNING: This constructor only accepts a uri string as {@code url}. {@link JedisURIHelper#isValid(java.net.URI)} + * can be used before this. *

- * To use a host string, - * {@link #JedisPooled(java.lang.String, int, boolean, javax.net.ssl.SSLSocketFactory, javax.net.ssl.SSLParameters, javax.net.ssl.HostnameVerifier)} - * can be used with {@link Protocol#DEFAULT_PORT} and {@code ssl=true}. + * To use a host string, {@link #JedisPooled(java.lang.String, int, boolean, javax.net.ssl.SSLSocketFactory, + * javax.net.ssl.SSLParameters, javax.net.ssl.HostnameVerifier)} can be used with {@link Protocol#DEFAULT_PORT} and + * {@code ssl=true}. * * @param url * @param sslSocketFactory @@ -57,62 +48,55 @@ public JedisPooled(final String url, final SSLSocketFactory sslSocketFactory, this(URI.create(url), sslSocketFactory, sslParameters, hostnameVerifier); } - public JedisPooled(final URI uri) { - super(uri); + public JedisPooled(final String host, final int port) { + this(new HostAndPort(host, port)); } - public JedisPooled(final URI uri, final SSLSocketFactory sslSocketFactory, - final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { - this(new GenericObjectPoolConfig(), uri, sslSocketFactory, sslParameters, - hostnameVerifier); + public JedisPooled(final HostAndPort hostAndPort) { + this(new PooledConnectionProvider(hostAndPort)); } - public JedisPooled(final URI uri, final int timeout) { - this(new GenericObjectPoolConfig(), uri, timeout); - } - - public JedisPooled(final URI uri, final int timeout, final SSLSocketFactory sslSocketFactory, - final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { - this(new GenericObjectPoolConfig(), uri, timeout, sslSocketFactory, sslParameters, - hostnameVerifier); - } - - public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String password) { - this(poolConfig, host, port, timeout, password, Protocol.DEFAULT_DATABASE); + public JedisPooled(final String host, final int port, final boolean ssl) { + this(new HostAndPort(host, port), DefaultJedisClientConfig.builder().ssl(ssl).build()); } - public JedisPooled(final String host, int port, String user, final String password) { - this(new GenericObjectPoolConfig(), host, port, user, password); + public JedisPooled(final String host, final int port, final boolean ssl, + final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters, + final HostnameVerifier hostnameVerifier) { + this(new HostAndPort(host, port), DefaultJedisClientConfig.builder().ssl(ssl) + .sslSocketFactory(sslSocketFactory).sslParameters(sslParameters) + .hostnameVerifier(hostnameVerifier).build()); } - public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, - String user, final String password) { - this(poolConfig, host, port, Protocol.DEFAULT_TIMEOUT, user, password, - Protocol.DEFAULT_DATABASE); + public JedisPooled(final String host, final int port, final String user, final String password) { + this(new HostAndPort(host, port), DefaultJedisClientConfig.builder().user(user).password(password).build()); } - public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String user, final String password) { - this(poolConfig, host, port, timeout, user, password, Protocol.DEFAULT_DATABASE); + public JedisPooled(final HostAndPort hostAndPort, final JedisClientConfig clientConfig) { + this(new PooledConnectionProvider(hostAndPort, clientConfig)); } - public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String password, final boolean ssl) { - this(poolConfig, host, port, timeout, password, Protocol.DEFAULT_DATABASE, ssl); + public JedisPooled(PooledObjectFactory factory) { + this(new PooledConnectionProvider(factory)); } - public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String user, final String password, final boolean ssl) { - this(poolConfig, host, port, timeout, user, password, Protocol.DEFAULT_DATABASE, ssl); + public JedisPooled(final GenericObjectPoolConfig poolConfig) { + this(poolConfig, Protocol.DEFAULT_HOST, Protocol.DEFAULT_PORT); } - public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String password, final boolean ssl, - final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters, - final HostnameVerifier hostnameVerifier) { - this(poolConfig, host, port, timeout, password, Protocol.DEFAULT_DATABASE, ssl, - sslSocketFactory, sslParameters, hostnameVerifier); + /** + * WARNING: This constructor only accepts a uri string as {@code url}. {@link JedisURIHelper#isValid(java.net.URI)} + * can be used before this. + *

+ * To use a host string, + * {@link #JedisPooled(org.apache.commons.pool2.impl.GenericObjectPoolConfig, java.lang.String, int)} can be used with + * {@link Protocol#DEFAULT_PORT}. + * + * @param poolConfig + * @param url + */ + public JedisPooled(final GenericObjectPoolConfig poolConfig, final String url) { + this(poolConfig, URI.create(url)); } public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, @@ -132,6 +116,12 @@ public JedisPooled(final GenericObjectPoolConfig poolConfig, final S hostnameVerifier); } + public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, + final int port, final String user, final String password) { + this(poolConfig, host, port, Protocol.DEFAULT_TIMEOUT, user, password, + Protocol.DEFAULT_DATABASE); + } + public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, final int port, final int timeout) { this(poolConfig, host, port, timeout, null); @@ -151,23 +141,40 @@ public JedisPooled(final GenericObjectPoolConfig poolConfig, final S } public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String password, final int database) { - this(poolConfig, host, port, timeout, password, database, null); + int timeout, final String password) { + this(poolConfig, host, port, timeout, password, Protocol.DEFAULT_DATABASE); } public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String user, final String password, final int database) { - this(poolConfig, host, port, timeout, user, password, database, null); + int timeout, final String password, final boolean ssl) { + this(poolConfig, host, port, timeout, password, Protocol.DEFAULT_DATABASE, ssl); } public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String password, final int database, final boolean ssl) { - this(poolConfig, host, port, timeout, password, database, null, ssl); + int timeout, final String password, final boolean ssl, final SSLSocketFactory sslSocketFactory, + final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { + this(poolConfig, host, port, timeout, password, Protocol.DEFAULT_DATABASE, ssl, sslSocketFactory, + sslParameters, hostnameVerifier); } public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String user, final String password, final int database, final boolean ssl) { - this(poolConfig, host, port, timeout, user, password, database, null, ssl); + int timeout, final String user, final String password) { + this(poolConfig, host, port, timeout, user, password, Protocol.DEFAULT_DATABASE); + } + + public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, + int timeout, final String user, final String password, final boolean ssl) { + this(poolConfig, host, port, timeout, user, password, Protocol.DEFAULT_DATABASE, ssl); + } + + public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, + int timeout, final String password, final int database) { + this(poolConfig, host, port, timeout, password, database, null); + } + + public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, + int timeout, final String password, final int database, final boolean ssl) { + this(poolConfig, host, port, timeout, password, database, null, ssl); } public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, @@ -179,26 +186,24 @@ public JedisPooled(final GenericObjectPoolConfig poolConfig, final S } public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String password, final int database, final String clientName) { - this(poolConfig, host, port, timeout, timeout, password, database, clientName); + int timeout, final String user, final String password, final int database) { + this(poolConfig, host, port, timeout, user, password, database, null); } public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String user, final String password, final int database, - final String clientName) { - this(poolConfig, host, port, timeout, timeout, user, password, database, clientName); + int timeout, final String user, final String password, final int database, final boolean ssl) { + this(poolConfig, host, port, timeout, user, password, database, null, ssl); } public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String password, final int database, final String clientName, - final boolean ssl) { - this(poolConfig, host, port, timeout, timeout, password, database, clientName, ssl); + int timeout, final String password, final int database, final String clientName) { + this(poolConfig, host, port, timeout, timeout, password, database, clientName); } public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, - int timeout, final String user, final String password, final int database, - final String clientName, final boolean ssl) { - this(poolConfig, host, port, timeout, timeout, user, password, database, clientName, ssl); + int timeout, final String password, final int database, final String clientName, + final boolean ssl) { + this(poolConfig, host, port, timeout, timeout, password, database, clientName, ssl); } public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, @@ -210,73 +215,67 @@ public JedisPooled(final GenericObjectPoolConfig poolConfig, final S } public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, - final int connectionTimeout, final int soTimeout, final String password, final int database, - final String clientName, final boolean ssl, final SSLSocketFactory sslSocketFactory, - final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { - this(poolConfig, host, port, connectionTimeout, soTimeout, 0, password, database, clientName, - ssl, sslSocketFactory, sslParameters, hostnameVerifier); + int timeout, final String user, final String password, final int database, + final String clientName) { + this(poolConfig, host, port, timeout, timeout, user, password, database, clientName); } public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, - final int connectionTimeout, final int soTimeout, final int infiniteSoTimeout, - final String password, final int database, final String clientName, final boolean ssl, - final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters, - final HostnameVerifier hostnameVerifier) { - this(poolConfig, host, port, connectionTimeout, soTimeout, infiniteSoTimeout, null, password, - database, clientName, ssl, sslSocketFactory, sslParameters, hostnameVerifier); + int timeout, final String user, final String password, final int database, + final String clientName, final boolean ssl) { + this(poolConfig, host, port, timeout, timeout, user, password, database, clientName, ssl); } public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, - final int connectionTimeout, final int soTimeout, final String user, final String password, - final int database, final String clientName, final boolean ssl, - final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters, - final HostnameVerifier hostnameVerifier) { - this(poolConfig, host, port, connectionTimeout, soTimeout, 0, user, password, database, - clientName, ssl, sslSocketFactory, sslParameters, hostnameVerifier); + final int connectionTimeout, final int soTimeout, final String password, final int database, + final String clientName) { + this(poolConfig, host, port, connectionTimeout, soTimeout, null, password, database, clientName); } public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, - final int connectionTimeout, final int soTimeout, final int infiniteSoTimeout, - final String user, final String password, final int database, final String clientName, - final boolean ssl, final SSLSocketFactory sslSocketFactory, - final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { - this(new HostAndPort(host, port), DefaultJedisClientConfig.create(connectionTimeout, soTimeout, - infiniteSoTimeout, user, password, database, clientName, ssl, sslSocketFactory, sslParameters, - hostnameVerifier, null)); - } - - public JedisPooled(final HostAndPort hostAndPort, final JedisClientConfig clientConfig) { - this(new GenericObjectPoolConfig(), hostAndPort, clientConfig); - } - - public JedisPooled(final GenericObjectPoolConfig poolConfig, final HostAndPort hostAndPort, - final JedisClientConfig clientConfig) { - this(hostAndPort, clientConfig, poolConfig); + final int connectionTimeout, final int soTimeout, final String password, final int database, + final String clientName, final boolean ssl) { + this(poolConfig, host, port, connectionTimeout, soTimeout, password, database, clientName, ssl, + null, null, null); } - public JedisPooled(final GenericObjectPoolConfig poolConfig, final JedisSocketFactory jedisSocketFactory, - final JedisClientConfig clientConfig) { - this(new ConnectionFactory(jedisSocketFactory, clientConfig), poolConfig); + public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, + final int connectionTimeout, final int soTimeout, final String password, final int database, + final String clientName, final boolean ssl, final SSLSocketFactory sslSocketFactory, + final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { + this(poolConfig, host, port, connectionTimeout, soTimeout, null, password, database, clientName, + ssl, sslSocketFactory, sslParameters, hostnameVerifier); } - public JedisPooled(final GenericObjectPoolConfig poolConfig) { - this(poolConfig, Protocol.DEFAULT_HOST, Protocol.DEFAULT_PORT); + public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, + final int connectionTimeout, final int soTimeout, final String user, final String password, + final int database, final String clientName) { + this(poolConfig, host, port, connectionTimeout, soTimeout, 0, user, password, database, clientName); } - public JedisPooled(final String host, final int port, final boolean ssl) { - this(new GenericObjectPoolConfig(), host, port, ssl); + public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, + final int connectionTimeout, final int soTimeout, final String user, final String password, + final int database, final String clientName, final boolean ssl) { + this(poolConfig, host, port, connectionTimeout, soTimeout, user, password, database, clientName, + ssl, null, null, null); } public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, - final int connectionTimeout, final int soTimeout, final String password, final int database, - final String clientName) { - this(poolConfig, host, port, connectionTimeout, soTimeout, null, password, database, clientName); + final int connectionTimeout, final int soTimeout, final String user, final String password, + final int database, final String clientName, final boolean ssl, + final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters, + final HostnameVerifier hostnameVerifier) { + this(poolConfig, host, port, connectionTimeout, soTimeout, 0, user, password, database, + clientName, ssl, sslSocketFactory, sslParameters, hostnameVerifier); } public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, - final int connectionTimeout, final int soTimeout, final String user, final String password, - final int database, final String clientName) { - this(poolConfig, host, port, connectionTimeout, soTimeout, 0, user, password, database, clientName); + final int connectionTimeout, final int soTimeout, final int infiniteSoTimeout, + final String password, final int database, final String clientName, final boolean ssl, + final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters, + final HostnameVerifier hostnameVerifier) { + this(poolConfig, host, port, connectionTimeout, soTimeout, infiniteSoTimeout, null, password, + database, clientName, ssl, sslSocketFactory, sslParameters, hostnameVerifier); } public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, @@ -287,25 +286,34 @@ public JedisPooled(final GenericObjectPoolConfig poolConfig, final S poolConfig); } - public JedisPooled(final String host, final int port, final boolean ssl, + public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, int port, + final int connectionTimeout, final int soTimeout, final int infiniteSoTimeout, final String user, + final String password, final int database, final String clientName, final boolean ssl, final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { - this(new GenericObjectPoolConfig(), host, port, ssl, sslSocketFactory, sslParameters, + this(new HostAndPort(host, port), DefaultJedisClientConfig.create(connectionTimeout, soTimeout, + infiniteSoTimeout, user, password, database, clientName, ssl, sslSocketFactory, sslParameters, + hostnameVerifier, null), poolConfig); + } + + public JedisPooled(final URI uri) { + super(uri); + } + + public JedisPooled(final URI uri, final SSLSocketFactory sslSocketFactory, + final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { + this(new GenericObjectPoolConfig(), uri, sslSocketFactory, sslParameters, hostnameVerifier); } - public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, - final int port, final int connectionTimeout, final int soTimeout, final String password, - final int database, final String clientName, final boolean ssl) { - this(poolConfig, host, port, connectionTimeout, soTimeout, password, database, clientName, ssl, - null, null, null); + public JedisPooled(final URI uri, final int timeout) { + this(new GenericObjectPoolConfig(), uri, timeout); } - public JedisPooled(final GenericObjectPoolConfig poolConfig, final String host, - final int port, final int connectionTimeout, final int soTimeout, final String user, - final String password, final int database, final String clientName, final boolean ssl) { - this(poolConfig, host, port, connectionTimeout, soTimeout, user, password, database, - clientName, ssl, null, null, null); + public JedisPooled(final URI uri, final int timeout, final SSLSocketFactory sslSocketFactory, + final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) { + this(new GenericObjectPoolConfig(), uri, timeout, sslSocketFactory, sslParameters, + hostnameVerifier); } public JedisPooled(final GenericObjectPoolConfig poolConfig, final URI uri) { @@ -319,7 +327,8 @@ public JedisPooled(final GenericObjectPoolConfig poolConfig, final U hostnameVerifier); } - public JedisPooled(final GenericObjectPoolConfig poolConfig, final URI uri, final int timeout) { + public JedisPooled(final GenericObjectPoolConfig poolConfig, final URI uri, + final int timeout) { this(poolConfig, uri, timeout, timeout); } @@ -344,26 +353,36 @@ 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)); + 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(GenericObjectPoolConfig poolConfig, PooledObjectFactory factory) { - this(factory, poolConfig); + public JedisPooled(final HostAndPort hostAndPort, final GenericObjectPoolConfig poolConfig) { + this(hostAndPort, DefaultJedisClientConfig.builder().build(), poolConfig); + } + + public JedisPooled(final GenericObjectPoolConfig poolConfig, final HostAndPort hostAndPort, + final JedisClientConfig clientConfig) { + this(hostAndPort, clientConfig, poolConfig); } - public JedisPooled(HostAndPort hostAndPort) { - this(new ConnectionFactory(hostAndPort), new GenericObjectPoolConfig()); + public JedisPooled(final HostAndPort hostAndPort, final JedisClientConfig clientConfig, + final GenericObjectPoolConfig poolConfig) { + this(new PooledConnectionProvider(hostAndPort, clientConfig, poolConfig)); } - public JedisPooled(HostAndPort hostAndPort, GenericObjectPoolConfig poolConfig) { - this(new ConnectionFactory(hostAndPort), poolConfig); + public JedisPooled(final GenericObjectPoolConfig poolConfig, + final JedisSocketFactory jedisSocketFactory, final JedisClientConfig clientConfig) { + this(new ConnectionFactory(jedisSocketFactory, clientConfig), poolConfig); } - public JedisPooled(HostAndPort hostAndPort, JedisClientConfig clientConfig, GenericObjectPoolConfig poolConfig) { - this(new ConnectionFactory(hostAndPort, clientConfig), poolConfig); + public JedisPooled(GenericObjectPoolConfig poolConfig, PooledObjectFactory factory) { + this(factory, poolConfig); } public JedisPooled(PooledObjectFactory factory, GenericObjectPoolConfig poolConfig) { @@ -377,4 +396,9 @@ public JedisPooled(PooledConnectionProvider provider) { public final Pool getPool() { return ((PooledConnectionProvider) provider).getPool(); } + + @Override + public Pipeline pipelined() { + return (Pipeline) super.pipelined(); + } } 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 6ec7c2c74f..586750540c 100644 --- a/src/main/java/redis/clients/jedis/JedisSentinelPool.java +++ b/src/main/java/redis/clients/jedis/JedisSentinelPool.java @@ -30,6 +30,11 @@ public class JedisSentinelPool extends Pool { private final Object initPoolLock = new Object(); + public JedisSentinelPool(String masterName, Set sentinels, + final JedisClientConfig masterClientConfig, final JedisClientConfig sentinelClientConfig) { + this(masterName, sentinels, new JedisFactory(masterClientConfig), sentinelClientConfig); + } + public JedisSentinelPool(String masterName, Set sentinels, final GenericObjectPoolConfig poolConfig) { this(masterName, sentinels, poolConfig, Protocol.DEFAULT_TIMEOUT, null, @@ -162,14 +167,20 @@ public JedisSentinelPool(String masterName, Set sentinels, } public JedisSentinelPool(String masterName, Set sentinels, - final JedisClientConfig masteClientConfig, final JedisClientConfig sentinelClientConfig) { - this(masterName, sentinels, new GenericObjectPoolConfig(), masteClientConfig, sentinelClientConfig); + final GenericObjectPoolConfig poolConfig, final JedisClientConfig masterClientConfig, + final JedisClientConfig sentinelClientConfig) { + this(masterName, sentinels, poolConfig, new JedisFactory(masterClientConfig), sentinelClientConfig); } public JedisSentinelPool(String masterName, Set sentinels, - final GenericObjectPoolConfig poolConfig, final JedisClientConfig masteClientConfig, - final JedisClientConfig sentinelClientConfig) { - this(masterName, sentinels, poolConfig, new JedisFactory(masteClientConfig), sentinelClientConfig); + final JedisFactory factory, final JedisClientConfig sentinelClientConfig) { + super(factory); + + this.factory = factory; + this.sentinelClientConfig = sentinelClientConfig; + + HostAndPort master = initSentinels(sentinels, masterName); + initMaster(master); } 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 new file mode 100644 index 0000000000..063d1c40d9 --- /dev/null +++ b/src/main/java/redis/clients/jedis/JedisSentineled.java @@ -0,0 +1,32 @@ +package redis.clients.jedis; + +import java.util.Set; +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import redis.clients.jedis.providers.SentineledConnectionProvider; + +public class JedisSentineled extends UnifiedJedis { + + public JedisSentineled(String masterName, final JedisClientConfig masterClientConfig, + Set sentinels, final JedisClientConfig sentinelClientConfig) { + this(new SentineledConnectionProvider(masterName, masterClientConfig, sentinels, sentinelClientConfig)); + } + + public JedisSentineled(String masterName, final JedisClientConfig masterClientConfig, + final GenericObjectPoolConfig poolConfig, + Set sentinels, final JedisClientConfig sentinelClientConfig) { + this(new SentineledConnectionProvider(masterName, masterClientConfig, poolConfig, sentinels, sentinelClientConfig)); + } + + public JedisSentineled(SentineledConnectionProvider sentineledConnectionProvider) { + super(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 a1cb7371e4..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) { @@ -39,4 +47,23 @@ public JedisSharding(ShardedConnectionProvider provider) { 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 1b6065c16a..eef6b2a810 100644 --- a/src/main/java/redis/clients/jedis/MultiNodePipelineBase.java +++ b/src/main/java/redis/clients/jedis/MultiNodePipelineBase.java @@ -1,67 +1,64 @@ 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.BFInsertParams; -import redis.clients.jedis.bloom.BFReserveParams; -import redis.clients.jedis.bloom.CFInsertParams; -import redis.clients.jedis.bloom.CFReserveParams; 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.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.timeseries.*; -import redis.clients.jedis.util.KeyValue; +import redis.clients.jedis.util.IOUtils; + +public abstract class MultiNodePipelineBase extends PipelineBase + implements PipelineCommands, PipelineBinaryCommands, RedisModulePipelineCommands, Closeable { -public abstract class MultiNodePipelineBase implements PipelineCommands, PipelineBinaryCommands, - RedisModulePipelineCommands, Closeable { + 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 synced; - - private final CommandObjects commandObjects; - private GraphCommandObjects graphCommandObjects; + private volatile boolean syncing = false; public MultiNodePipelineBase(CommandObjects commandObjects) { + super(commandObjects); pipelinedResponses = new LinkedHashMap<>(); connections = new LinkedHashMap<>(); - synced = false; - 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()); @@ -71,10 +68,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()); @@ -85,3956 +88,60 @@ protected final Response appendCommand(CommandObject commandObject) { @Override public void close() { - sync(); - for (Connection connection : connections.values()) { - connection.close(); + try { + sync(); + } finally { + connections.values().forEach(IOUtils::closeQuietly); } } + @Override public final void sync() { - if (synced) { + if (syncing) { return; } - for (Map.Entry>> entry : pipelinedResponses.entrySet()) { + 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()) { + Map.Entry>> entry = pipelinedResponsesIterator.next(); HostAndPort nodeKey = entry.getKey(); Queue> queue = entry.getValue(); - List unformatted = connections.get(nodeKey).getMany(queue.size()); - for (Object o : unformatted) { - queue.poll().set(o); - } + Connection connection = connections.get(nodeKey); + 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(); + } + }); } - synced = true; - } - - @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 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)); - } + try { + countDownLatch.await(); + } catch (InterruptedException e) { + log.error("Thread is interrupted during sync.", e); + } - @Override - public Response set(String key, String value, SetParams params) { - return appendCommand(commandObjects.set(key, value, params)); - } + executorService.shutdownNow(); - @Override - public Response rpush(String key, String... string) { - return appendCommand(commandObjects.rpush(key, string)); + syncing = false; } - @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 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 ftAlter(String indexName, Schema schema) { - return appendCommand(commandObjects.ftAlter(indexName, schema)); - } - - @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> ftInfo(String indexName) { - return appendCommand(commandObjects.ftInfo(indexName)); - } - - @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)); - } - // 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> 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)); - } - - @Override - public Response ftCreate(String indexName, IndexOptions indexOptions, Schema schema) { - return appendCommand(commandObjects.ftCreate(indexName, indexOptions, schema)); - } - // 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>> 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 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> 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> 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)); - } - // 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)); - } - // 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 2b0bbc34c2..67e3523702 100644 --- a/src/main/java/redis/clients/jedis/Pipeline.java +++ b/src/main/java/redis/clients/jedis/Pipeline.java @@ -2,70 +2,59 @@ 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.BFInsertParams; -import redis.clients.jedis.bloom.BFReserveParams; -import redis.clients.jedis.bloom.CFInsertParams; -import redis.clients.jedis.bloom.CFReserveParams; 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.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.timeseries.*; import redis.clients.jedis.util.KeyValue; -public class Pipeline extends Queable implements PipelineCommands, PipelineBinaryCommands, +public class Pipeline extends PipelineBase implements PipelineCommands, PipelineBinaryCommands, DatabasePipelineCommands, RedisModulePipelineCommands, Closeable { + private final Queue> pipelinedResponses = new LinkedList<>(); protected final Connection connection; -// private final Jedis jedis; - private final CommandObjects commandObjects; - private final GraphCommandObjects graphCommandObjects; + private final boolean closeConnection; + //private final CommandObjects commandObjects; + + public Pipeline(Jedis jedis) { + this(jedis.getConnection(), false); + } public Pipeline(Connection connection) { -// super(connection); - this.connection = connection; -// this.jedis = null; - this.commandObjects = new CommandObjects(); - this.graphCommandObjects = new GraphCommandObjects(this.connection); + this(connection, false); } - public Pipeline(Jedis jedis) { -// super(jedis.getConnection()); - this.connection = jedis.getConnection(); -// this.jedis = jedis; - this.commandObjects = new CommandObjects(); - this.graphCommandObjects = new GraphCommandObjects(this.connection); + public Pipeline(Connection connection, boolean closeConnection) { + super(new CommandObjects()); + this.connection = connection; + this.closeConnection = closeConnection; + 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 public void close() { sync(); + + if (closeConnection) { + connection.close(); + } } /** @@ -73,11 +62,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()); + List unformatted = connection.getMany(pipelinedResponses.size()); for (Object o : unformatted) { - generateResponse(o); + pipelinedResponses.poll().set(o); } } @@ -89,11 +79,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) { try { - formatted.add(generateResponse(o).get()); + Response response = pipelinedResponses.poll(); + response.set(o); + formatted.add(response.get()); } catch (JedisDataException e) { formatted.add(e); } @@ -105,4017 +97,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)); - } - - @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 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)); + return pipelinedResponses.size() > 0; } - @Override - public Response bitpos(String key, boolean value, BitPosParams params) { - return appendCommand(commandObjects.bitpos(key, value, params)); + public Response waitReplicas(int replicas, long timeout) { + return appendCommand(commandObjects.waitReplicas(replicas, timeout)); } - @Override - public Response> bitfield(String key, String... arguments) { - return appendCommand(commandObjects.bitfield(key, arguments)); + public Response> waitAOF(long numLocal, long numReplicas, long timeout) { + return appendCommand(commandObjects.waitAOF(numLocal, numReplicas, timeout)); } - @Override - public Response> bitfieldReadonly(String key, String... arguments) { - return appendCommand(commandObjects.bitfieldReadonly(key, arguments)); + public Response> time() { + return appendCommand(new CommandObject<>(commandObjects.commandArguments(Protocol.Command.TIME), BuilderFactory.STRING_LIST)); } @Override - public Response bitop(BitOP op, String destKey, String... srcKeys) { - return appendCommand(commandObjects.bitop(op, destKey, srcKeys)); + public Response select(final int index) { + return appendCommand(new CommandObject<>(commandObjects.commandArguments(Protocol.Command.SELECT).add(index), BuilderFactory.STRING)); } @Override - public Response strAlgoLCSKeys(String keyA, String keyB, StrAlgoLCSParams params) { - return appendCommand(commandObjects.strAlgoLCSKeys(keyA, keyB, params)); + public Response dbSize() { + return appendCommand(new CommandObject<>(commandObjects.commandArguments(Protocol.Command.DBSIZE), BuilderFactory.LONG)); } @Override - public Response lcs(String keyA, String keyB, LCSParams params) { - return appendCommand(commandObjects.lcs(keyA, keyB, params)); + 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) { - return appendCommand(commandObjects.set(key, value)); + 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 set(String key, String value, SetParams params) { - return appendCommand(commandObjects.set(key, value, params)); + 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 rpush(String key, String... string) { - return appendCommand(commandObjects.rpush(key, string)); - + public Response copy(String srcKey, String dstKey, int db, boolean replace) { + return appendCommand(commandObjects.copy(srcKey, dstKey, db, replace)); } @Override - public Response lpush(String key, String... string) { - return appendCommand(commandObjects.lpush(key, string)); + public Response copy(byte[] srcKey, byte[] 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 migrate(String host, int port, byte[] key, int destinationDB, int timeout) { + return appendCommand(commandObjects.migrate(host, port, key, destinationDB, timeout)); } @Override - public Response> lrange(String key, long start, long stop) { - return appendCommand(commandObjects.lrange(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 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 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 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 ftAlter(String indexName, Schema schema) { - return appendCommand(commandObjects.ftAlter(indexName, schema)); - } - - @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> ftInfo(String indexName) { - return appendCommand(commandObjects.ftInfo(indexName)); - } - - @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)); - } - // 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> 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>> 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 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> 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> 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)); - } - // 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)); - } - // 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..aa2b33e9e7 --- /dev/null +++ b/src/main/java/redis/clients/jedis/PipelineBase.java @@ -0,0 +1,4259 @@ +package redis.clients.jedis; + +import java.io.Closeable; +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 PipelineBase implements PipelineCommands, PipelineBinaryCommands, + RedisModulePipelineCommands, Closeable { + + protected final CommandObjects commandObjects; + private GraphCommandObjects graphCommandObjects; + + public PipelineBase(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 abstract void close(); + + /** + * Synchronize pipeline by reading all responses. + */ + public abstract void sync(); + + @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 publish(String channel, String message) { + return appendCommand(commandObjects.publish(channel, message)); + } + + public Response publish(byte[] channel, byte[] message) { + return appendCommand(commandObjects.publish(channel, message)); + } + + 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 cce61636d0..d7c36503fc 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, @Deprecated STRALGO, RESET; + 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, ASC, BY, DESC, GET, LIMIT, NO, NOSORT, ONE, SET, STORE, WEIGHTS, WITHSCORES, + 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, LIST, ID, KILL, PAUSE, UNBLOCK, + 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, - @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; 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 911156757b..a0db77a068 100644 --- a/src/main/java/redis/clients/jedis/ReliableTransaction.java +++ b/src/main/java/redis/clients/jedis/ReliableTransaction.java @@ -3,19 +3,51 @@ import java.util.List; import redis.clients.jedis.exceptions.JedisException; +/** + * ReliableTransaction is a transaction where commands are immediately sent to Redis server and the + * 'QUEUED' reply checked. + */ public class ReliableTransaction extends TransactionBase { + private static final String QUEUED_STR = "QUEUED"; + + /** + * 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); } /** - * If you want to WATCH/UNWATCH keys before MULTI command you should do {@code doMulti = 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 ReliableTransaction(Connection connection, boolean doMulti) { super(connection, doMulti); } + /** + * 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) { + super(connection, doMulti, closeConnection); + } + @Override protected final void processMultiResponse() { String status = connection.getStatusCodeReply(); @@ -27,13 +59,13 @@ protected final void processMultiResponse() { @Override protected final void processAppendStatus() { String status = connection.getStatusCodeReply(); - if (!"QUEUED".equals(status)) { + if (!QUEUED_STR.equals(status)) { throw new JedisException(status); } } @Override - protected final void processPipelinedResponses() { + protected final void processPipelinedResponses(int pipelineLength) { // do nothing } 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 fad28538da..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() { @@ -113,10 +113,8 @@ public String toString() { /** * Should be used only with XREADGROUP - * - * - * XREADGROUP $GroupName $ConsumerName BLOCK 2000 COUNT 10 STREAMS mystream > - * + *

+ * {@code XREADGROUP $GroupName $ConsumerName BLOCK 2000 COUNT 10 STREAMS mystream >} */ public static final StreamEntryID UNRECEIVED_ENTRY = new StreamEntryID() { diff --git a/src/main/java/redis/clients/jedis/Transaction.java b/src/main/java/redis/clients/jedis/Transaction.java index 278e5fd4bd..a799ae3da9 100644 --- a/src/main/java/redis/clients/jedis/Transaction.java +++ b/src/main/java/redis/clients/jedis/Transaction.java @@ -2,28 +2,61 @@ import java.util.List; +/** + * A pipeline based transaction. + */ public class Transaction extends TransactionBase { private final Jedis jedis; + // Legacy - to support Jedis.multi() + // TODO: Should be package private ?? public Transaction(Jedis jedis) { super(jedis.getConnection()); this.jedis = jedis; } + /** + * 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. + * @param connection connection + */ public Transaction(Connection connection) { super(connection); this.jedis = null; } /** - * If you want to WATCH/UNWATCH keys before MULTI command you should do {@code doMulti = 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 Transaction(Connection connection, boolean doMulti) { super(connection, doMulti); this.jedis = null; } + /** + * 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) { + super(connection, doMulti, closeConnection); + this.jedis = null; + } + @Override protected final void processMultiResponse() { // do nothing @@ -35,9 +68,9 @@ protected final void processAppendStatus() { } @Override - protected final void processPipelinedResponses() { + protected final void processPipelinedResponses(int pipelineLength) { // ignore QUEUED or ERROR - connection.getMany(1 + getPipelinedResponseLength()); + connection.getMany(1 + pipelineLength); } @Override diff --git a/src/main/java/redis/clients/jedis/TransactionBase.java b/src/main/java/redis/clients/jedis/TransactionBase.java index d74fa095db..a806dd0f92 100644 --- a/src/main/java/redis/clients/jedis/TransactionBase.java +++ b/src/main/java/redis/clients/jedis/TransactionBase.java @@ -8,16 +8,15 @@ import java.io.Closeable; import java.util.ArrayList; +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 redis.clients.jedis.args.*; -import redis.clients.jedis.bloom.BFInsertParams; -import redis.clients.jedis.bloom.BFReserveParams; -import redis.clients.jedis.bloom.CFInsertParams; -import redis.clients.jedis.bloom.CFReserveParams; +import redis.clients.jedis.bloom.*; import redis.clients.jedis.commands.PipelineBinaryCommands; import redis.clients.jedis.commands.PipelineCommands; import redis.clients.jedis.commands.ProtocolCommand; @@ -29,21 +28,22 @@ 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.IndexOptions; -import redis.clients.jedis.search.Query; -import redis.clients.jedis.search.Schema; -import redis.clients.jedis.search.SearchResult; +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 { +public abstract class TransactionBase implements PipelineCommands, PipelineBinaryCommands, + RedisModulePipelineCommands, Closeable { + private final Queue> pipelinedResponses = new LinkedList<>(); protected final Connection connection; + private final boolean closeConnection; private final CommandObjects commandObjects; private final GraphCommandObjects graphCommandObjects; @@ -51,15 +51,43 @@ public abstract class TransactionBase extends Queable implements PipelineCommand 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. + * @param connection connection + */ public TransactionBase(Connection connection) { this(connection, true); } /** - * If you want to WATCH/UNWATCH keys before MULTI command you should do {@code doMulti = 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, 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 TransactionBase(Connection connection, boolean doMulti, boolean closeConnection) { this.connection = connection; + this.closeConnection = closeConnection; this.commandObjects = new CommandObjects(); this.graphCommandObjects = new GraphCommandObjects(this.connection); if (doMulti) multi(); @@ -99,12 +127,20 @@ public String unwatch() { protected final Response appendCommand(CommandObject commandObject) { connection.sendCommand(commandObject.getArguments()); processAppendStatus(); - return enqueResponse(commandObject.getBuilder()); + Response response = new Response<>(commandObject.getBuilder()); + pipelinedResponses.add(response); + return response; } @Override public final void close() { - clear(); + try { + clear(); + } finally { + if (closeConnection) { + connection.close(); + } + } } public final void clear() { @@ -118,7 +154,7 @@ public final void clear() { } } - protected abstract void processPipelinedResponses(); + protected abstract void processPipelinedResponses(int pipelineLength); public List exec() { if (!inMulti) { @@ -126,19 +162,21 @@ public List exec() { } try { - processPipelinedResponses(); + processPipelinedResponses(pipelinedResponses.size()); connection.sendCommand(EXEC); List unformatted = connection.getObjectMultiBulkReply(); if (unformatted == null) { - clean(); + pipelinedResponses.clear(); return null; } List formatted = new ArrayList<>(unformatted.size()); for (Object o : unformatted) { try { - formatted.add(generateResponse(o).get()); + Response response = pipelinedResponses.poll(); + response.set(o); + formatted.add(response.get()); } catch (JedisDataException e) { formatted.add(e); } @@ -150,7 +188,7 @@ public List exec() { } finally { inMulti = false; inWatch = false; - clean(); + pipelinedResponses.clear(); } } @@ -160,7 +198,7 @@ public String discard() { } try { - processPipelinedResponses(); + processPipelinedResponses(pipelinedResponses.size()); connection.sendCommand(DISCARD); return connection.getStatusCodeReply(); } catch (JedisConnectionException jce) { @@ -169,7 +207,7 @@ public String discard() { } finally { inMulti = false; inWatch = false; - clean(); + pipelinedResponses.clear(); } } @@ -408,6 +446,11 @@ 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)); @@ -553,11 +596,6 @@ 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)); @@ -670,7 +708,7 @@ public Response> blpop(int timeout, String key) { } @Override - public Response blpop(double timeout, String key) { + public Response> blpop(double timeout, String key) { return appendCommand(commandObjects.blpop(timeout, key)); } @@ -680,7 +718,7 @@ public Response> brpop(int timeout, String key) { } @Override - public Response brpop(double timeout, String key) { + public Response> brpop(double timeout, String key) { return appendCommand(commandObjects.brpop(timeout, key)); } @@ -690,7 +728,7 @@ public Response> blpop(int timeout, String... keys) { } @Override - public Response blpop(double timeout, String... keys) { + public Response> blpop(double timeout, String... keys) { return appendCommand(commandObjects.blpop(timeout, keys)); } @@ -700,7 +738,7 @@ public Response> brpop(int timeout, String... keys) { } @Override - public Response brpop(double timeout, String... keys) { + public Response> brpop(double timeout, String... keys) { return appendCommand(commandObjects.brpop(timeout, keys)); } @@ -735,12 +773,12 @@ public Response>> lmpop(ListDirection direction, i } @Override - public Response>> blmpop(long timeout, ListDirection direction, String... keys) { + public Response>> blmpop(double timeout, ListDirection direction, String... keys) { return appendCommand(commandObjects.blmpop(timeout, direction, keys)); } @Override - public Response>> blmpop(long timeout, ListDirection direction, int count, String... keys) { + public Response>> blmpop(double timeout, ListDirection direction, int count, String... keys) { return appendCommand(commandObjects.blmpop(timeout, direction, count, keys)); } @@ -825,7 +863,7 @@ public Response> hrandfield(String key, long count) { } @Override - public Response> hrandfieldWithValues(String key, long count) { + public Response>> hrandfieldWithValues(String key, long count) { return appendCommand(commandObjects.hrandfieldWithValues(key, count)); } @@ -900,7 +938,7 @@ public Response> sdiff(String... keys) { } @Override - public Response sdiffstore(String dstKey, String... keys) { + public Response sdiffStore(String dstKey, String... keys) { return appendCommand(commandObjects.sdiffstore(dstKey, keys)); } @@ -989,6 +1027,16 @@ 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)); @@ -1216,12 +1264,12 @@ public Response> zscan(String key, String cursor, ScanParams p } @Override - public Response bzpopmax(double timeout, String... keys) { + public Response> bzpopmax(double timeout, String... keys) { return appendCommand(commandObjects.bzpopmax(timeout, keys)); } @Override - public Response bzpopmin(double timeout, String... keys) { + public Response> bzpopmin(double timeout, String... keys) { return appendCommand(commandObjects.bzpopmin(timeout, keys)); } @@ -1236,30 +1284,36 @@ public Response>> zmpop(SortedSetOption option, int } @Override - public Response>> bzmpop(long timeout, SortedSetOption option, String... keys) { + public Response>> bzmpop(double timeout, SortedSetOption option, String... keys) { return appendCommand(commandObjects.bzmpop(timeout, option, keys)); } @Override - public Response>> bzmpop(long timeout, SortedSetOption option, int count, String... keys) { + 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) { + public Response> zdiff(String... keys) { return appendCommand(commandObjects.zdiff(keys)); } @Override - public Response> zdiffWithScores(String... keys) { + 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)); @@ -1271,12 +1325,12 @@ public Response zinterstore(String dstKey, ZParams params, String... sets) } @Override - public Response> zinter(ZParams params, String... keys) { + public Response> zinter(ZParams params, String... keys) { return appendCommand(commandObjects.zinter(params, keys)); } @Override - public Response> zinterWithScores(ZParams params, String... keys) { + public Response> zinterWithScores(ZParams params, String... keys) { return appendCommand(commandObjects.zinterWithScores(params, keys)); } @@ -1291,12 +1345,12 @@ public Response zintercard(long limit, String... keys) { } @Override - public Response> zunion(ZParams params, String... keys) { + public Response> zunion(ZParams params, String... keys) { return appendCommand(commandObjects.zunion(params, keys)); } @Override - public Response> zunionWithScores(ZParams params, String... keys) { + public Response> zunionWithScores(ZParams params, String... keys) { return appendCommand(commandObjects.zunionWithScores(params, keys)); } @@ -1560,11 +1614,6 @@ 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)); @@ -1620,12 +1669,6 @@ 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)); @@ -1636,6 +1679,11 @@ public Response> xinfoConsumers(String key, String gro 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)); @@ -1692,6 +1740,11 @@ 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)); @@ -1861,10 +1914,6 @@ 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)); @@ -2086,7 +2135,7 @@ public Response> hrandfield(byte[] key, long count) { } @Override - public Response> hrandfieldWithValues(byte[] key, long count) { + public Response>> hrandfieldWithValues(byte[] key, long count) { return appendCommand(commandObjects.hrandfieldWithValues(key, count)); } @@ -2446,7 +2495,7 @@ public Response> blpop(int timeout, byte[]... keys) { } @Override - public Response> blpop(double timeout, byte[]... keys) { + public Response> blpop(double timeout, byte[]... keys) { return appendCommand(commandObjects.blpop(timeout, keys)); } @@ -2456,7 +2505,7 @@ public Response> brpop(int timeout, byte[]... keys) { } @Override - public Response> brpop(double timeout, byte[]... keys) { + public Response> brpop(double timeout, byte[]... keys) { return appendCommand(commandObjects.brpop(timeout, keys)); } @@ -2491,12 +2540,12 @@ public Response>> lmpop(ListDirection direction, i } @Override - public Response>> blmpop(long timeout, ListDirection direction, byte[]... keys) { + public Response>> blmpop(double timeout, ListDirection direction, byte[]... keys) { return appendCommand(commandObjects.blmpop(timeout, direction, keys)); } @Override - public Response>> blmpop(long timeout, ListDirection direction, int count, byte[]... keys) { + public Response>> blmpop(double timeout, ListDirection direction, int count, byte[]... keys) { return appendCommand(commandObjects.blmpop(timeout, direction, count, keys)); } @@ -2504,15 +2553,16 @@ 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> 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)); @@ -2738,6 +2788,16 @@ 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)); @@ -2964,12 +3024,12 @@ public Response> zscan(byte[] key, byte[] cursor, ScanParams p } @Override - public Response> bzpopmax(double timeout, byte[]... keys) { + public Response> bzpopmax(double timeout, byte[]... keys) { return appendCommand(commandObjects.bzpopmax(timeout, keys)); } @Override - public Response> bzpopmin(double timeout, byte[]... keys) { + public Response> bzpopmin(double timeout, byte[]... keys) { return appendCommand(commandObjects.bzpopmin(timeout, keys)); } @@ -2984,37 +3044,43 @@ public Response>> zmpop(SortedSetOption option, int } @Override - public Response>> bzmpop(long timeout, SortedSetOption option, byte[]... keys) { + public Response>> bzmpop(double timeout, SortedSetOption option, byte[]... keys) { return appendCommand(commandObjects.bzmpop(timeout, option, keys)); } @Override - public Response>> bzmpop(long timeout, SortedSetOption option, int count, byte[]... keys) { + 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) { + public Response> zdiff(byte[]... keys) { return appendCommand(commandObjects.zdiff(keys)); } @Override - public Response> zdiffWithScores(byte[]... keys) { + 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> zinter(ZParams params, byte[]... keys) { + 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) { + public Response> zinterWithScores(ZParams params, byte[]... keys) { return appendCommand(commandObjects.zinterWithScores(params, keys)); } @@ -3039,12 +3105,12 @@ public Response zintercard(long limit, byte[]... keys) { } @Override - public Response> zunion(ZParams params, byte[]... keys) { + public Response> zunion(ZParams params, byte[]... keys) { return appendCommand(commandObjects.zunion(params, keys)); } @Override - public Response> zunionWithScores(ZParams params, byte[]... keys) { + public Response> zunionWithScores(ZParams params, byte[]... keys) { return appendCommand(commandObjects.zunionWithScores(params, keys)); } @@ -3069,22 +3135,22 @@ public Response xlen(byte[] key) { } @Override - public Response> xrange(byte[] key, byte[] start, byte[] end) { + 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) { + 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) { + 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) { + public Response> xrevrange(byte[] key, byte[] end, byte[] start, int count) { return appendCommand(commandObjects.xrevrange(key, end, start, count)); } @@ -3138,11 +3204,6 @@ 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)); @@ -3183,12 +3244,6 @@ 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)); @@ -3200,12 +3255,12 @@ public Response> xinfoConsumers(byte[] key, byte[] group) { } @Override - public Response> xread(XReadParams xReadParams, Map.Entry... streams) { + 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) { + public Response> xreadGroup(byte[] groupName, byte[] consumer, XReadGroupParams xReadGroupParams, Map.Entry... streams) { return appendCommand(commandObjects.xreadGroup(groupName, consumer, xReadGroupParams, streams)); } @@ -3224,6 +3279,11 @@ 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)); @@ -3369,28 +3429,69 @@ 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 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)); } @@ -3411,62 +3512,72 @@ public Response ftAggregate(String indexName, AggregationBuil } @Override - public Response ftCursorRead(String indexName, long cursorId, int count) { - return appendCommand(commandObjects.ftCursorRead(indexName, cursorId, count)); + public Response ftSynUpdate(String indexName, String synonymGroupId, String... terms) { + return appendCommand(commandObjects.ftSynUpdate(indexName, synonymGroupId, terms)); } @Override - public Response ftCursorDel(String indexName, long cursorId) { - return appendCommand(commandObjects.ftCursorDel(indexName, cursorId)); + public Response>> ftSynDump(String indexName) { + return appendCommand(commandObjects.ftSynDump(indexName)); } @Override - public Response ftDropIndex(String indexName) { - return appendCommand(commandObjects.ftDropIndex(indexName)); + public Response ftDictAdd(String dictionary, String... terms) { + return appendCommand(commandObjects.ftDictAdd(dictionary, terms)); } @Override - public Response ftDropIndexDD(String indexName) { - return appendCommand(commandObjects.ftDropIndexDD(indexName)); + public Response ftDictDel(String dictionary, String... terms) { + return appendCommand(commandObjects.ftDictDel(dictionary, terms)); } @Override - public Response ftSynUpdate(String indexName, String synonymGroupId, String... terms) { - return appendCommand(commandObjects.ftSynUpdate(indexName, synonymGroupId, terms)); + public Response> ftDictDump(String dictionary) { + return appendCommand(commandObjects.ftDictDump(dictionary)); } @Override - public Response>> ftSynDump(String indexName) { - return appendCommand(commandObjects.ftSynDump(indexName)); + public Response ftDictAddBySampleKey(String indexName, String dictionary, String... terms) { + return appendCommand(commandObjects.ftDictAddBySampleKey(indexName, dictionary, terms)); } @Override - public Response> ftInfo(String indexName) { - return appendCommand(commandObjects.ftInfo(indexName)); + public Response ftDictDelBySampleKey(String indexName, String dictionary, String... terms) { + return appendCommand(commandObjects.ftDictDelBySampleKey(indexName, dictionary, terms)); } @Override - public Response ftAliasAdd(String aliasName, String indexName) { - return appendCommand(commandObjects.ftAliasAdd(aliasName, indexName)); + public Response> ftDictDumpBySampleKey(String indexName, String dictionary) { + return appendCommand(commandObjects.ftDictDumpBySampleKey(indexName, dictionary)); } @Override - public Response ftAliasUpdate(String aliasName, String indexName) { - return appendCommand(commandObjects.ftAliasUpdate(aliasName, indexName)); + public Response>> ftSpellCheck(String index, String query) { + return appendCommand(commandObjects.ftSpellCheck(index, query)); } @Override - public Response ftAliasDel(String aliasName) { - return appendCommand(commandObjects.ftAliasDel(aliasName)); + 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> ftConfigGet(String option) { + 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) { + public Response> ftConfigGet(String indexName, String option) { return appendCommand(commandObjects.ftConfigGet(indexName, option)); } @@ -3479,6 +3590,46 @@ public Response ftConfigSet(String option, String value) { 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 @@ -3518,6 +3669,16 @@ public Response jsonSet(String key, Path path, Object object, JsonSetPar 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)); @@ -3638,6 +3799,16 @@ 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)); @@ -3831,22 +4002,22 @@ public Response> tsRevRange(String key, TSRangeParams rangeParam } @Override - public Response> tsMRange(long fromTimestamp, long toTimestamp, String... filters) { + public Response> tsMRange(long fromTimestamp, long toTimestamp, String... filters) { return appendCommand(commandObjects.tsMRange(fromTimestamp, toTimestamp, filters)); } @Override - public Response> tsMRange(TSMRangeParams multiRangeParams) { + public Response> tsMRange(TSMRangeParams multiRangeParams) { return appendCommand(commandObjects.tsMRange(multiRangeParams)); } @Override - public Response> tsMRevRange(long fromTimestamp, long toTimestamp, String... filters) { + public Response> tsMRevRange(long fromTimestamp, long toTimestamp, String... filters) { return appendCommand(commandObjects.tsMRevRange(fromTimestamp, toTimestamp, filters)); } @Override - public Response> tsMRevRange(TSMRangeParams multiRangeParams) { + public Response> tsMRevRange(TSMRangeParams multiRangeParams) { return appendCommand(commandObjects.tsMRevRange(multiRangeParams)); } @@ -3856,7 +4027,12 @@ public Response tsGet(String key) { } @Override - public Response>> tsMGet(TSMGetParams multiGetParams, String... filters) { + 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)); } @@ -3865,6 +4041,11 @@ public Response tsCreateRule(String sourceKey, String destKey, Aggregati 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)); @@ -3917,6 +4098,21 @@ 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)); @@ -3977,6 +4173,16 @@ 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)); @@ -4043,19 +4249,99 @@ public Response> topkQuery(String key, String... items) { } @Override - public Response> topkCount(String key, String... items) { - return appendCommand(commandObjects.topkCount(key, items)); + public Response> topkList(String key) { + return appendCommand(commandObjects.topkList(key)); } @Override - public Response> topkList(String key) { - return appendCommand(commandObjects.topkList(key)); + 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 @@ -4103,6 +4389,11 @@ public Response graphReadonlyQuery(String name, String query, Map 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) { @@ -4124,4 +4415,8 @@ public Response sendCommand(CommandArguments args) { 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/UnifiedJedis.java b/src/main/java/redis/clients/jedis/UnifiedJedis.java index 26998f6097..2184534ca6 100644 --- a/src/main/java/redis/clients/jedis/UnifiedJedis.java +++ b/src/main/java/redis/clients/jedis/UnifiedJedis.java @@ -10,31 +10,32 @@ import org.json.JSONArray; import redis.clients.jedis.args.*; -import redis.clients.jedis.bloom.BFInsertParams; -import redis.clients.jedis.bloom.BFReserveParams; -import redis.clients.jedis.bloom.CFInsertParams; -import redis.clients.jedis.bloom.CFReserveParams; +import redis.clients.jedis.bloom.*; import redis.clients.jedis.commands.JedisCommands; import redis.clients.jedis.commands.JedisBinaryCommands; import redis.clients.jedis.commands.ProtocolCommand; 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.params.*; import redis.clients.jedis.providers.*; import redis.clients.jedis.resps.*; -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.*; 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; import redis.clients.jedis.util.JedisURIHelper; @@ -44,10 +45,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)); @@ -65,7 +68,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) { @@ -75,6 +79,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()); @@ -83,60 +88,149 @@ 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 + } } + /** + * 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) { 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}. + *

+ * WARNING: Using this constructor means a {@link NullPointerException} will be occurred if + * {@link UnifiedJedis#provider} is accessed. + */ 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)); + } + + /** + * The constructor to use a custom {@link CommandExecutor}. + *

+ * WARNING: Using this constructor means a {@link NullPointerException} will be occurred if + * {@link UnifiedJedis#provider} is accessed. + */ + 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 @@ -144,10 +238,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) { @@ -523,6 +659,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)); @@ -570,6 +725,16 @@ 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)); + } + @Override public String getDel(String key) { return executeCommand(commandObjects.getDel(key)); @@ -595,6 +760,16 @@ 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)); + } + @Override public byte[] getDel(byte[] key) { return executeCommand(commandObjects.getDel(key)); @@ -875,16 +1050,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)); @@ -1083,7 +1248,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)); } @@ -1093,7 +1258,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)); } @@ -1103,7 +1268,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)); } @@ -1113,7 +1278,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)); } @@ -1123,7 +1288,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)); } @@ -1133,7 +1298,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)); } @@ -1188,12 +1353,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)); } @@ -1208,12 +1373,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 @@ -1370,7 +1535,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)); } @@ -1395,7 +1560,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)); } @@ -1688,6 +1853,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)); @@ -1713,6 +1888,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)); @@ -2164,55 +2349,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)); @@ -2224,12 +2421,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)); } @@ -2264,22 +2461,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)); } @@ -2294,12 +2491,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)); } @@ -2324,12 +2521,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)); } @@ -2344,12 +2541,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 @@ -2769,11 +2966,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)); @@ -2829,12 +3021,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)); @@ -2845,6 +3031,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)); @@ -2867,22 +3058,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)); } @@ -2936,11 +3127,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)); @@ -2981,12 +3167,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)); @@ -2998,12 +3178,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 @@ -3101,22 +3281,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 @@ -3141,12 +3321,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 @@ -3166,7 +3346,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 @@ -3196,22 +3376,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 @@ -3293,6 +3473,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)); @@ -3313,6 +3503,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); @@ -3333,11 +3527,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)); @@ -3348,6 +3550,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)); @@ -3372,6 +3578,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 @@ -3406,25 +3616,74 @@ public void psubscribe(BinaryJedisPubSub jedisPubSub, final byte[]... patterns) jedisPubSub.proceedWithPatterns(connection, patterns); } } - - public LCSMatchResult strAlgoLCSStrings(final String strA, final String strB, final StrAlgoLCSParams params) { - return executeCommand(commandObjects.strAlgoLCSStrings(strA, strB, params)); - } - - public LCSMatchResult strAlgoLCSStrings(byte[] strA, byte[] strB, StrAlgoLCSParams params) { - return executeCommand(commandObjects.strAlgoLCSStrings(strA, strB, params)); - } // 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 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 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 + public SearchResult ftSearch(String indexName, String query) { + return executeCommand(commandObjects.ftSearch(indexName, query)); + } + + @Override + public SearchResult ftSearch(String indexName, String query, FTSearchParams params) { + 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 @@ -3432,7 +3691,19 @@ 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)); } @@ -3462,14 +3733,32 @@ 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 String ftDropIndex(String indexName) { - return executeCommand(commandObjects.ftDropIndex(indexName)); + public Map.Entry> ftProfileAggregate(String indexName, + FTProfileParams profileParams, AggregationBuilder aggr) { + return executeCommand(commandObjects.ftProfileAggregate(indexName, profileParams, aggr)); } @Override - public String ftDropIndexDD(String indexName) { - return executeCommand(commandObjects.ftDropIndexDD(indexName)); + public Map.Entry> ftProfileSearch(String indexName, + FTProfileParams profileParams, Query query) { + return executeCommand(commandObjects.ftProfileSearch(indexName, profileParams, query)); + } + + @Override + public Map.Entry> ftProfileSearch(String indexName, + FTProfileParams profileParams, String query, FTSearchParams searchParams) { + return executeCommand(commandObjects.ftProfileSearch(indexName, profileParams, query, searchParams)); } @Override @@ -3483,32 +3772,62 @@ public Map> ftSynDump(String indexName) { } @Override - public Map ftInfo(String indexName) { - return executeCommand(commandObjects.ftInfo(indexName)); + public long ftDictAdd(String dictionary, String... terms) { + return executeCommand(commandObjects.ftDictAdd(dictionary, terms)); } @Override - public String ftAliasAdd(String aliasName, String indexName) { - return executeCommand(commandObjects.ftAliasAdd(aliasName, indexName)); + public long ftDictDel(String dictionary, String... terms) { + return executeCommand(commandObjects.ftDictDel(dictionary, terms)); } @Override - public String ftAliasUpdate(String aliasName, String indexName) { - return executeCommand(commandObjects.ftAliasUpdate(aliasName, indexName)); + public Set ftDictDump(String dictionary) { + return executeCommand(commandObjects.ftDictDump(dictionary)); } @Override - public String ftAliasDel(String aliasName) { - return executeCommand(commandObjects.ftAliasDel(aliasName)); + public long ftDictAddBySampleKey(String indexName, String dictionary, String... terms) { + return executeCommand(commandObjects.ftDictAddBySampleKey(indexName, dictionary, terms)); + } + + @Override + public long ftDictDelBySampleKey(String indexName, String dictionary, String... terms) { + return executeCommand(commandObjects.ftDictDelBySampleKey(indexName, dictionary, terms)); + } + + @Override + public Set ftDictDumpBySampleKey(String indexName, String dictionary) { + return executeCommand(commandObjects.ftDictDumpBySampleKey(indexName, dictionary)); + } + + @Override + public Map> ftSpellCheck(String index, String query) { + return executeCommand(commandObjects.ftSpellCheck(index, query)); + } + + @Override + public Map> ftSpellCheck(String index, String query, FTSpellCheckParams spellCheckParams) { + return executeCommand(commandObjects.ftSpellCheck(index, query, spellCheckParams)); + } + + @Override + public Map ftInfo(String indexName) { + return executeCommand(commandObjects.ftInfo(indexName)); + } + + @Override + public Set ftTagVals(String indexName, String fieldName) { + return executeCommand(commandObjects.ftTagVals(indexName, fieldName)); } @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)); } @@ -3521,6 +3840,51 @@ public String ftConfigSet(String option, String value) { public String ftConfigSet(String indexName, String option, String value) { return executeCommand(commandObjects.ftConfigSet(indexName, option, value)); } + + @Override + public long ftSugAdd(String key, String string, double score) { + return executeCommand(commandObjects.ftSugAdd(key, string, score)); + } + + @Override + public long ftSugAddIncr(String key, String string, double score) { + return executeCommand(commandObjects.ftSugAddIncr(key, string, score)); + } + + @Override + public List ftSugGet(String key, String prefix) { + return executeCommand(commandObjects.ftSugGet(key, prefix)); + } + + @Override + public List ftSugGet(String key, String prefix, boolean fuzzy, int max) { + return executeCommand(commandObjects.ftSugGet(key, prefix, fuzzy, max)); + } + + @Override + public List ftSugGetWithScores(String key, String prefix) { + return executeCommand(commandObjects.ftSugGetWithScores(key, prefix)); + } + + @Override + public List ftSugGetWithScores(String key, String prefix, boolean fuzzy, int max) { + return executeCommand(commandObjects.ftSugGetWithScores(key, prefix, fuzzy, max)); + } + + @Override + public boolean ftSugDel(String key, String string) { + return executeCommand(commandObjects.ftSugDel(key, string)); + } + + @Override + public long ftSugLen(String key) { + return executeCommand(commandObjects.ftSugLen(key)); + } + + @Override + public Set ftList() { + return executeCommand(commandObjects.ftList()); + } // RediSearch commands // RedisJSON commands @@ -3535,11 +3899,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)); } @@ -3555,16 +3921,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)); } @@ -3575,16 +3954,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)); } @@ -3595,6 +3977,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)); } @@ -3610,6 +3993,7 @@ public long jsonDel(String key, Path2 path) { } @Override + @Deprecated public long jsonDel(String key, Path path) { return executeCommand(commandObjects.jsonDel(key, path)); } @@ -3625,6 +4009,7 @@ public long jsonClear(String key, Path2 path) { } @Override + @Deprecated public long jsonClear(String key, Path path) { return executeCommand(commandObjects.jsonClear(key, path)); } @@ -3635,11 +4020,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)); } @@ -3650,11 +4037,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)); } @@ -3665,11 +4054,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)); } @@ -3680,16 +4071,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)); } @@ -3705,6 +4098,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)); } @@ -3720,6 +4114,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)); } @@ -3735,16 +4130,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)); } @@ -3755,11 +4153,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)); } @@ -3770,16 +4170,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)); } @@ -3790,6 +4193,7 @@ public List jsonArrLen(String key, Path2 path) { } @Override + @Deprecated public Long jsonArrLen(String key, Path path) { return executeCommand(commandObjects.jsonArrLen(key, path)); } @@ -3800,22 +4204,59 @@ 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)); + } + + @Override + public List jsonObjLen(String key, Path2 path) { + return executeCommand(commandObjects.jsonObjLen(key, 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)); + } + + @Override + public List> jsonObjKeys(String key, Path2 path) { + return executeCommand(commandObjects.jsonObjKeys(key, path)); + } + + @Override + @Deprecated public long jsonDebugMemory(String key) { return executeCommand(commandObjects.jsonDebugMemory(key)); } @Override - public List jsonDebugMemory(String key, Path2 path) { + @Deprecated + public long jsonDebugMemory(String key, Path path) { return executeCommand(commandObjects.jsonDebugMemory(key, path)); } @Override - public long jsonDebugMemory(String key, Path path) { + public List jsonDebugMemory(String key, Path2 path) { return executeCommand(commandObjects.jsonDebugMemory(key, path)); } // RedisJSON commands @@ -3902,22 +4343,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)); } @@ -3927,7 +4368,12 @@ public TSElement tsGet(String key) { } @Override - public List> tsMGet(TSMGetParams multiGetParams, String... filters) { + public TSElement tsGet(String key, TSGetParams getParams) { + return executeCommand(commandObjects.tsGet(key, getParams)); + } + + @Override + public Map tsMGet(TSMGetParams multiGetParams, String... filters) { return executeCommand(commandObjects.tsMGet(multiGetParams, filters)); } @@ -3936,6 +4382,11 @@ public String tsCreateRule(String sourceKey, String destKey, AggregationType agg return executeCommand(commandObjects.tsCreateRule(sourceKey, destKey, aggregationType, timeBucket)); } + @Override + public String tsCreateRule(String sourceKey, String destKey, AggregationType aggregationType, long bucketDuration, long alignTimestamp) { + return executeCommand(commandObjects.tsCreateRule(sourceKey, destKey, aggregationType, bucketDuration, alignTimestamp)); + } + @Override public String tsDeleteRule(String sourceKey, String destKey) { return executeCommand(commandObjects.tsDeleteRule(sourceKey, destKey)); @@ -3945,6 +4396,16 @@ public String tsDeleteRule(String sourceKey, String destKey) { public List tsQueryIndex(String... filters) { return executeCommand(commandObjects.tsQueryIndex(filters)); } + + @Override + public TSInfo tsInfo(String key) { + return executor.executeCommand(commandObjects.tsInfo(key)); + } + + @Override + public TSInfo tsInfoDebug(String key) { + return executeCommand(commandObjects.tsInfoDebug(key)); + } // RedisTimeSeries commands // RedisBloom commands @@ -3988,6 +4449,21 @@ public List bfMExists(String key, String... items) { return executeCommand(commandObjects.bfMExists(key, items)); } + @Override + public Map.Entry bfScanDump(String key, long iterator) { + return executeCommand(commandObjects.bfScanDump(key, iterator)); + } + + @Override + public String bfLoadChunk(String key, long iterator, byte[] data) { + return executeCommand(commandObjects.bfLoadChunk(key, iterator, data)); + } + + @Override + public long bfCard(String key) { + return executeCommand(commandObjects.bfCard(key)); + } + @Override public Map bfInfo(String key) { return executeCommand(commandObjects.bfInfo(key)); @@ -4053,6 +4529,16 @@ public long cfCount(String key, String item) { return executeCommand(commandObjects.cfCount(key, item)); } + @Override + public Map.Entry cfScanDump(String key, long iterator) { + return executeCommand(commandObjects.cfScanDump(key, iterator)); + } + + @Override + public String cfLoadChunk(String key, long iterator, byte[] data) { + return executeCommand(commandObjects.cfLoadChunk(key, iterator, data)); + } + @Override public Map cfInfo(String key) { return executeCommand(commandObjects.cfInfo(key)); @@ -4119,68 +4605,234 @@ public List topkQuery(String key, String... items) { } @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 public Map topkInfo(String key) { return executeCommand(commandObjects.topkInfo(key)); } + + @Override + public String tdigestCreate(String key) { + return executeCommand(commandObjects.tdigestCreate(key)); + } + + @Override + public String tdigestCreate(String key, int compression) { + return executeCommand(commandObjects.tdigestCreate(key, compression)); + } + + @Override + public String tdigestReset(String key) { + return executeCommand(commandObjects.tdigestReset(key)); + } + + @Override + public String tdigestMerge(String destinationKey, String... sourceKeys) { + return executeCommand(commandObjects.tdigestMerge(destinationKey, sourceKeys)); + } + + @Override + public String tdigestMerge(TDigestMergeParams mergeParams, String destinationKey, String... sourceKeys) { + return executeCommand(commandObjects.tdigestMerge(mergeParams, destinationKey, sourceKeys)); + } + + @Override + public Map tdigestInfo(String key) { + return executeCommand(commandObjects.tdigestInfo(key)); + } + + @Override + public String tdigestAdd(String key, double... values) { + return executeCommand(commandObjects.tdigestAdd(key, values)); + } + + @Override + public List tdigestCDF(String key, double... values) { + return executeCommand(commandObjects.tdigestCDF(key, values)); + } + + @Override + public List tdigestQuantile(String key, double... quantiles) { + return executeCommand(commandObjects.tdigestQuantile(key, quantiles)); + } + + @Override + public double tdigestMin(String key) { + return executeCommand(commandObjects.tdigestMin(key)); + } + + @Override + public double tdigestMax(String key) { + return executeCommand(commandObjects.tdigestMax(key)); + } + + @Override + public double tdigestTrimmedMean(String key, double lowCutQuantile, double highCutQuantile) { + return executeCommand(commandObjects.tdigestTrimmedMean(key, lowCutQuantile, highCutQuantile)); + } + + @Override + public List tdigestRank(String key, double... values) { + return executeCommand(commandObjects.tdigestRank(key, values)); + } + + @Override + public List tdigestRevRank(String key, double... values) { + return executeCommand(commandObjects.tdigestRevRank(key, values)); + } + + @Override + public List tdigestByRank(String key, long... ranks) { + return executeCommand(commandObjects.tdigestByRank(key, ranks)); + } + + @Override + public List tdigestByRevRank(String key, long... ranks) { + return executeCommand(commandObjects.tdigestByRevRank(key, ranks)); + } // RedisBloom commands // 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 + @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 + // 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)); + } + + @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 + + public PipelineBase pipelined() { + if (provider == null) { + throw new IllegalStateException("It is not allowed to create Pipeline from this " + getClass()); + } + return new Pipeline(provider.getConnection(), true); + } + + public Transaction multi() { + if (provider == null) { + throw new IllegalStateException("It is not allowed to create Pipeline from this " + getClass()); + } + return new Transaction(provider.getConnection(), true, true); + } + public Object sendCommand(ProtocolCommand cmd) { return executeCommand(commandObjects.commandArguments(cmd)); } @@ -4220,4 +4872,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/BitCountOption.java b/src/main/java/redis/clients/jedis/args/BitCountOption.java index 0e16f9d50c..795dadb738 100644 --- a/src/main/java/redis/clients/jedis/args/BitCountOption.java +++ b/src/main/java/redis/clients/jedis/args/BitCountOption.java @@ -2,6 +2,9 @@ import redis.clients.jedis.util.SafeEncoder; +/** + * The options for {@code BITCOUNT} command. + */ public enum BitCountOption implements Rawable { BYTE, BIT; diff --git a/src/main/java/redis/clients/jedis/args/BitOP.java b/src/main/java/redis/clients/jedis/args/BitOP.java index 81ba6302ff..2ca6c198fc 100644 --- a/src/main/java/redis/clients/jedis/args/BitOP.java +++ b/src/main/java/redis/clients/jedis/args/BitOP.java @@ -2,6 +2,9 @@ import redis.clients.jedis.util.SafeEncoder; +/** + * Bit operations for {@code BITOP} command. + */ public enum BitOP implements Rawable { AND, OR, XOR, NOT; 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/ClientPauseMode.java b/src/main/java/redis/clients/jedis/args/ClientPauseMode.java index 28fd190807..db3a4e0032 100644 --- a/src/main/java/redis/clients/jedis/args/ClientPauseMode.java +++ b/src/main/java/redis/clients/jedis/args/ClientPauseMode.java @@ -2,6 +2,9 @@ import redis.clients.jedis.util.SafeEncoder; +/** + * Client pause supported modes. + */ public enum ClientPauseMode implements Rawable { ALL, WRITE; diff --git a/src/main/java/redis/clients/jedis/args/ClusterFailoverOption.java b/src/main/java/redis/clients/jedis/args/ClusterFailoverOption.java index 01cad8f85b..e7838ad2d5 100644 --- a/src/main/java/redis/clients/jedis/args/ClusterFailoverOption.java +++ b/src/main/java/redis/clients/jedis/args/ClusterFailoverOption.java @@ -2,6 +2,11 @@ import redis.clients.jedis.util.SafeEncoder; +/** + * Enumeration of cluster failover options. + *

+ * Used by {@link redis.clients.jedis.commands.ClusterCommands#clusterFailover(ClusterFailoverOption)}. + */ public enum ClusterFailoverOption implements Rawable { FORCE, TAKEOVER; diff --git a/src/main/java/redis/clients/jedis/args/ClusterResetType.java b/src/main/java/redis/clients/jedis/args/ClusterResetType.java index 99cb969980..f00c79e9e2 100644 --- a/src/main/java/redis/clients/jedis/args/ClusterResetType.java +++ b/src/main/java/redis/clients/jedis/args/ClusterResetType.java @@ -2,9 +2,21 @@ import redis.clients.jedis.util.SafeEncoder; +/** + * Reset type for command cluster reset. Before reset cluster status you should make true no data in Redis. + * It is generally used to create/expand clusters. + */ public enum ClusterResetType implements Rawable { - SOFT, HARD; + /** + * Soft reset: Reset only the cluster info. + */ + SOFT, + + /** + * Hard reset: Reset the cluster info, set epochs to 0, change node ID. + */ + HARD; private final byte[] raw; diff --git a/src/main/java/redis/clients/jedis/args/ExpiryOption.java b/src/main/java/redis/clients/jedis/args/ExpiryOption.java index bd23b46b01..5ed3034ba3 100644 --- a/src/main/java/redis/clients/jedis/args/ExpiryOption.java +++ b/src/main/java/redis/clients/jedis/args/ExpiryOption.java @@ -2,9 +2,30 @@ import redis.clients.jedis.util.SafeEncoder; +/** + * Enumeration of setting expiration. + */ public enum ExpiryOption implements Rawable { - NX, XX, GT, LT; + /** + * Set expiry only when the key has no expiry. + */ + NX, + + /** + * Set expiry only when the key has an existing expiry. + */ + XX, + + /** + * Set expiry only when the new expiry is greater than the existing one. + */ + GT, + + /** + * Set expiry only when the new expiry is less than the existing one. + */ + LT; private final byte[] raw; diff --git a/src/main/java/redis/clients/jedis/args/Rawable.java b/src/main/java/redis/clients/jedis/args/Rawable.java index 9aaa702c12..7515386861 100644 --- a/src/main/java/redis/clients/jedis/args/Rawable.java +++ b/src/main/java/redis/clients/jedis/args/Rawable.java @@ -1,6 +1,13 @@ package redis.clients.jedis.args; +/** + * Byte array representation of arguments to write in socket input stream. + */ public interface Rawable { + /** + * Get byte array. + * @return binary + */ byte[] getRaw(); } diff --git a/src/main/java/redis/clients/jedis/args/RawableFactory.java b/src/main/java/redis/clients/jedis/args/RawableFactory.java index 6b4355da8d..90bcc3c297 100644 --- a/src/main/java/redis/clients/jedis/args/RawableFactory.java +++ b/src/main/java/redis/clients/jedis/args/RawableFactory.java @@ -1,32 +1,60 @@ 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. + */ public final class RawableFactory { + /** + * Get a {@link Rawable} from an {@code int}. + * @param i integer value + * @return raw + */ public static Rawable from(int i) { return from(toByteArray(i)); } + /** + * Get a {@link Rawable} from a {@code double}. + * @param d numeric value + * @return raw + */ public static Rawable from(double d) { return from(toByteArray(d)); } + /** + * Get a {@link Rawable} from a byte array. + * @param binary value + * @return raw + */ public static Rawable from(byte[] binary) { return new Raw(binary); } + /** + * Get a {@link Rawable} from a {@link String}. + * @param string value + * @return raw + */ public static Rawable from(String string) { return new RawString(string); } + /** + * Default implementation of {@link Rawable}. + */ 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 @@ -35,10 +63,20 @@ public byte[] getRaw() { } } - public static class RawString extends Raw { + /** + * A {@link Rawable} wrapping a {@link String}. + */ + 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/args/SortingOrder.java b/src/main/java/redis/clients/jedis/args/SortingOrder.java new file mode 100644 index 0000000000..1e82cbd7fe --- /dev/null +++ b/src/main/java/redis/clients/jedis/args/SortingOrder.java @@ -0,0 +1,19 @@ +package redis.clients.jedis.args; + +import redis.clients.jedis.util.SafeEncoder; + +public enum SortingOrder implements Rawable { + + ASC, DESC; + + private final byte[] raw; + + private SortingOrder() { + raw = SafeEncoder.encode(this.name()); + } + + @Override + public byte[] getRaw() { + return raw; + } +} diff --git a/src/main/java/redis/clients/jedis/args/package-info.java b/src/main/java/redis/clients/jedis/args/package-info.java index fb06d1bf43..d69e96fb6d 100644 --- a/src/main/java/redis/clients/jedis/args/package-info.java +++ b/src/main/java/redis/clients/jedis/args/package-info.java @@ -1,4 +1,4 @@ -/* - * This package contains the classes that represent arguments of Redis commands. +/** + * This package contains the classes that represent arguments of Redis core commands. */ package redis.clients.jedis.args; diff --git a/src/main/java/redis/clients/jedis/bloom/BFReserveParams.java b/src/main/java/redis/clients/jedis/bloom/BFReserveParams.java index 391b895088..b403f2e1c5 100644 --- a/src/main/java/redis/clients/jedis/bloom/BFReserveParams.java +++ b/src/main/java/redis/clients/jedis/bloom/BFReserveParams.java @@ -1,10 +1,10 @@ package redis.clients.jedis.bloom; +import static redis.clients.jedis.Protocol.toByteArray; import static redis.clients.jedis.bloom.RedisBloomProtocol.RedisBloomKeyword.EXPANSION; import static redis.clients.jedis.bloom.RedisBloomProtocol.RedisBloomKeyword.NONSCALING; import redis.clients.jedis.CommandArguments; -import redis.clients.jedis.Protocol; import redis.clients.jedis.params.IParams; public class BFReserveParams implements IParams { @@ -29,7 +29,7 @@ public BFReserveParams nonScaling() { @Override public void addParams(CommandArguments args) { if (expansion != null) { - args.add(EXPANSION).add(Protocol.toByteArray(expansion)); + args.add(EXPANSION).add(toByteArray(expansion)); } if (nonScaling) { args.add(NONSCALING); diff --git a/src/main/java/redis/clients/jedis/bloom/RedisBloomCommands.java b/src/main/java/redis/clients/jedis/bloom/RedisBloomCommands.java deleted file mode 100644 index 5c51b7a762..0000000000 --- a/src/main/java/redis/clients/jedis/bloom/RedisBloomCommands.java +++ /dev/null @@ -1,6 +0,0 @@ -package redis.clients.jedis.bloom; - -public interface RedisBloomCommands extends BloomFilterCommands, CuckooFilterCommands, - CountMinSketchCommands, TopKFilterCommands { - -} diff --git a/src/main/java/redis/clients/jedis/bloom/RedisBloomPipelineCommands.java b/src/main/java/redis/clients/jedis/bloom/RedisBloomPipelineCommands.java deleted file mode 100644 index 4895f68765..0000000000 --- a/src/main/java/redis/clients/jedis/bloom/RedisBloomPipelineCommands.java +++ /dev/null @@ -1,9 +0,0 @@ -package redis.clients.jedis.bloom; - -public interface RedisBloomPipelineCommands extends - BloomFilterPipelineCommands, - CuckooFilterPipelineCommands, - CountMinSketchPipelineCommands, - TopKFilterPipelineCommands { - -} diff --git a/src/main/java/redis/clients/jedis/bloom/RedisBloomProtocol.java b/src/main/java/redis/clients/jedis/bloom/RedisBloomProtocol.java index e6c38a003e..c60b9fcc4a 100644 --- a/src/main/java/redis/clients/jedis/bloom/RedisBloomProtocol.java +++ b/src/main/java/redis/clients/jedis/bloom/RedisBloomProtocol.java @@ -14,6 +14,9 @@ public enum BloomFilterCommand implements ProtocolCommand { EXISTS("BF.EXISTS"), MEXISTS("BF.MEXISTS"), INSERT("BF.INSERT"), + SCANDUMP("BF.SCANDUMP"), + LOADCHUNK("BF.LOADCHUNK"), + CARD("BF.CARD"), INFO("BF.INFO"); private final byte[] raw; @@ -82,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"); @@ -98,9 +100,27 @@ public byte[] getRaw() { } } + public enum TDigestCommand implements ProtocolCommand { + + CREATE, INFO, ADD, RESET, MERGE, CDF, QUANTILE, MIN, MAX, TRIMMED_MEAN, + RANK, REVRANK, BYRANK, BYREVRANK; + + private final byte[] raw; + + private TDigestCommand() { + raw = SafeEncoder.encode("TDIGEST." + name()); + } + + @Override + public byte[] getRaw() { + return raw; + } + } + public enum RedisBloomKeyword implements Rawable { - CAPACITY, ERROR, NOCREATE, EXPANSION, NONSCALING, BUCKETSIZE, MAXITERATIONS, ITEMS, WEIGHTS; + CAPACITY, ERROR, NOCREATE, EXPANSION, NONSCALING, BUCKETSIZE, MAXITERATIONS, ITEMS, WEIGHTS, + COMPRESSION, OVERRIDE, WITHCOUNT; private final byte[] raw; diff --git a/src/main/java/redis/clients/jedis/bloom/TDigestMergeParams.java b/src/main/java/redis/clients/jedis/bloom/TDigestMergeParams.java new file mode 100644 index 0000000000..8407f5e635 --- /dev/null +++ b/src/main/java/redis/clients/jedis/bloom/TDigestMergeParams.java @@ -0,0 +1,38 @@ +package redis.clients.jedis.bloom; + +import static redis.clients.jedis.Protocol.toByteArray; +import static redis.clients.jedis.bloom.RedisBloomProtocol.RedisBloomKeyword.COMPRESSION; +import static redis.clients.jedis.bloom.RedisBloomProtocol.RedisBloomKeyword.OVERRIDE; + +import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.params.IParams; + +public class TDigestMergeParams implements IParams { + + private Integer compression; + private boolean override = false; + + public static TDigestMergeParams mergeParams() { + return new TDigestMergeParams(); + } + + public TDigestMergeParams compression(int compression) { + this.compression = compression; + return this; + } + + public TDigestMergeParams override() { + this.override = true; + return this; + } + + @Override + public void addParams(CommandArguments args) { + if (compression != null) { + args.add(COMPRESSION).add(toByteArray(compression)); + } + if (override) { + args.add(OVERRIDE); + } + } +} diff --git a/src/main/java/redis/clients/jedis/bloom/BloomFilterCommands.java b/src/main/java/redis/clients/jedis/bloom/commands/BloomFilterCommands.java similarity index 74% rename from src/main/java/redis/clients/jedis/bloom/BloomFilterCommands.java rename to src/main/java/redis/clients/jedis/bloom/commands/BloomFilterCommands.java index 0d2286daed..468bd0d5dc 100644 --- a/src/main/java/redis/clients/jedis/bloom/BloomFilterCommands.java +++ b/src/main/java/redis/clients/jedis/bloom/commands/BloomFilterCommands.java @@ -1,7 +1,9 @@ -package redis.clients.jedis.bloom; +package redis.clients.jedis.bloom.commands; import java.util.List; import java.util.Map; +import redis.clients.jedis.bloom.BFInsertParams; +import redis.clients.jedis.bloom.BFReserveParams; public interface BloomFilterCommands { @@ -77,8 +79,26 @@ public interface BloomFilterCommands { */ List bfMExists(String key, String... items); - // BF.SCANDUMP {key} {iter} - // BF.LOADCHUNK {key} {iter} {data} + /** + * {@code BF.SCANDUMP {key} {iterator}} + * + * @param key + * @param iterator + * @return Pair of next iterator and current data + */ + Map.Entry bfScanDump(String key, long iterator); + + /** + * {@code BF.LOADCHUNK {key} {iterator} {data}} + * + * @param key + * @param iterator + * @param data + * @return OK + */ + String bfLoadChunk(String key, long iterator, byte[] data); + + long bfCard(String key); Map bfInfo(String key); } diff --git a/src/main/java/redis/clients/jedis/bloom/BloomFilterPipelineCommands.java b/src/main/java/redis/clients/jedis/bloom/commands/BloomFilterPipelineCommands.java similarity index 70% rename from src/main/java/redis/clients/jedis/bloom/BloomFilterPipelineCommands.java rename to src/main/java/redis/clients/jedis/bloom/commands/BloomFilterPipelineCommands.java index 74fd081678..ef593d3d35 100644 --- a/src/main/java/redis/clients/jedis/bloom/BloomFilterPipelineCommands.java +++ b/src/main/java/redis/clients/jedis/bloom/commands/BloomFilterPipelineCommands.java @@ -1,8 +1,10 @@ -package redis.clients.jedis.bloom; +package redis.clients.jedis.bloom.commands; import java.util.List; import java.util.Map; import redis.clients.jedis.Response; +import redis.clients.jedis.bloom.BFInsertParams; +import redis.clients.jedis.bloom.BFReserveParams; public interface BloomFilterPipelineCommands { @@ -22,5 +24,11 @@ public interface BloomFilterPipelineCommands { Response> bfMExists(String key, String... items); + Response> bfScanDump(String key, long iterator); + + Response bfLoadChunk(String key, long iterator, byte[] data); + + Response bfCard(String key); + Response> bfInfo(String key); } diff --git a/src/main/java/redis/clients/jedis/bloom/CountMinSketchCommands.java b/src/main/java/redis/clients/jedis/bloom/commands/CountMinSketchCommands.java similarity index 98% rename from src/main/java/redis/clients/jedis/bloom/CountMinSketchCommands.java rename to src/main/java/redis/clients/jedis/bloom/commands/CountMinSketchCommands.java index 70d42031f3..4684804860 100644 --- a/src/main/java/redis/clients/jedis/bloom/CountMinSketchCommands.java +++ b/src/main/java/redis/clients/jedis/bloom/commands/CountMinSketchCommands.java @@ -1,4 +1,4 @@ -package redis.clients.jedis.bloom; +package redis.clients.jedis.bloom.commands; import java.util.List; import java.util.Map; @@ -35,7 +35,7 @@ public interface CountMinSketchCommands { * of 0.1% (1 in 1000), error_rate should be set to 0.001. * The closer this number is to zero, the greater the memory * consumption per item and the more CPU usage per operation. - * @return + * @return OK */ String cmsInitByProb(String key, double error, double probability); diff --git a/src/main/java/redis/clients/jedis/bloom/CountMinSketchPipelineCommands.java b/src/main/java/redis/clients/jedis/bloom/commands/CountMinSketchPipelineCommands.java similarity index 93% rename from src/main/java/redis/clients/jedis/bloom/CountMinSketchPipelineCommands.java rename to src/main/java/redis/clients/jedis/bloom/commands/CountMinSketchPipelineCommands.java index c6ca2c6c3d..f63d2c3e9d 100644 --- a/src/main/java/redis/clients/jedis/bloom/CountMinSketchPipelineCommands.java +++ b/src/main/java/redis/clients/jedis/bloom/commands/CountMinSketchPipelineCommands.java @@ -1,4 +1,4 @@ -package redis.clients.jedis.bloom; +package redis.clients.jedis.bloom.commands; import java.util.List; import java.util.Map; diff --git a/src/main/java/redis/clients/jedis/bloom/CuckooFilterCommands.java b/src/main/java/redis/clients/jedis/bloom/commands/CuckooFilterCommands.java similarity index 85% rename from src/main/java/redis/clients/jedis/bloom/CuckooFilterCommands.java rename to src/main/java/redis/clients/jedis/bloom/commands/CuckooFilterCommands.java index d44fb85875..d62d707583 100644 --- a/src/main/java/redis/clients/jedis/bloom/CuckooFilterCommands.java +++ b/src/main/java/redis/clients/jedis/bloom/commands/CuckooFilterCommands.java @@ -1,7 +1,9 @@ -package redis.clients.jedis.bloom; +package redis.clients.jedis.bloom.commands; import java.util.List; import java.util.Map; +import redis.clients.jedis.bloom.CFInsertParams; +import redis.clients.jedis.bloom.CFReserveParams; /** * Interface for RedisBloom Cuckoo Filter Commands @@ -137,21 +139,21 @@ public interface CuckooFilterCommands { * @return The number of times the item exists in the filter */ long cfCount(String key, String item); -// -// /** -// * CF.SCANDUMP Begins an incremental save of the cuckoo filter. This is useful -// * for large cuckoo filters which cannot fit into the normal SAVE and RESTORE -// * model. -// * -// * The Iterator is passed as input to the next invocation of SCANDUMP . If -// * Iterator is 0, the iteration has completed. -// * -// * @param key Name of the filter -// * @param iterator This is either 0, or the iterator from a previous invocation -// * of this command -// * @return a Map.Entry containing the Iterator and Data. -// */ -// Map.Entry cfScanDump(String key, long iterator); + + /** + * CF.SCANDUMP Begins an incremental save of the cuckoo filter. This is useful + * for large cuckoo filters which cannot fit into the normal SAVE and RESTORE + * model. + * + * The Iterator is passed as input to the next invocation of SCANDUMP . If + * Iterator is 0, the iteration has completed. + * + * @param key Name of the filter + * @param iterator This is either 0, or the iterator from a previous invocation + * of this command + * @return a Map.Entry containing the Iterator and Data. + */ + Map.Entry cfScanDump(String key, long iterator); // // /** // * CF.SCANDUMP Begins an incremental save of the cuckoo filter. This is useful @@ -177,6 +179,16 @@ public interface CuckooFilterCommands { // * @return A sequential Stream of Pair of iterator and data // */ // Stream> cfScanDumpStream(String key); + + /** + * CF.LOADCHUNK Restores a filter previously saved using SCANDUMP. + * + * @param key Name of the filter to restore + * @param iterator Iterator from CF.SCANDUMP + * @param data Data from CF.SCANDUMP + * @return OK + */ + String cfLoadChunk(String key, long iterator, byte[] data); // // /** // * CF.LOADCHUNK Restores a filter previously saved using SCANDUMP . See the diff --git a/src/main/java/redis/clients/jedis/bloom/CuckooFilterPipelineCommands.java b/src/main/java/redis/clients/jedis/bloom/commands/CuckooFilterPipelineCommands.java similarity index 76% rename from src/main/java/redis/clients/jedis/bloom/CuckooFilterPipelineCommands.java rename to src/main/java/redis/clients/jedis/bloom/commands/CuckooFilterPipelineCommands.java index 516bd01a34..b911d741ea 100644 --- a/src/main/java/redis/clients/jedis/bloom/CuckooFilterPipelineCommands.java +++ b/src/main/java/redis/clients/jedis/bloom/commands/CuckooFilterPipelineCommands.java @@ -1,8 +1,10 @@ -package redis.clients.jedis.bloom; +package redis.clients.jedis.bloom.commands; import java.util.List; import java.util.Map; import redis.clients.jedis.Response; +import redis.clients.jedis.bloom.CFInsertParams; +import redis.clients.jedis.bloom.CFReserveParams; public interface CuckooFilterPipelineCommands { @@ -28,5 +30,9 @@ public interface CuckooFilterPipelineCommands { Response cfCount(String key, String item); + Response> cfScanDump(String key, long iterator); + + Response cfLoadChunk(String key, long iterator, byte[] data); + Response> cfInfo(String key); } diff --git a/src/main/java/redis/clients/jedis/bloom/commands/RedisBloomCommands.java b/src/main/java/redis/clients/jedis/bloom/commands/RedisBloomCommands.java new file mode 100644 index 0000000000..e3577194a9 --- /dev/null +++ b/src/main/java/redis/clients/jedis/bloom/commands/RedisBloomCommands.java @@ -0,0 +1,6 @@ +package redis.clients.jedis.bloom.commands; + +public interface RedisBloomCommands extends BloomFilterCommands, CuckooFilterCommands, + CountMinSketchCommands, TopKFilterCommands, TDigestSketchCommands { + +} diff --git a/src/main/java/redis/clients/jedis/bloom/commands/RedisBloomPipelineCommands.java b/src/main/java/redis/clients/jedis/bloom/commands/RedisBloomPipelineCommands.java new file mode 100644 index 0000000000..91750a85b6 --- /dev/null +++ b/src/main/java/redis/clients/jedis/bloom/commands/RedisBloomPipelineCommands.java @@ -0,0 +1,7 @@ +package redis.clients.jedis.bloom.commands; + +public interface RedisBloomPipelineCommands extends BloomFilterPipelineCommands, + CuckooFilterPipelineCommands, CountMinSketchPipelineCommands, TopKFilterPipelineCommands, + TDigestSketchPipelineCommands { + +} diff --git a/src/main/java/redis/clients/jedis/bloom/commands/TDigestSketchCommands.java b/src/main/java/redis/clients/jedis/bloom/commands/TDigestSketchCommands.java new file mode 100644 index 0000000000..c69c35e380 --- /dev/null +++ b/src/main/java/redis/clients/jedis/bloom/commands/TDigestSketchCommands.java @@ -0,0 +1,122 @@ +package redis.clients.jedis.bloom.commands; + +import java.util.List; +import java.util.Map; +import redis.clients.jedis.bloom.TDigestMergeParams; + +public interface TDigestSketchCommands { + + /** + * {@code TDIGEST.CREATE key} + * + * @param key The name of the sketch (a t-digest data structure) + * @return OK + */ + String tdigestCreate(String key); + + /** + * {@code TDIGEST.CREATE key [compression]} + * + * @param key The name of the sketch (a t-digest data structure) + * @param compression The compression parameter. 100 is a common value for normal uses. 1000 is extremely large. + * @return OK + */ + String tdigestCreate(String key, int compression); + + /** + * {@code TDIGEST.RESET key} + * + * @param key The name of the sketch (a t-digest data structure) + * @return OK + */ + String tdigestReset(String key); + + /** + * {@code TDIGEST.MERGE destination-key numkeys source-key [source-key ...]} + * + * @param destinationKey Sketch to copy observation values to (a t-digest data structure) + * @param sourceKeys Sketch(es) to copy observation values from (a t-digest data structure) + * @return OK + */ + String tdigestMerge(String destinationKey, String... sourceKeys); + + /** + * {@code TDIGEST.MERGE destination-key numkeys source-key [source-key ...] + * [COMPRESSION compression] [OVERRIDE]} + * + * @param mergeParams compression and override options + * @param destinationKey Sketch to copy observation values to (a t-digest data structure) + * @param sourceKeys Sketch(es) to copy observation values from (a t-digest data structure) + * @return OK + */ + String tdigestMerge(TDigestMergeParams mergeParams, String destinationKey, String... sourceKeys); + + /** + * {@code TDIGEST.INFO key} + * + * @param key The name of the sketch (a t-digest data structure) + * @return information about the sketch + */ + Map tdigestInfo(String key); + + /** + * {@code TDIGEST.ADD key value weight [ value weight ...]} + * + * @param key The name of the sketch (a t-digest data structure) + * @param values The value of the observation (floating-point) + * @return OK + */ + String tdigestAdd(String key, double... values); + + /** + * {@code TDIGEST.CDF key value [value ...]} + * + * @param key The name of the sketch (a t-digest data structure) + * @param values upper limit of observation value, for which the fraction of all observations added which are ≤ value + * @return estimation of the fraction of all observations added which are ≤ value + */ + List tdigestCDF(String key, double... values); + + /** + * {@code TDIGEST.QUANTILE key quantile [quantile ...]} + * + * @param key The name of the sketch (a t-digest data structure) + * @param quantiles The desired fraction(s) (between 0 and 1 inclusively) + * @return results + */ + List tdigestQuantile(String key, double... quantiles); + + /** + * {@code TDIGEST.MIN key} + * + * @param key The name of the sketch (a t-digest data structure) + * @return minimum observation value from the sketch + */ + double tdigestMin(String key); + + /** + * {@code TDIGEST.MAX key} + * + * @param key The name of the sketch (a t-digest data structure) + * @return maximum observation value from the sketch + */ + double tdigestMax(String key); + + /** + * {@code TDIGEST.TRIMMED_MEAN key low_cut_quantile high_cut_quantile} + * + * @param key The name of the sketch (a t-digest data structure) + * @param lowCutQuantile Exclude observation values lower than this quantile + * @param highCutQuantile Exclude observation values higher than this quantile + * @return estimation of the mean value + */ + double tdigestTrimmedMean(String key, double lowCutQuantile, double highCutQuantile); + + List tdigestRank(String key, double... values); + + List tdigestRevRank(String key, double... values); + + List tdigestByRank(String key, long... ranks); + + List tdigestByRevRank(String key, long... ranks); +} diff --git a/src/main/java/redis/clients/jedis/bloom/commands/TDigestSketchPipelineCommands.java b/src/main/java/redis/clients/jedis/bloom/commands/TDigestSketchPipelineCommands.java new file mode 100644 index 0000000000..dc675f74e8 --- /dev/null +++ b/src/main/java/redis/clients/jedis/bloom/commands/TDigestSketchPipelineCommands.java @@ -0,0 +1,41 @@ +package redis.clients.jedis.bloom.commands; + +import java.util.List; +import java.util.Map; +import redis.clients.jedis.Response; +import redis.clients.jedis.bloom.TDigestMergeParams; + +public interface TDigestSketchPipelineCommands { + + Response tdigestCreate(String key); + + Response tdigestCreate(String key, int compression); + + Response tdigestReset(String key); + + Response tdigestMerge(String destinationKey, String... sourceKeys); + + Response tdigestMerge(TDigestMergeParams mergeParams, String destinationKey, String... sourceKeys); + + Response> tdigestInfo(String key); + + Response tdigestAdd(String key, double... values); + + Response> tdigestCDF(String key, double... values); + + Response> tdigestQuantile(String key, double... quantiles); + + Response tdigestMin(String key); + + Response tdigestMax(String key); + + Response tdigestTrimmedMean(String key, double lowCutQuantile, double highCutQuantile); + + Response> tdigestRank(String key, double... values); + + Response> tdigestRevRank(String key, double... values); + + Response> tdigestByRank(String key, long... ranks); + + Response> tdigestByRevRank(String key, long... ranks); +} diff --git a/src/main/java/redis/clients/jedis/bloom/TopKFilterCommands.java b/src/main/java/redis/clients/jedis/bloom/commands/TopKFilterCommands.java similarity index 73% rename from src/main/java/redis/clients/jedis/bloom/TopKFilterCommands.java rename to src/main/java/redis/clients/jedis/bloom/commands/TopKFilterCommands.java index 4c6ab15ab2..d16e31a72f 100644 --- a/src/main/java/redis/clients/jedis/bloom/TopKFilterCommands.java +++ b/src/main/java/redis/clients/jedis/bloom/commands/TopKFilterCommands.java @@ -1,5 +1,6 @@ -package redis.clients.jedis.bloom; +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,21 +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 + * @return k (or less) items in Top K list */ - 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/TopKFilterPipelineCommands.java b/src/main/java/redis/clients/jedis/bloom/commands/TopKFilterPipelineCommands.java similarity index 85% rename from src/main/java/redis/clients/jedis/bloom/TopKFilterPipelineCommands.java rename to src/main/java/redis/clients/jedis/bloom/commands/TopKFilterPipelineCommands.java index f37130549f..d75b3d7447 100644 --- a/src/main/java/redis/clients/jedis/bloom/TopKFilterPipelineCommands.java +++ b/src/main/java/redis/clients/jedis/bloom/commands/TopKFilterPipelineCommands.java @@ -1,4 +1,4 @@ -package redis.clients.jedis.bloom; +package redis.clients.jedis.bloom.commands; import java.util.List; import java.util.Map; @@ -16,9 +16,9 @@ public interface TopKFilterPipelineCommands { Response> topkQuery(String key, String... items); - 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/bloom/commands/package-info.java b/src/main/java/redis/clients/jedis/bloom/commands/package-info.java new file mode 100644 index 0000000000..e13c1638e5 --- /dev/null +++ b/src/main/java/redis/clients/jedis/bloom/commands/package-info.java @@ -0,0 +1,4 @@ +/** + * This package contains the interfaces that contain methods representing RedisBloom commands. + */ +package redis.clients.jedis.bloom.commands; diff --git a/src/main/java/redis/clients/jedis/bloom/package-info.java b/src/main/java/redis/clients/jedis/bloom/package-info.java new file mode 100644 index 0000000000..e196f93497 --- /dev/null +++ b/src/main/java/redis/clients/jedis/bloom/package-info.java @@ -0,0 +1,4 @@ +/** + * This package contains the classes related to RedisBloom module. + */ +package redis.clients.jedis.bloom; 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/BitBinaryCommands.java b/src/main/java/redis/clients/jedis/commands/BitBinaryCommands.java new file mode 100644 index 0000000000..e773742bad --- /dev/null +++ b/src/main/java/redis/clients/jedis/commands/BitBinaryCommands.java @@ -0,0 +1,30 @@ +package redis.clients.jedis.commands; + +import java.util.List; + +import redis.clients.jedis.args.BitCountOption; +import redis.clients.jedis.args.BitOP; +import redis.clients.jedis.params.BitPosParams; + +public interface BitBinaryCommands { + + boolean setbit(byte[] key, long offset, boolean value); + + boolean getbit(byte[] key, long offset); + + long bitcount(byte[] key); + + long bitcount(byte[] key, long start, long end); + + long bitcount(byte[] key, long start, long end, BitCountOption option); + + long bitpos(byte[] key, boolean value); + + long bitpos(byte[] key, boolean value, BitPosParams params); + + List bitfield(byte[] key, byte[]... arguments); + + List bitfieldReadonly(byte[] key, byte[]... arguments); + + long bitop(BitOP op, byte[] destKey, byte[]... srcKeys); +} diff --git a/src/main/java/redis/clients/jedis/commands/BitCommands.java b/src/main/java/redis/clients/jedis/commands/BitCommands.java new file mode 100644 index 0000000000..704f29c52f --- /dev/null +++ b/src/main/java/redis/clients/jedis/commands/BitCommands.java @@ -0,0 +1,109 @@ +package redis.clients.jedis.commands; + +import java.util.List; + +import redis.clients.jedis.args.BitCountOption; +import redis.clients.jedis.args.BitOP; +import redis.clients.jedis.params.BitPosParams; + +public interface BitCommands { + + /** + * SetBit Command + * Sets or clears the bit at offset in the string value stored at key. + *

+ * Time complexity: O(1) + * @param key + * @param offset + * @param value + * @return The original bit value stored at offset + */ + boolean setbit(String key, long offset, boolean value); + + /** + * GetBit Command + * Returns the bit value at offset in the string value stored at key. + *

+ * Time complexity: O(1) + * @param key + * @param offset + * @return The bit value stored at offset + */ + boolean getbit(String key, long offset); + + /** + * Bitcount Command + * Count the number of set bits (population counting) in a string. + * @param key + * @return The number of bits set to 1 + */ + long bitcount(String key); + + /** + * Bitcount Command + * Count the number of set bits (population counting) in a string only in an interval start and end. + *

+ * Like for the GETRANGE command start and end can contain negative values in order to index bytes + * starting from the end of the string, where -1 is the last byte, -2 is the penultimate, and so forth. + * @param key + * @param start byte start index + * @param end byte end index + * @return The number of bits set to 1 + */ + long bitcount(String key, long start, long end); + + /** + * @see StringCommands#bitcount(String, long, long) + * @param key + * @param start byte start index + * @param end byte end index + * @param option indicate BYTE or BIT + * @return The number of bits set to 1 + */ + long bitcount(String key, long start, long end, BitCountOption option); + + /** + * Bitpos Command + * Return the position of the first bit set to 1 or 0 in a string. + * @param key + * @param value the bit value + * @return The position of the first bit set to 1 or 0 according to the request + */ + long bitpos(String key, boolean value); + + /** + * Bitpos Command + * Return the position of the first bit set to 1 or 0 in a string. + * @param key + * @param value the bit value + * @param params {@link BitPosParams} + * @return The position of the first bit set to 1 or 0 according to the request + */ + long bitpos(String key, boolean value, BitPosParams params); + + /** + * Bitfield Command + * The command treats a Redis string as an array of bits, and is capable of addressing specific integer + * fields of varying bit widths and arbitrary non (necessary) aligned offset. + * @param key + * @param arguments may be used with optional arguments + * @return A List of results + */ + List bitfield(String key, String...arguments); + + /** + * The readonly version of {@link StringCommands#bitfield(String, String...) BITFIELD} + */ + List bitfieldReadonly(String key, String...arguments); + + /** + * Bitop Command + * Perform a bitwise operation between multiple keys (containing string values) and store the result in the destKey. + * @param op can be AND, OR, XOR or NOT + * @param destKey + * @param srcKeys + * @return The size of the string stored in the destKey + */ + long bitop(BitOP op, String destKey, String... srcKeys); + +} diff --git a/src/main/java/redis/clients/jedis/commands/BitPipelineBinaryCommands.java b/src/main/java/redis/clients/jedis/commands/BitPipelineBinaryCommands.java new file mode 100644 index 0000000000..0f57756325 --- /dev/null +++ b/src/main/java/redis/clients/jedis/commands/BitPipelineBinaryCommands.java @@ -0,0 +1,31 @@ +package redis.clients.jedis.commands; + +import java.util.List; + +import redis.clients.jedis.Response; +import redis.clients.jedis.args.BitCountOption; +import redis.clients.jedis.args.BitOP; +import redis.clients.jedis.params.BitPosParams; + +public interface BitPipelineBinaryCommands { + + Response setbit(byte[] key, long offset, boolean value); + + Response getbit(byte[] key, long offset); + + Response bitcount(byte[] key); + + Response bitcount(byte[] key, long start, long end); + + Response bitcount(byte[] key, long start, long end, BitCountOption option); + + Response bitpos(byte[] key, boolean value); + + Response bitpos(byte[] key, boolean value, BitPosParams params); + + Response> bitfield(byte[] key, byte[]... arguments); + + Response> bitfieldReadonly(byte[] key, byte[]... arguments); + + Response bitop(BitOP op, byte[] destKey, byte[]... srcKeys); +} diff --git a/src/main/java/redis/clients/jedis/commands/BitPipelineCommands.java b/src/main/java/redis/clients/jedis/commands/BitPipelineCommands.java new file mode 100644 index 0000000000..433638a337 --- /dev/null +++ b/src/main/java/redis/clients/jedis/commands/BitPipelineCommands.java @@ -0,0 +1,31 @@ +package redis.clients.jedis.commands; + +import redis.clients.jedis.Response; +import redis.clients.jedis.args.BitCountOption; +import redis.clients.jedis.args.BitOP; +import redis.clients.jedis.params.BitPosParams; + +import java.util.List; + +public interface BitPipelineCommands { + + Response setbit(String key, long offset, boolean value); + + Response getbit(String key, long offset); + + Response bitcount(String key); + + Response bitcount(String key, long start, long end); + + Response bitcount(String key, long start, long end, BitCountOption option); + + Response bitpos(String key, boolean value); + + Response bitpos(String key, boolean value, BitPosParams params); + + Response> bitfield(String key, String...arguments); + + Response> bitfieldReadonly(String key, String...arguments); + + Response bitop(BitOP op, String destKey, String... srcKeys); +} diff --git a/src/main/java/redis/clients/jedis/commands/ClientBinaryCommands.java b/src/main/java/redis/clients/jedis/commands/ClientBinaryCommands.java index d4e223de25..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. * @@ -133,6 +143,12 @@ public interface ClientBinaryCommands { */ String clientPause(long timeout, ClientPauseMode mode); + /** + * CLIENT UNPAUSE is used to resume command processing for all clients that were paused by CLIENT PAUSE. + * @return OK + */ + String clientUnpause(); + /** * Turn on the client eviction mode for 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 d77955d6ba..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. * @@ -129,6 +139,12 @@ public interface ClientCommands { */ String clientPause(long timeout, ClientPauseMode mode); + /** + * CLIENT UNPAUSE is used to resume command processing for all clients that were paused by CLIENT PAUSE. + * @return OK + */ + String clientUnpause(); + /** * Turn on the client eviction mode for the current connection. * @@ -142,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..da0d3fc8e0 100644 --- a/src/main/java/redis/clients/jedis/commands/ClusterCommands.java +++ b/src/main/java/redis/clients/jedis/commands/ClusterCommands.java @@ -93,6 +93,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 +108,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 +116,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/FunctionBinaryCommands.java b/src/main/java/redis/clients/jedis/commands/FunctionBinaryCommands.java index 59eb9664d6..14daafd4c9 100644 --- a/src/main/java/redis/clients/jedis/commands/FunctionBinaryCommands.java +++ b/src/main/java/redis/clients/jedis/commands/FunctionBinaryCommands.java @@ -14,6 +14,7 @@ public interface FunctionBinaryCommands { * @param name * @param keys * @param args + * @return */ Object fcall(byte[] name, List keys, List args); @@ -88,11 +89,12 @@ public interface FunctionBinaryCommands { /** * Load a library to Redis. - * @param functionCode the source code. The library payload must start - * with Shebang statement that provides a metadata - * about the library (like the engine to use and the library name). - * Shebang format: #! name=. - * Currently engine name must be lua. + *

+ * The library payload must start with Shebang statement that provides a metadata about the + * library (like the engine to use and the library name). Shebang format: + * {@code #! name=}. Currently engine name must be lua. + * + * @param functionCode the source code. * @return The library name that was loaded */ String functionLoad(byte[] functionCode); diff --git a/src/main/java/redis/clients/jedis/commands/FunctionCommands.java b/src/main/java/redis/clients/jedis/commands/FunctionCommands.java index 2a918d9482..abc8e661d4 100644 --- a/src/main/java/redis/clients/jedis/commands/FunctionCommands.java +++ b/src/main/java/redis/clients/jedis/commands/FunctionCommands.java @@ -92,11 +92,12 @@ public interface FunctionCommands { /** * Load a library to Redis. - * @param functionCode the source code. The library payload must start - * with Shebang statement that provides a metadata - * about the library (like the engine to use and the library name). - * Shebang format: #! name=. - * Currently engine name must be lua. + *

+ * The library payload must start with Shebang statement that provides a metadata about the + * library (like the engine to use and the library name). Shebang format: + * {@code #! name=}. Currently engine name must be lua. + * + * @param functionCode the source code. * @return The library name that was loaded */ String functionLoad(String functionCode); 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 c6bacf36f8..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 { @@ -261,8 +260,9 @@ public interface ListCommands { long linsert(String key, ListPosition where, String pivot, String value); /** - * Inserts specified values at the head of the list stored at key. In contrary to {@link ListBinaryCommands#lpush(byte[], byte[]...) LPUSH}, - * no operation will be performed when key does not yet exist. + * Inserts specified values at the head of the list stored at key. In contrary to + * {@link ListCommands#lpush(String, String...) LPUSH}, no operation will be performed when key + * does not yet exist. * @param key * @param strings the strings to push * @return The length of the list after the push operation @@ -270,8 +270,9 @@ public interface ListCommands { long lpushx(String key, String... strings); /** - * Inserts specified values at the tail of the list stored at key. In contrary to {@link ListBinaryCommands#rpush(byte[], byte[]...) RPUSH}, - * no operation will be performed when key does not yet exist. + * Inserts specified values at the tail of the list stored at key. In contrary to + * {@link ListCommands#rpush(String, String...) RPUSH}, no operation will be performed when key + * does not yet exist. * @param key * @param strings the strings to push * @return The length of the list after the push operation @@ -301,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 @@ -332,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 @@ -396,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/ModuleCommands.java b/src/main/java/redis/clients/jedis/commands/ModuleCommands.java index e2497d3d8a..689f9a0ae8 100644 --- a/src/main/java/redis/clients/jedis/commands/ModuleCommands.java +++ b/src/main/java/redis/clients/jedis/commands/ModuleCommands.java @@ -2,11 +2,13 @@ import java.util.List; import redis.clients.jedis.Module; +import redis.clients.jedis.params.ModuleLoadExParams; public interface ModuleCommands { /** * Load and initialize the Redis module from the dynamic library specified by the path argument. + * * @param path should be the absolute path of the library, including the full filename * @return OK */ @@ -14,15 +16,35 @@ public interface ModuleCommands { /** * Load and initialize the Redis module from the dynamic library specified by the path argument. + * * @param path should be the absolute path of the library, including the full filename * @param args additional arguments are passed unmodified to the module * @return OK */ String moduleLoad(String path, String... args); + /** + * Loads a module from a dynamic library at runtime with configuration directives. + *

+ * This is an extended version of the MODULE LOAD command. + *

+ * It loads and initializes the Redis module from the dynamic library specified by the path + * argument. The path should be the absolute path of the library, including the full filename. + *

+ * You can use the optional CONFIG argument to provide the module with configuration directives. + * Any additional arguments that follow the ARGS keyword are passed unmodified to the module. + * + * @param path should be the absolute path of the library, including the full filename + * @param params as in description + * @return OK + */ + String moduleLoadEx(String path, ModuleLoadExParams params); + /** * Unload the module specified by name. Note that the module's name is reported by the - * {@link ModuleCommands#moduleList() MODULE LIST} command, and may differ from the dynamic library's filename. + * {@link ModuleCommands#moduleList() MODULE LIST} command, and may differ from the dynamic + * library's filename. + * * @param name * @return OK */ @@ -30,6 +52,7 @@ public interface ModuleCommands { /** * Return information about the modules loaded to the server. + * * @return list of {@link Module} */ List moduleList(); diff --git a/src/main/java/redis/clients/jedis/commands/RedisModuleCommands.java b/src/main/java/redis/clients/jedis/commands/RedisModuleCommands.java index af17f2a448..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.RedisBloomCommands; +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 79f468d27e..ca1d9f1e0c 100644 --- a/src/main/java/redis/clients/jedis/commands/RedisModulePipelineCommands.java +++ b/src/main/java/redis/clients/jedis/commands/RedisModulePipelineCommands.java @@ -1,8 +1,8 @@ package redis.clients.jedis.commands; -import redis.clients.jedis.bloom.RedisBloomPipelineCommands; +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 5c4f7427c3..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. @@ -42,7 +44,7 @@ public interface ServerCommands { /** * Delete all the keys of all the existing databases, not just the currently selected one. - * @param flushMode + * @param flushMode SYNC or ASYNC * @return a simple string reply (OK) */ String flushAll(FlushMode flushMode); @@ -53,7 +55,6 @@ public interface ServerCommands { * requirepass directive in the configuration file. If password matches the password in the * configuration file, the server replies with the OK status code and starts accepting commands. * Otherwise, an error is returned and the clients needs to try a new password. - * @param password * @return the result of the auth */ String auth(String password); @@ -61,8 +62,6 @@ public interface ServerCommands { /** * Request for authentication with username and password, based on the ACL feature introduced in * Redis 6.0 see https://redis.io/topics/acl - * @param user - * @param password * @return OK */ String auth(String user, String password); @@ -71,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 @@ -117,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 @@ -203,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 @@ -218,9 +211,39 @@ 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. + *

+ * This command is the most powerful analysis tool in the latency monitoring framework, and is + * able to provide additional statistical data like the average period between latency spikes, the + * median deviation, and a human-readable analysis of the event. For certain events, like fork, + * additional information is provided, like the rate at which the system forks processes. + *

+ * This is the output you should post in the Redis mailing list if you are looking for help about + * Latency related issues. + * + * @return the report + */ + String latencyDoctor(); } 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 46caa3b510..9c34cbc6a6 100644 --- a/src/main/java/redis/clients/jedis/commands/StreamCommands.java +++ b/src/main/java/redis/clients/jedis/commands/StreamCommands.java @@ -12,9 +12,6 @@ public interface StreamCommands { /** * XADD key ID field string [field string ...] * - * @param key - * @param id - * @param hash * @return the ID of the added entry */ StreamEntryID xadd(String key, StreamEntryID id, Map hash); @@ -22,9 +19,6 @@ public interface StreamCommands { /** * XADD key [NOMKSTREAM] [MAXLEN|MINID [=|~] threshold [LIMIT count]] *|ID field value [field value ...] * - * @param key - * @param hash - * @param params * @return the ID of the added entry */ // Legacy @@ -37,7 +31,6 @@ default StreamEntryID xadd(String key, Map hash, XAddParams para /** * XLEN key * - * @param key * @return length of stream */ long xlen(String key); @@ -46,8 +39,10 @@ default StreamEntryID xadd(String key, Map hash, XAddParams para * XRANGE key start end * * @param key - * @param start minimum {@link StreamEntryID} for the retrieved range, passing null will indicate minimum ID possible in the stream - * @param end maximum {@link StreamEntryID} for the retrieved range, passing null will indicate maximum ID possible in the stream + * @param start minimum {@link StreamEntryID} for the retrieved range, passing {@code null} will + * indicate minimum ID possible in the stream + * @param end maximum {@link StreamEntryID} for the retrieved range, passing {@code null} will + * indicate maximum ID possible in the stream * @return The entries with IDs matching the specified range. */ List xrange(String key, StreamEntryID start, StreamEntryID end); @@ -56,8 +51,10 @@ default StreamEntryID xadd(String key, Map hash, XAddParams para * XRANGE key start end COUNT count * * @param key - * @param start minimum {@link StreamEntryID} for the retrieved range, passing null will indicate minimum ID possible in the stream - * @param end maximum {@link StreamEntryID} for the retrieved range, passing null will indicate maximum ID possible in the stream + * @param start minimum {@link StreamEntryID} for the retrieved range, passing {@code null} will + * indicate minimum ID possible in the stream + * @param end maximum {@link StreamEntryID} for the retrieved range, passing {@code null} will + * indicate maximum ID possible in the stream * @param count maximum number of entries returned * @return The entries with IDs matching the specified range. */ @@ -67,8 +64,10 @@ default StreamEntryID xadd(String key, Map hash, XAddParams para * XREVRANGE key end start * * @param key - * @param start minimum {@link StreamEntryID} for the retrieved range, passing null will indicate minimum ID possible in the stream - * @param end maximum {@link StreamEntryID} for the retrieved range, passing null will indicate maximum ID possible in the stream + * @param start minimum {@link StreamEntryID} for the retrieved range, passing {@code null} will + * indicate minimum ID possible in the stream + * @param end maximum {@link StreamEntryID} for the retrieved range, passing {@code null} will + * indicate maximum ID possible in the stream * @return the entries with IDs matching the specified range, from the higher ID to the lower ID matching. */ List xrevrange(String key, StreamEntryID end, StreamEntryID start); @@ -77,8 +76,10 @@ default StreamEntryID xadd(String key, Map hash, XAddParams para * XREVRANGE key end start COUNT count * * @param key - * @param start minimum {@link StreamEntryID} for the retrieved range, passing null will indicate minimum ID possible in the stream - * @param end maximum {@link StreamEntryID} for the retrieved range, passing null will indicate maximum ID possible in the stream + * @param start minimum {@link StreamEntryID} for the retrieved range, passing {@code null} will + * indicate minimum ID possible in the stream + * @param end maximum {@link StreamEntryID} for the retrieved range, passing {@code null} will + * indicate maximum ID possible in the stream * @param count The entries with IDs matching the specified range. * @return the entries with IDs matching the specified range, from the higher ID to the lower ID matching. */ @@ -94,122 +95,71 @@ default StreamEntryID xadd(String key, Map hash, XAddParams para /** * XACK key group ID [ID ...] - * - * @param key - * @param group - * @param ids */ long xack(String key, String group, StreamEntryID... ids); /** - * XGROUP CREATE - * - * @param key - * @param groupName - * @param id - * @param makeStream + * {@code XGROUP CREATE key groupName } */ - String xgroupCreate( String key, String groupName, StreamEntryID id, boolean makeStream); + String xgroupCreate(String key, String groupName, StreamEntryID id, boolean makeStream); /** - * XGROUP SETID - * - * @param key - * @param groupName - * @param id + * {@code XGROUP SETID key groupName } */ - String xgroupSetID( String key, String groupName, StreamEntryID id); + String xgroupSetID(String key, String groupName, StreamEntryID id); /** - * XGROUP DESTROY - * - * @param key - * @param groupName + * XGROUP DESTROY key groupName */ long xgroupDestroy(String key, String groupName); /** - * XGROUP CREATECONSUMER - * @param key - * @param groupName - * @param consumerName + * XGROUP CREATECONSUMER key groupName consumerName */ boolean xgroupCreateConsumer(String key, String groupName, String consumerName); /** - * XGROUP DELCONSUMER - * @param key - * @param groupName - * @param consumerName + * XGROUP DELCONSUMER key groupName consumerName */ long xgroupDelConsumer(String key, String groupName, String consumerName); - /** - * XPENDING key group - * - * @param key - * @param groupName - */ - StreamPendingSummary xpending(String key, String groupName); - - /** - * XPENDING key group [start end count] [consumer] - * - * @param key - * @param groupName - * @param start - * @param end - * @param count - * @param consumerName - * @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]] - * - * @param key - * @param groupName - * @param params - */ - List xpending(String key, String groupName, XPendingParams params); - /** * XDEL key ID [ID ...] - * @param key - * @param ids */ long xdel(String key, StreamEntryID... ids); /** * XTRIM key MAXLEN [~] count - * @param key - * @param maxLen - * @param approximate */ long xtrim(String key, long maxLen, boolean approximate); /** * XTRIM key MAXLEN|MINID [=|~] threshold [LIMIT count] - * @param key - * @param params */ long xtrim(String key, XTrimParams params); /** - * XCLAIM ... + * 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 ] - * [FORCE] + * [FORCE]} */ List xclaim(String key, String group, String consumerName, long minIdleTime, XClaimParams params, StreamEntryID... ids); /** - * XCLAIM ... + * {@code XCLAIM key group consumer min-idle-time ... * [IDLE ] [TIME ] [RETRYCOUNT ] - * [FORCE] JUSTID + * [FORCE] JUSTID} */ List xclaimJustId(String key, String group, String consumerName, long minIdleTime, XClaimParams params, StreamEntryID... ids); @@ -221,7 +171,8 @@ List xclaimJustId(String key, String group, String consumerName, * @param group Consumer Group * @param consumerName Consumer name to transfer the auto claimed entries * @param minIdleTime Entries pending more than minIdleTime will be transferred ownership - * @param start {@link StreamEntryID} - Entries >= start will be transferred ownership, passing null will indicate '-' + * @param start {@link StreamEntryID} - Entries ≥ start will be transferred ownership, passing + * {@code null} will indicate '-' * @param params {@link XAutoClaimParams} */ Map.Entry> xautoclaim(String key, String group, String consumerName, @@ -234,7 +185,8 @@ Map.Entry> xautoclaim(String key, String group, * @param group Consumer Group * @param consumerName Consumer name to transfer the auto claimed entries * @param minIdleTime Entries pending more than minIdleTime will be transferred ownership - * @param start {@link StreamEntryID} - Entries >= start will be transferred ownership, passing null will indicate '-' + * @param start {@link StreamEntryID} - Entries ≥ start will be transferred ownership, passing + * {@code null} will indicate '-' * @param params {@link XAutoClaimParams} */ Map.Entry> xautoclaimJustId(String key, String group, String consumerName, @@ -245,7 +197,7 @@ Map.Entry> xautoclaimJustId(String key, Strin * @param key Stream name * @return {@link StreamInfo} that contains information about the stream */ - StreamInfo xinfoStream (String key); + StreamInfo xinfoStream(String key); /** * Introspection command used in order to retrieve all information about the stream @@ -262,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 @@ -280,26 +226,29 @@ 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 xinfoConsumers (String key, String group); + List xinfoConsumers2(String key, String group); /** * XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] ID [ID ...] - * - * @param xReadParams - * @param streams */ List>> xread(XReadParams xReadParams, Map streams); /** * XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] ID [ID ...] - * - * @param groupName - * @param consumer - * @param xReadGroupParams - * @param streams */ List>> xreadGroup(String groupName, String consumer, XReadGroupParams xReadGroupParams, Map streams); 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 e5bb692bd8..e435c02341 100644 --- a/src/main/java/redis/clients/jedis/commands/StreamPipelineCommands.java +++ b/src/main/java/redis/clients/jedis/commands/StreamPipelineCommands.java @@ -13,9 +13,6 @@ public interface StreamPipelineCommands { /** * XADD key ID field string [field string ...] * - * @param key - * @param id - * @param hash * @return the ID of the added entry */ Response xadd(String key, StreamEntryID id, Map hash); @@ -23,9 +20,6 @@ public interface StreamPipelineCommands { /** * XADD key [NOMKSTREAM] [MAXLEN|MINID [=|~] threshold [LIMIT count]] *|ID field value [field value ...] * - * @param key - * @param hash - * @param params * @return the ID of the added entry */ // Legacy @@ -38,7 +32,6 @@ default Response xadd(String key, Map hash, XAddP /** * XLEN key * - * @param key * @return length of stream */ Response xlen(String key); @@ -46,7 +39,7 @@ default Response xadd(String key, Map hash, XAddP /** * XRANGE key start end * - * @param key + * @param key key * @param start minimum {@link StreamEntryID} for the retrieved range, passing null will indicate minimum ID possible in the stream * @param end maximum {@link StreamEntryID} for the retrieved range, passing null will indicate maximum ID possible in the stream * @return The entries with IDs matching the specified range. @@ -56,7 +49,7 @@ default Response xadd(String key, Map hash, XAddP /** * XRANGE key start end COUNT count * - * @param key + * @param key key * @param start minimum {@link StreamEntryID} for the retrieved range, passing null will indicate minimum ID possible in the stream * @param end maximum {@link StreamEntryID} for the retrieved range, passing null will indicate maximum ID possible in the stream * @param count maximum number of entries returned @@ -67,7 +60,7 @@ default Response xadd(String key, Map hash, XAddP /** * XREVRANGE key end start * - * @param key + * @param key key * @param start minimum {@link StreamEntryID} for the retrieved range, passing null will indicate minimum ID possible in the stream * @param end maximum {@link StreamEntryID} for the retrieved range, passing null will indicate maximum ID possible in the stream * @return the entries with IDs matching the specified range, from the higher ID to the lower ID matching. @@ -77,7 +70,7 @@ default Response xadd(String key, Map hash, XAddP /** * XREVRANGE key end start COUNT count * - * @param key + * @param key key * @param start minimum {@link StreamEntryID} for the retrieved range, passing null will indicate minimum ID possible in the stream * @param end maximum {@link StreamEntryID} for the retrieved range, passing null will indicate maximum ID possible in the stream * @param count The entries with IDs matching the specified range. @@ -95,122 +88,71 @@ default Response xadd(String key, Map hash, XAddP /** * XACK key group ID [ID ...] - * - * @param key - * @param group - * @param ids */ Response xack(String key, String group, StreamEntryID... ids); /** - * XGROUP CREATE - * - * @param key - * @param groupName - * @param id - * @param makeStream + * {@code XGROUP CREATE key groupName } */ Response xgroupCreate( String key, String groupName, StreamEntryID id, boolean makeStream); /** - * XGROUP SETID - * - * @param key - * @param groupName - * @param id + * {@code XGROUP SETID key groupName } */ Response xgroupSetID( String key, String groupName, StreamEntryID id); /** - * XGROUP DESTROY - * - * @param key - * @param groupName + * XGROUP DESTROY key groupName */ Response xgroupDestroy(String key, String groupName); /** - * XGROUP CREATECONSUMER - * @param key - * @param groupName - * @param consumerName + * XGROUP CREATECONSUMER key groupName consumerName */ Response xgroupCreateConsumer( String key, String groupName, String consumerName); /** - * XGROUP DELCONSUMER - * @param key - * @param groupName - * @param consumerName + * XGROUP DELCONSUMER key groupName consumerName */ Response xgroupDelConsumer( String key, String groupName, String consumerName); /** * XPENDING key group - * - * @param key - * @param groupName */ Response xpending(String key, String groupName); - /** - * XPENDING key group [start end count] [consumer] - * - * @param key - * @param groupName - * @param start - * @param end - * @param count - * @param consumerName - * @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]] - * - * @param key - * @param groupName - * @param params */ Response> xpending(String key, String groupName, XPendingParams params); /** * XDEL key ID [ID ...] - * @param key - * @param ids */ Response xdel(String key, StreamEntryID... ids); /** * XTRIM key MAXLEN [~] count - * @param key - * @param maxLen - * @param approximate */ Response xtrim(String key, long maxLen, boolean approximate); /** * XTRIM key MAXLEN|MINID [=|~] threshold [LIMIT count] - * @param key - * @param params */ Response xtrim(String key, XTrimParams params); /** - * XCLAIM ... + * {@code XCLAIM key group consumer min-idle-time ... * [IDLE ] [TIME ] [RETRYCOUNT ] - * [FORCE] + * [FORCE]} */ Response> xclaim(String key, String group, String consumerName, long minIdleTime, XClaimParams params, StreamEntryID... ids); /** - * XCLAIM ... + * {@code XCLAIM key group consumer min-idle-time ... * [IDLE ] [TIME ] [RETRYCOUNT ] - * [FORCE] JUSTID + * [FORCE] JUSTID} */ Response> xclaimJustId(String key, String group, String consumerName, long minIdleTime, XClaimParams params, StreamEntryID... ids); @@ -222,7 +164,8 @@ Response> xclaimJustId(String key, String group, String cons * @param group Consumer Group * @param consumerName Consumer name to transfer the auto claimed entries * @param minIdleTime Entries pending more than minIdleTime will be transferred ownership - * @param start {@link StreamEntryID} - Entries >= start will be transferred ownership, passing null will indicate '-' + * @param start {@link StreamEntryID} - Entries ≥ start will be transferred ownership, passing + * {@code null} will indicate '-' * @param params {@link XAutoClaimParams} */ Response>> xautoclaim(String key, String group, String consumerName, @@ -235,7 +178,8 @@ Response>> xautoclaim(String key, Str * @param group Consumer Group * @param consumerName Consumer name to transfer the auto claimed entries * @param minIdleTime Entries pending more than minIdleTime will be transferred ownership - * @param start {@link StreamEntryID} - Entries >= start will be transferred ownership, passing null will indicate '-' + * @param start {@link StreamEntryID} - Entries ≥ start will be transferred ownership, passing + * {@code null} will indicate '-' * @param params {@link XAutoClaimParams} */ Response>> xautoclaimJustId(String key, String group, String consumerName, @@ -246,7 +190,7 @@ Response>> xautoclaimJustId(String * @param key Stream name * @return {@link StreamInfo} that contains information about the stream */ - Response xinfoStream (String key); + Response xinfoStream(String key); /** * Introspection command used in order to retrieve all information about the stream @@ -263,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 @@ -281,26 +219,29 @@ 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> xinfoConsumers (String key, String group); + Response> xinfoConsumers2(String key, String group); /** * XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] ID [ID ...] - * - * @param xReadParams - * @param streams */ Response>>> xread(XReadParams xReadParams, Map streams); /** * XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] ID [ID ...] - * - * @param groupName - * @param consumer - * @param xReadGroupParams - * @param streams */ Response>>> xreadGroup(String groupName, String consumer, XReadGroupParams xReadGroupParams, Map streams); diff --git a/src/main/java/redis/clients/jedis/commands/StringBinaryCommands.java b/src/main/java/redis/clients/jedis/commands/StringBinaryCommands.java index abccef7d92..ca51b1a1af 100644 --- a/src/main/java/redis/clients/jedis/commands/StringBinaryCommands.java +++ b/src/main/java/redis/clients/jedis/commands/StringBinaryCommands.java @@ -2,16 +2,12 @@ import java.util.List; -import redis.clients.jedis.args.BitCountOption; -import redis.clients.jedis.args.BitOP; -import redis.clients.jedis.params.BitPosParams; 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; -public interface StringBinaryCommands { +public interface StringBinaryCommands extends BitBinaryCommands { String set(byte[] key, byte[] value); @@ -19,13 +15,13 @@ public interface StringBinaryCommands { byte[] get(byte[] key); - byte[] getDel(byte[] key); + byte[] setGet(byte[] key, byte[] value); - byte[] getEx(byte[] key, GetExParams params); + byte[] setGet(byte[] key, byte[] value, SetParams params); - boolean setbit(byte[] key, long offset, boolean value); + byte[] getDel(byte[] key); - boolean getbit(byte[] key, long offset); + byte[] getEx(byte[] key, GetExParams params); long setrange(byte[] key, long offset, byte[] value); @@ -61,29 +57,6 @@ public interface StringBinaryCommands { long strlen(byte[] key); - long bitcount(byte[] key); - - long bitcount(byte[] key, long start, long end); - - long bitcount(byte[] key, long start, long end, BitCountOption option); - - long bitpos(byte[] key, boolean value); - - long bitpos(byte[] key, boolean value, BitPosParams params); - - List bitfield(byte[] key, byte[]... arguments); - - List bitfieldReadonly(byte[] key, byte[]... arguments); - - long bitop(BitOP op, byte[] destKey, byte[]... srcKeys); - - /** - * @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 316f6c9836..0621bc9334 100644 --- a/src/main/java/redis/clients/jedis/commands/StringCommands.java +++ b/src/main/java/redis/clients/jedis/commands/StringCommands.java @@ -2,16 +2,12 @@ import java.util.List; -import redis.clients.jedis.args.BitCountOption; -import redis.clients.jedis.args.BitOP; -import redis.clients.jedis.params.BitPosParams; 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; -public interface StringCommands { +public interface StringCommands extends BitCommands { /** * Set Command @@ -28,11 +24,13 @@ public interface StringCommands { * Set Command * Set the string value as value of the key. Can be used with optional params. *

- * Time complexity: O(1)< + * Time complexity: O(1) * @param key * @param value * @param params {@link SetParams} - * @return OK + * @return simple-string-reply {@code OK} if {@code SET} was executed correctly, or {@code null} + * if the {@code SET} operation was not performed because the user specified the NX or XX option + * but the condition was not met. */ String set(String key, String value, SetParams params); @@ -48,6 +46,10 @@ public interface StringCommands { */ String get(String key); + String setGet(String key, String value); + + String setGet(String key, String value, SetParams params); + /** * GetDel Command * Get the value of key and delete the key. This command is similar to GET, except for the fact @@ -55,7 +57,7 @@ public interface StringCommands { *

* Time complexity: O(1) * @param key - * @return The value of key + * @return The value stored in key */ String getDel(String key); @@ -72,33 +74,10 @@ public interface StringCommands { * Time complexity: O(1) * @param key * @param params {@link GetExParams} - * @return The original bit value stored at offset + * @return The value stored in key */ String getEx(String key, GetExParams params); - /** - * SetBit Command - * Sets or clears the bit at offset in the string value stored at key. - *

- * Time complexity: O(1) - * @param key - * @param offset - * @param value - * @return The original bit value stored at offset - */ - boolean setbit(String key, long offset, boolean value); - - /** - * GetBit Command - * Returns the bit value at offset in the string value stored at key. - *

- * Time complexity: O(1) - * @param key - * @param offset - * @return The bit value stored at offset - */ - boolean getbit(String key, long offset); - /** * SetRange Command * GETRANGE overwrite part of the string stored at key, starting at the specified offset, for the entire @@ -193,7 +172,7 @@ public interface StringCommands { /** * 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. *

@@ -234,10 +213,10 @@ public interface StringCommands { * 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) @@ -251,10 +230,10 @@ public interface StringCommands { * 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) @@ -288,10 +267,10 @@ public interface StringCommands { * 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) @@ -305,10 +284,10 @@ public interface StringCommands { * 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) @@ -360,93 +339,6 @@ public interface StringCommands { */ long strlen(String key); - /** - * Bitcount Command - * Count the number of set bits (population counting) in a string. - * @param key - * @return The number of bits set to 1 - */ - long bitcount(String key); - - /** - * Bitcount Command - * Count the number of set bits (population counting) in a string only in an interval start and end. - *

- * Like for the GETRANGE command start and end can contain negative values in order to index bytes - * starting from the end of the string, where -1 is the last byte, -2 is the penultimate, and so forth. - * @param key - * @param start byte start index - * @param end byte end index - * @return The number of bits set to 1 - */ - long bitcount(String key, long start, long end); - - /** - * @see StringCommands#bitcount(String, long, long) - * @param key - * @param start byte start index - * @param end byte end index - * @param option indicate BYTE or BIT - * @return The number of bits set to 1 - */ - long bitcount(String key, long start, long end, BitCountOption option); - - /** - * Bitpos Command - * Return the position of the first bit set to 1 or 0 in a string. - * @param key - * @param value the bit value - * @return The position of the first bit set to 1 or 0 according to the request - */ - long bitpos(String key, boolean value); - - /** - * Bitpos Command - * Return the position of the first bit set to 1 or 0 in a string. - * @param key - * @param value the bit value - * @param params {@link BitPosParams} - * @return The position of the first bit set to 1 or 0 according to the request - */ - long bitpos(String key, boolean value, BitPosParams params); - - /** - * Bitfield Command - * The command treats a Redis string as an array of bits, and is capable of addressing specific integer - * fields of varying bit widths and arbitrary non (necessary) aligned offset. - * @param key - * @param arguments may be used with optional arguments - * @return A List of results - */ - List bitfield(String key, String...arguments); - - /** - * The readonly version of {@link StringCommands#bitfield(String, String...) BITFIELD} - */ - List bitfieldReadonly(String key, String...arguments); - - /** - * Bitop Command - * Perform a bitwise operation between multiple keys (containing string values) and store the result in the destKey. - * @param op can be AND, OR, XOR or NOT - * @param destKey - * @param srcKeys - * @return The size of the string stored in the destKey - */ - long bitop(BitOP op, String destKey, String... srcKeys); - - /** - * 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 15edfa928b..b4a114d565 100644 --- a/src/main/java/redis/clients/jedis/commands/StringPipelineBinaryCommands.java +++ b/src/main/java/redis/clients/jedis/commands/StringPipelineBinaryCommands.java @@ -3,16 +3,12 @@ import java.util.List; import redis.clients.jedis.Response; -import redis.clients.jedis.args.BitCountOption; -import redis.clients.jedis.args.BitOP; -import redis.clients.jedis.params.BitPosParams; 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; -public interface StringPipelineBinaryCommands { +public interface StringPipelineBinaryCommands extends BitPipelineBinaryCommands { Response set(byte[] key, byte[] value); @@ -20,14 +16,12 @@ public interface StringPipelineBinaryCommands { Response get(byte[] key); + Response setGet(byte[] key, byte[] value, SetParams params); + Response getDel(byte[] key); Response getEx(byte[] key, GetExParams params); - Response setbit(byte[] key, long offset, boolean value); - - Response getbit(byte[] key, long offset); - Response setrange(byte[] key, long offset, byte[] value); Response getrange(byte[] key, long startOffset, long endOffset); @@ -62,28 +56,5 @@ public interface StringPipelineBinaryCommands { Response strlen(byte[] key); - Response bitcount(byte[] key); - - Response bitcount(byte[] key, long start, long end); - - Response bitcount(byte[] key, long start, long end, BitCountOption option); - - Response bitpos(byte[] key, boolean value); - - Response bitpos(byte[] key, boolean value, BitPosParams params); - - Response> bitfield(byte[] key, byte[]... arguments); - - Response> bitfieldReadonly(byte[] key, byte[]... arguments); - - Response bitop(BitOP op, byte[] destKey, byte[]... srcKeys); - - /** - * @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 862fbf555d..6af9968ebe 100644 --- a/src/main/java/redis/clients/jedis/commands/StringPipelineCommands.java +++ b/src/main/java/redis/clients/jedis/commands/StringPipelineCommands.java @@ -1,18 +1,14 @@ package redis.clients.jedis.commands; import redis.clients.jedis.Response; -import redis.clients.jedis.args.BitCountOption; -import redis.clients.jedis.args.BitOP; -import redis.clients.jedis.params.BitPosParams; 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; import java.util.List; -public interface StringPipelineCommands { +public interface StringPipelineCommands extends BitPipelineCommands { Response set(String key, String value); @@ -20,14 +16,12 @@ public interface StringPipelineCommands { Response get(String key); + Response setGet(String key, String value, SetParams params); + Response getDel(String key); Response getEx(String key, GetExParams params); - Response setbit(String key, long offset, boolean value); - - Response getbit(String key, long offset); - Response setrange(String key, long offset, String value); Response getrange(String key, long startOffset, long endOffset); @@ -62,29 +56,5 @@ public interface StringPipelineCommands { Response strlen(String key); - Response bitcount(String key); - - Response bitcount(String key, long start, long end); - - Response bitcount(String key, long start, long end, BitCountOption option); - - Response bitpos(String key, boolean value); - - Response bitpos(String key, boolean value, BitPosParams params); - - Response> bitfield(String key, String...arguments); - - Response> bitfieldReadonly(String key, String...arguments); - - Response bitop(BitOP op, String destKey, String... srcKeys); - - /** - * @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/commands/package-info.java b/src/main/java/redis/clients/jedis/commands/package-info.java new file mode 100644 index 0000000000..055ca5e14a --- /dev/null +++ b/src/main/java/redis/clients/jedis/commands/package-info.java @@ -0,0 +1,4 @@ +/** + * This package contains the interfaces that contain methods representing Redis core commands. + */ +package redis.clients.jedis.commands; 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/JedisAccessControlException.java b/src/main/java/redis/clients/jedis/exceptions/JedisAccessControlException.java index b58f05f593..c3bf2b8932 100644 --- a/src/main/java/redis/clients/jedis/exceptions/JedisAccessControlException.java +++ b/src/main/java/redis/clients/jedis/exceptions/JedisAccessControlException.java @@ -1,5 +1,8 @@ package redis.clients.jedis.exceptions; +/** + * An access control error reply from Redis; i.e. {@code -WRONGPASS}, {@code -NOPERM}. + */ public class JedisAccessControlException extends JedisDataException { public JedisAccessControlException(String message) { diff --git a/src/main/java/redis/clients/jedis/exceptions/JedisAskDataException.java b/src/main/java/redis/clients/jedis/exceptions/JedisAskDataException.java index 87e41fda42..bb667882f0 100644 --- a/src/main/java/redis/clients/jedis/exceptions/JedisAskDataException.java +++ b/src/main/java/redis/clients/jedis/exceptions/JedisAskDataException.java @@ -2,6 +2,9 @@ import redis.clients.jedis.HostAndPort; +/** + * {@code -ASK} reply from Redis. + */ public class JedisAskDataException extends JedisRedirectionException { private static final long serialVersionUID = 3878126572474819403L; 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/JedisBusyException.java b/src/main/java/redis/clients/jedis/exceptions/JedisBusyException.java index a7483162fb..a004b91ab1 100644 --- a/src/main/java/redis/clients/jedis/exceptions/JedisBusyException.java +++ b/src/main/java/redis/clients/jedis/exceptions/JedisBusyException.java @@ -1,5 +1,8 @@ package redis.clients.jedis.exceptions; +/** + * {@code -BUSY} reply from Redis. + */ public class JedisBusyException extends JedisDataException { private static final long serialVersionUID = 3992655220229243478L; diff --git a/src/main/java/redis/clients/jedis/exceptions/JedisClusterException.java b/src/main/java/redis/clients/jedis/exceptions/JedisClusterException.java index a015c477d5..2771d90946 100644 --- a/src/main/java/redis/clients/jedis/exceptions/JedisClusterException.java +++ b/src/main/java/redis/clients/jedis/exceptions/JedisClusterException.java @@ -1,5 +1,8 @@ package redis.clients.jedis.exceptions; +/** + * Any {@code -CLUSTER...} reply from Redis. + */ public class JedisClusterException extends JedisDataException { private static final long serialVersionUID = 3878126572474819403L; diff --git a/src/main/java/redis/clients/jedis/exceptions/JedisClusterOperationException.java b/src/main/java/redis/clients/jedis/exceptions/JedisClusterOperationException.java index 9efb4169f4..3d5f18b7aa 100644 --- a/src/main/java/redis/clients/jedis/exceptions/JedisClusterOperationException.java +++ b/src/main/java/redis/clients/jedis/exceptions/JedisClusterOperationException.java @@ -1,5 +1,8 @@ package redis.clients.jedis.exceptions; +/** + * Error while processing cluster operations. This is not an error reply from Redis. + */ public class JedisClusterOperationException extends JedisException { private static final long serialVersionUID = 8124535086306604887L; diff --git a/src/main/java/redis/clients/jedis/exceptions/JedisConnectionException.java b/src/main/java/redis/clients/jedis/exceptions/JedisConnectionException.java index 3304aa91fe..5bcfe6a7be 100644 --- a/src/main/java/redis/clients/jedis/exceptions/JedisConnectionException.java +++ b/src/main/java/redis/clients/jedis/exceptions/JedisConnectionException.java @@ -1,5 +1,8 @@ package redis.clients.jedis.exceptions; +/** + * A connection error. + */ public class JedisConnectionException extends JedisException { private static final long serialVersionUID = 3878126572474819403L; diff --git a/src/main/java/redis/clients/jedis/exceptions/JedisDataException.java b/src/main/java/redis/clients/jedis/exceptions/JedisDataException.java index 62a91c5d66..6f1216e22f 100644 --- a/src/main/java/redis/clients/jedis/exceptions/JedisDataException.java +++ b/src/main/java/redis/clients/jedis/exceptions/JedisDataException.java @@ -1,5 +1,8 @@ package redis.clients.jedis.exceptions; +/** + * Any error reply from Redis. + */ public class JedisDataException extends JedisException { private static final long serialVersionUID = 3878126572474819403L; diff --git a/src/main/java/redis/clients/jedis/exceptions/JedisException.java b/src/main/java/redis/clients/jedis/exceptions/JedisException.java index 25b809370a..cc4ed32a29 100644 --- a/src/main/java/redis/clients/jedis/exceptions/JedisException.java +++ b/src/main/java/redis/clients/jedis/exceptions/JedisException.java @@ -1,5 +1,8 @@ package redis.clients.jedis.exceptions; +/** + * Umbrella exception class for all exceptions in Jedis library. + */ public class JedisException extends RuntimeException { private static final long serialVersionUID = -2946266495682282677L; diff --git a/src/main/java/redis/clients/jedis/exceptions/JedisMovedDataException.java b/src/main/java/redis/clients/jedis/exceptions/JedisMovedDataException.java index b9e2f5a024..dfd95c8b4f 100644 --- a/src/main/java/redis/clients/jedis/exceptions/JedisMovedDataException.java +++ b/src/main/java/redis/clients/jedis/exceptions/JedisMovedDataException.java @@ -2,6 +2,9 @@ import redis.clients.jedis.HostAndPort; +/** + * {@code -MOVED} reply from Redis. + */ public class JedisMovedDataException extends JedisRedirectionException { private static final long serialVersionUID = 3878126572474819403L; diff --git a/src/main/java/redis/clients/jedis/exceptions/JedisNoScriptException.java b/src/main/java/redis/clients/jedis/exceptions/JedisNoScriptException.java index 4106e6ffcc..f3c4d32a01 100644 --- a/src/main/java/redis/clients/jedis/exceptions/JedisNoScriptException.java +++ b/src/main/java/redis/clients/jedis/exceptions/JedisNoScriptException.java @@ -1,5 +1,8 @@ package redis.clients.jedis.exceptions; +/** + * {@code -NOSCRIPT} reply from Redis. + */ public class JedisNoScriptException extends JedisDataException { private static final long serialVersionUID = 4674378093072060731L; diff --git a/src/main/java/redis/clients/jedis/exceptions/JedisRedirectionException.java b/src/main/java/redis/clients/jedis/exceptions/JedisRedirectionException.java index 40f377aaed..e5e1757da9 100644 --- a/src/main/java/redis/clients/jedis/exceptions/JedisRedirectionException.java +++ b/src/main/java/redis/clients/jedis/exceptions/JedisRedirectionException.java @@ -2,6 +2,12 @@ import redis.clients.jedis.HostAndPort; +/** + * Umbrella exception class representing all redirection replies from Redis. + * + * @see JedisAskDataException + * @see JedisMovedDataException + */ public class JedisRedirectionException extends JedisDataException { private static final long serialVersionUID = 3878126572474819403L; 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/exceptions/package-info.java b/src/main/java/redis/clients/jedis/exceptions/package-info.java new file mode 100644 index 0000000000..b440452756 --- /dev/null +++ b/src/main/java/redis/clients/jedis/exceptions/package-info.java @@ -0,0 +1,4 @@ +/** + * This package contains the Exception classes. + */ +package redis.clients.jedis.exceptions; diff --git a/src/main/java/redis/clients/jedis/executors/CircuitBreakerCommandExecutor.java b/src/main/java/redis/clients/jedis/executors/CircuitBreakerCommandExecutor.java new file mode 100644 index 0000000000..a01a58d98d --- /dev/null +++ b/src/main/java/redis/clients/jedis/executors/CircuitBreakerCommandExecutor.java @@ -0,0 +1,95 @@ +package redis.clients.jedis.executors; + +import io.github.resilience4j.circuitbreaker.CallNotPermittedException; +import io.github.resilience4j.circuitbreaker.CircuitBreaker; +import io.github.resilience4j.decorators.Decorators; +import io.github.resilience4j.decorators.Decorators.DecorateSupplier; +import redis.clients.jedis.*; +import redis.clients.jedis.exceptions.JedisConnectionException; +import redis.clients.jedis.providers.MultiClusterPooledConnectionProvider; +import redis.clients.jedis.providers.MultiClusterPooledConnectionProvider.Cluster; +import redis.clients.jedis.util.IOUtils; + +import java.util.Arrays; +import java.util.List; + + +/** + * @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 implements CommandExecutor { + + private final static List> circuitBreakerFallbackException = + Arrays.asList(CallNotPermittedException.class); + + private final MultiClusterPooledConnectionProvider provider; + + public CircuitBreakerCommandExecutor(MultiClusterPooledConnectionProvider provider) { + this.provider = provider; + } + + @Override + public void close() { + IOUtils.closeQuietly(this.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(circuitBreakerFallbackException, + 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 synchronized T handleClusterFailover(CommandObject commandObject, 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"); + } + + // 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/executors/ClusterCommandExecutor.java b/src/main/java/redis/clients/jedis/executors/ClusterCommandExecutor.java index 345ed3509b..4cc25c42a9 100644 --- a/src/main/java/redis/clients/jedis/executors/ClusterCommandExecutor.java +++ b/src/main/java/redis/clients/jedis/executors/ClusterCommandExecutor.java @@ -2,13 +2,16 @@ 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; import org.slf4j.LoggerFactory; 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); @@ -54,7 +90,7 @@ public final T executeCommand(CommandObject commandObject) { connection = provider.getConnection(commandObject.getArguments()); } - return connection.executeCommand(commandObject); + return execute(connection, commandObject); } catch (JedisClusterOperationException jnrcne) { throw jnrcne; @@ -95,6 +131,14 @@ public final T executeCommand(CommandObject commandObject) { throw maxAttemptsException; } + /** + * WARNING: This method is accessible for the purpose of testing. + * This should not be used or overriden. + */ + protected T execute(Connection connection, CommandObject commandObject) { + return connection.executeCommand(commandObject); + } + /** * Related values should be reset if TRUE is returned. * @@ -141,9 +185,14 @@ private static long getBackoffSleepMillis(int attemptsLeft, Instant deadline) { throw new JedisClusterOperationException("Cluster retry deadline exceeded."); } - return millisLeft / (attemptsLeft * (attemptsLeft + 1)); + long maxBackOff = millisLeft / (attemptsLeft * attemptsLeft); + return ThreadLocalRandom.current().nextLong(maxBackOff + 1); } + /** + * WARNING: This method is accessible for the purpose of testing. + * This should not be used or overriden. + */ protected void sleep(long sleepMillis) { try { TimeUnit.MILLISECONDS.sleep(sleepMillis); 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/executors/RetryableCommandExecutor.java b/src/main/java/redis/clients/jedis/executors/RetryableCommandExecutor.java index c271ee9a9a..f4f9002539 100644 --- a/src/main/java/redis/clients/jedis/executors/RetryableCommandExecutor.java +++ b/src/main/java/redis/clients/jedis/executors/RetryableCommandExecutor.java @@ -5,9 +5,9 @@ import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import redis.clients.jedis.CommandObject; import redis.clients.jedis.Connection; - import redis.clients.jedis.exceptions.JedisConnectionException; import redis.clients.jedis.exceptions.JedisException; import redis.clients.jedis.util.IOUtils; @@ -45,7 +45,7 @@ public final T executeCommand(CommandObject commandObject) { try { connection = provider.getConnection(commandObject.getArguments()); - return connection.executeCommand(commandObject); + return execute(connection, commandObject); } catch (JedisConnectionException jce) { lastException = jce; @@ -62,15 +62,23 @@ public final T executeCommand(CommandObject commandObject) { } } if (Instant.now().isAfter(deadline)) { - throw new JedisException("Cluster retry deadline exceeded."); + throw new JedisException("Retry deadline exceeded."); } } - JedisException maxAttemptsException = new JedisException("No more cluster attempts left."); + JedisException maxAttemptsException = new JedisException("No more attempts left."); maxAttemptsException.addSuppressed(lastException); throw maxAttemptsException; } + /** + * WARNING: This method is accessible for the purpose of testing. + * This should not be used or overriden. + */ + protected T execute(Connection connection, CommandObject commandObject) { + return connection.executeCommand(commandObject); + } + /** * Related values should be reset if TRUE is returned. * @@ -97,12 +105,16 @@ private static long getBackoffSleepMillis(int attemptsLeft, Instant deadline) { long millisLeft = Duration.between(Instant.now(), deadline).toMillis(); if (millisLeft < 0) { - throw new JedisException("Cluster retry deadline exceeded."); + throw new JedisException("Retry deadline exceeded."); } return millisLeft / (attemptsLeft * (attemptsLeft + 1)); } + /** + * WARNING: This method is accessible for the purpose of testing. + * This should not be used or overriden. + */ protected void sleep(long sleepMillis) { try { TimeUnit.MILLISECONDS.sleep(sleepMillis); diff --git a/src/main/java/redis/clients/jedis/executors/package-info.java b/src/main/java/redis/clients/jedis/executors/package-info.java new file mode 100644 index 0000000000..f2f1ca6957 --- /dev/null +++ b/src/main/java/redis/clients/jedis/executors/package-info.java @@ -0,0 +1,4 @@ +/** + * This package contains the implementations of CommandExecutor interface. + */ +package redis.clients.jedis.executors; 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 26de5864de..6884466c10 100644 --- a/src/main/java/redis/clients/jedis/graph/GraphProtocol.java +++ b/src/main/java/redis/clients/jedis/graph/GraphProtocol.java @@ -4,13 +4,20 @@ import redis.clients.jedis.commands.ProtocolCommand; import redis.clients.jedis.util.SafeEncoder; +@Deprecated public class GraphProtocol { + @Deprecated public enum GraphCommand implements ProtocolCommand { QUERY, RO_QUERY, - DELETE; + DELETE, + LIST, + PROFILE, + EXPLAIN, + SLOWLOG, + CONFIG; private final byte[] raw; @@ -24,10 +31,13 @@ public byte[] getRaw() { } } + @Deprecated public enum GraphKeyword implements Rawable { CYPHER, TIMEOUT, + SET, + GET, __COMPACT("--COMPACT"); private final byte[] raw; 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 68cf747169..45115a7bfa 100644 --- a/src/main/java/redis/clients/jedis/graph/RedisGraphCommands.java +++ b/src/main/java/redis/clients/jedis/graph/RedisGraphCommands.java @@ -1,7 +1,12 @@ package redis.clients.jedis.graph; +import java.util.List; import java.util.Map; +/** + * @deprecated Redis Graph support is deprecated. + */ +@Deprecated public interface RedisGraphCommands { /** @@ -10,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); /** @@ -19,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); /** @@ -29,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); /** @@ -39,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); /** @@ -49,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); /** @@ -59,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); /** @@ -70,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); /** @@ -81,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); /** @@ -89,7 +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. + */ + @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 f8933206d6..b270fc79c8 100644 --- a/src/main/java/redis/clients/jedis/graph/RedisGraphPipelineCommands.java +++ b/src/main/java/redis/clients/jedis/graph/RedisGraphPipelineCommands.java @@ -1,26 +1,42 @@ package redis.clients.jedis.graph; +import java.util.List; 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 1478efb25e..9269331cb4 100644 --- a/src/main/java/redis/clients/jedis/graph/ResultSetBuilder.java +++ b/src/main/java/redis/clients/jedis/graph/ResultSetBuilder.java @@ -9,17 +9,18 @@ import java.util.Map; import java.util.Objects; 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.exceptions.JedisException; -import redis.clients.jedis.graph.entities.Edge; -import redis.clients.jedis.graph.entities.GraphEntity; -import redis.clients.jedis.graph.entities.Node; -import redis.clients.jedis.graph.entities.Path; -import redis.clients.jedis.graph.entities.Point; +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; @@ -129,42 +130,44 @@ public Iterator iterator() { @SuppressWarnings("unchecked") private List parseRecords(Header header, Object data) { List> rawResultSet = (List>) data; - List results = new ArrayList<>(); - if (rawResultSet == null || rawResultSet.isEmpty()) { - return results; - } else { - // go over each raw result - for (List row : rawResultSet) { - - List parsedRow = new ArrayList<>(row.size()); - // go over each object in the result - for (int i = 0; i < row.size(); i++) { - // get raw representation of the object - List obj = (List) row.get(i); - // get object type - ResultSet.ColumnType objType = header.getSchemaTypes().get(i); - // deserialize according to type and - switch (objType) { - case NODE: - parsedRow.add(deserializeNode(obj)); - break; - case RELATION: - parsedRow.add(deserializeEdge(obj)); - break; - case SCALAR: - parsedRow.add(deserializeScalar(obj)); - break; - default: - parsedRow.add(null); - break; - } + if (rawResultSet == null || rawResultSet.isEmpty()) { + return new ArrayList<>(0); + } + + List results = new ArrayList<>(rawResultSet.size()); + // go over each raw result + for (List row : rawResultSet) { + + List parsedRow = new ArrayList<>(row.size()); + // go over each object in the result + for (int i = 0; i < row.size(); i++) { + // get raw representation of the object + List obj = (List) row.get(i); + // get object type + ResultSet.ColumnType objType = header.getSchemaTypes().get(i); + // deserialize according to type and + switch (objType) { + case NODE: + parsedRow.add(deserializeNode(obj)); + break; + case RELATION: + parsedRow.add(deserializeEdge(obj)); + break; + case SCALAR: + parsedRow.add(deserializeScalar(obj)); + break; + default: + parsedRow.add(null); + break; } - // create new record from deserialized objects - Record record = new RecordImpl(header.getSchemaNames(), parsedRow); - results.add(record); } + + // create new record from deserialized objects + Record record = new RecordImpl(header.getSchemaNames(), parsedRow); + results.add(record); } + return results; } @@ -177,25 +180,28 @@ private List parseRecords(Header header, Object data) { */ @SuppressWarnings("unchecked") private Node deserializeNode(List rawNodeData) { - Node node = new Node(); - deserializeGraphEntityId(node, rawNodeData.get(0)); + List labelsIndices = (List) rawNodeData.get(1); + List> rawProperties = (List>) rawNodeData.get(2); + + Node node = new Node(labelsIndices.size(), rawProperties.size()); + deserializeGraphEntityId(node, (Long) rawNodeData.get(0)); + for (Long labelIndex : labelsIndices) { String label = graphCache.getLabel(labelIndex.intValue()); node.addLabel(label); } - deserializeGraphEntityProperties(node, (List>) rawNodeData.get(2)); - return node; + deserializeGraphEntityProperties(node, rawProperties); + return node; } /** * @param graphEntity graph entity - * @param rawEntityId raw representation of entity id to be set to the graph entity + * @param id entity id to be set to the graph entity */ - private void deserializeGraphEntityId(GraphEntity graphEntity, Object rawEntityId) { - long id = (Long) rawEntityId; + private void deserializeGraphEntityId(GraphEntity graphEntity, long id) { graphEntity.setId(id); } @@ -207,8 +213,11 @@ private void deserializeGraphEntityId(GraphEntity graphEntity, Object rawEntityI */ @SuppressWarnings("unchecked") private Edge deserializeEdge(List rawEdgeData) { - Edge edge = new Edge(); - deserializeGraphEntityId(edge, rawEdgeData.get(0)); + + List> rawProperties = (List>) rawEdgeData.get(4); + + Edge edge = new Edge(rawProperties.size()); + deserializeGraphEntityId(edge, (Long) rawEdgeData.get(0)); String relationshipType = graphCache.getRelationshipType(((Long) rawEdgeData.get(1)).intValue()); edge.setRelationshipType(relationshipType); @@ -216,7 +225,7 @@ private Edge deserializeEdge(List rawEdgeData) { edge.setSource((long) rawEdgeData.get(2)); edge.setDestination((long) rawEdgeData.get(3)); - deserializeGraphEntityProperties(edge, (List>) rawEdgeData.get(4)); + deserializeGraphEntityProperties(edge, rawProperties); return edge; } @@ -237,7 +246,6 @@ private void deserializeGraphEntityProperties(GraphEntity entity, List deserializeMap(Object rawScalarData) { List keyTypeValueEntries = (List) rawScalarData; - Map map = new HashMap<>(); - for (int i = 0; i < keyTypeValueEntries.size(); i += 2) { + + int size = keyTypeValueEntries.size(); + Map map = new HashMap<>(size >> 1); // set the capacity to half of the list + + for (int i = 0; i < size; i += 2) { String key = SafeEncoder.encode((byte[]) keyTypeValueEntries.get(i)); Object value = deserializeScalar((List) keyTypeValueEntries.get(i + 1)); map.put(key, value); @@ -327,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 406967fee7..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,17 +3,30 @@ 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 - private String relationshipType; + private String relationshipType; private long source; private long destination; + public Edge() { + super(); + } + /** + * Use this constructor to reduce memory allocations + * when properties are added to the edge + * @param propertiesCapacity preallocate the capacity for the properties + */ + public Edge(int propertiesCapacity) { + super(propertiesCapacity); + } //getters & setters /** 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 6af7321e61..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,11 +5,26 @@ /** * 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; - protected final Map> propertyMap = new HashMap<>(); + protected final Map> propertyMap; + + public GraphEntity() { + propertyMap = new HashMap<>(); + } + + /** + * Use this constructor to reduce memory allocations + * when properties are added to the edge + * @param propertiesCapacity preallocate the capacity for the properties + */ + public GraphEntity(int propertiesCapacity) { + propertyMap = new HashMap<>(propertiesCapacity); + } /** * @return entity 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 36cf9230de..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,11 +6,30 @@ /** * * 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 - private final List labels = new ArrayList<>(); + private final List labels; + + public Node() { + super(); + labels = new ArrayList<>(); + } + + /** + * Use this constructor to reduce memory allocations + * when labels or properties are added to the node + * @param labelsCapacity preallocate the capacity for the node labels + * @param propertiesCapacity preallocate the capacity for the properties + */ + public Node(int labelsCapacity, int propertiesCapacity) { + super(propertiesCapacity); + this.labels = new ArrayList<>(labelsCapacity); + } + /** * @param label - a label to be add 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 9eae0ef699..1f23ad978f 100644 --- a/src/main/java/redis/clients/jedis/graph/entities/Property.java +++ b/src/main/java/redis/clients/jedis/graph/entities/Property.java @@ -3,10 +3,10 @@ import java.util.Objects; /** - * A Graph entity property. Has a name, type, and value - * - * @param + * A Graph entity property. Has a name, type, and value. + * @deprecated Redis Graph support is deprecated. */ +@Deprecated public class Property { private final String name; @@ -48,7 +48,7 @@ public int hashCode() { /** * Default toString implementation * - * @return + * @return the String */ @Override public String toString() { diff --git a/src/main/java/redis/clients/jedis/graph/entities/package-info.java b/src/main/java/redis/clients/jedis/graph/entities/package-info.java new file mode 100644 index 0000000000..6e90d67072 --- /dev/null +++ b/src/main/java/redis/clients/jedis/graph/entities/package-info.java @@ -0,0 +1,4 @@ +/** + * This package contains the classes representing the entities of RedisGraph module. + */ +package redis.clients.jedis.graph.entities; diff --git a/src/main/java/redis/clients/jedis/graph/package-info.java b/src/main/java/redis/clients/jedis/graph/package-info.java new file mode 100644 index 0000000000..36842023cc --- /dev/null +++ b/src/main/java/redis/clients/jedis/graph/package-info.java @@ -0,0 +1,4 @@ +/** + * This package contains the classes and interfaces related to RedisGraph module. + */ +package redis.clients.jedis.graph; 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 new file mode 100644 index 0000000000..e4c00f7045 --- /dev/null +++ b/src/main/java/redis/clients/jedis/json/JsonBuilderFactory.java @@ -0,0 +1,144 @@ +package redis.clients.jedis.json; + +import static redis.clients.jedis.BuilderFactory.STRING; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import org.json.JSONArray; +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 { + + public static final Builder> JSON_TYPE = new Builder>() { + @Override + public Class build(Object data) { + if (data == null) return null; + String str = STRING.build(data); + switch (str) { + case "null": + return null; + case "boolean": + return boolean.class; + case "integer": + return int.class; + case "number": + return float.class; + case "string": + return String.class; + case "object": + return Object.class; + case "array": + return List.class; + default: + throw new JedisException("Unknown type: " + str); + } + } + + @Override + public String toString() { + return "Class"; + } + }; + + public static final Builder>> JSON_TYPE_LIST = new Builder>>() { + @Override + public List> build(Object data) { + List list = (List) data; + List> classes = new ArrayList<>(list.size()); + for (Object elem : list) { + try { + classes.add(JSON_TYPE.build(elem)); + } catch (JedisException je) { + classes.add(null); + } + } + return classes; + } + }; + + 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) { + if (data == null) { + return null; + } + + if (!(data instanceof byte[])) { + return data; + } + String str = STRING.build(data); + if (str.charAt(0) == '{') { + try { + return new JSONObject(str); + } catch (Exception ex) { + } + } else if (str.charAt(0) == '[') { + try { + return new JSONArray(str); + } catch (Exception ex) { + } + } + return str; + } + }; + + public static final Builder JSON_ARRAY = new Builder() { + @Override + public JSONArray build(Object data) { + if (data == null) { + return null; + } + String str = STRING.build(data); + try { + return new JSONArray(str); + } catch (JSONException ex) { // This is not necessary but we are doing this + // just to make it safe for com.vaadin.external.google:android-json library + throw new JedisException(ex); + } + } + }; + + 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) { + if (data == null) { + return null; + } + List list = (List) data; + return list.stream().map(o -> JSON_ARRAY.build(o)).collect(Collectors.toList()); + } + }; + + private JsonBuilderFactory() { + throw new InstantiationError("Must not instantiate this class"); + } +} 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 0b7b434e76..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"), @@ -22,7 +23,10 @@ public enum JsonCommand implements ProtocolCommand { ARRTRIM("JSON.ARRTRIM"), CLEAR("JSON.CLEAR"), TOGGLE("JSON.TOGGLE"), - DEBUG("JSON.DEBUG"); + OBJKEYS("JSON.OBJKEYS"), + OBJLEN("JSON.OBJLEN"), + DEBUG("JSON.DEBUG"), + RESP("JSON.RESP"); private final byte[] raw; 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 6889176129..0000000000 --- a/src/main/java/redis/clients/jedis/json/RedisJsonCommands.java +++ /dev/null @@ -1,157 +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 jsonDebugMemory(String key); - - List jsonDebugMemory(String key, Path2 path); - - long jsonDebugMemory(String key, Path 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 e65f914761..0000000000 --- a/src/main/java/redis/clients/jedis/json/RedisJsonPipelineCommands.java +++ /dev/null @@ -1,149 +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> 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/json/package-info.java b/src/main/java/redis/clients/jedis/json/package-info.java index 7b19d4b471..d3d453585f 100644 --- a/src/main/java/redis/clients/jedis/json/package-info.java +++ b/src/main/java/redis/clients/jedis/json/package-info.java @@ -1,4 +1,4 @@ -/* - * This package contains the classes related to RedisJSON module. +/** + * This package contains the classes and interfaces related to RedisJSON module. */ package redis.clients.jedis.json; diff --git a/src/main/java/redis/clients/jedis/params/BitPosParams.java b/src/main/java/redis/clients/jedis/params/BitPosParams.java index 920eaa1562..dc9d3ceea1 100644 --- a/src/main/java/redis/clients/jedis/params/BitPosParams.java +++ b/src/main/java/redis/clients/jedis/params/BitPosParams.java @@ -1,30 +1,65 @@ package redis.clients.jedis.params; -import java.util.ArrayList; -import java.util.List; import redis.clients.jedis.CommandArguments; -import redis.clients.jedis.Protocol; +import redis.clients.jedis.args.BitCountOption; public class BitPosParams implements IParams { - private List params = new ArrayList<>(); + + private Long start; + private Long end; + private BitCountOption modifier; public BitPosParams() { } + // TODO: deprecate ?? public BitPosParams(long start) { - params.add(Protocol.toByteArray(start)); + this.start = start; } + // TODO: deprecate ?? public BitPosParams(long start, long end) { this(start); - params.add(Protocol.toByteArray(end)); + this.end = end; + } + + public static BitPosParams bitPosParams() { + return new BitPosParams(); + } + + public BitPosParams start(long start) { + this.start = 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; } @Override public void addParams(CommandArguments args) { - for (byte[] param : params) { - args.add(param); + if (start != null) { + args.add(start); + if (end != null) { + args.add(end); + if (modifier != null) { + args.add(modifier); + } + } } } } 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 112c9a6a41..113624af93 100644 --- a/src/main/java/redis/clients/jedis/params/GeoRadiusParam.java +++ b/src/main/java/redis/clients/jedis/params/GeoRadiusParam.java @@ -1,14 +1,8 @@ package redis.clients.jedis.params; -import static redis.clients.jedis.Protocol.Keyword.ASC; -import static redis.clients.jedis.Protocol.Keyword.COUNT; -import static redis.clients.jedis.Protocol.Keyword.DESC; -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 { @@ -18,8 +12,7 @@ public class GeoRadiusParam implements IParams { private Integer count = null; private boolean any = false; - private boolean asc = false; - private boolean desc = false; + private SortingOrder sortingOrder = null; public GeoRadiusParam() { } @@ -44,30 +37,34 @@ public GeoRadiusParam withHash() { } public GeoRadiusParam sortAscending() { - asc = true; - return this; + return sortingOrder(SortingOrder.ASC); } public GeoRadiusParam sortDescending() { - desc = true; + return sortingOrder(SortingOrder.DESC); + } + + public GeoRadiusParam sortingOrder(SortingOrder order) { + this.sortingOrder = order; return this; } 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; } @@ -75,26 +72,24 @@ 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); } } - if (asc) { - args.add(ASC); - } else if (desc) { - args.add(DESC); + if (sortingOrder != null) { + args.add(sortingOrder); } } } 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 457b0e7504..9c12269c6b 100644 --- a/src/main/java/redis/clients/jedis/params/GeoSearchParam.java +++ b/src/main/java/redis/clients/jedis/params/GeoSearchParam.java @@ -1,22 +1,13 @@ package redis.clients.jedis.params; -import static redis.clients.jedis.Protocol.Keyword.ANY; -import static redis.clients.jedis.Protocol.Keyword.ASC; -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.DESC; -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; public class GeoSearchParam implements IParams { + private boolean fromMember = false; private boolean fromLonLat = false; private String member; @@ -35,8 +26,7 @@ public class GeoSearchParam implements IParams { private Integer count = null; private boolean any = false; - private boolean asc = false; - private boolean desc = false; + private SortingOrder sortingOrder = null; public GeoSearchParam() { } @@ -92,72 +82,71 @@ public GeoSearchParam withHash() { } public GeoSearchParam asc() { - asc = true; - return this; + return sortingOrder(SortingOrder.ASC); } public GeoSearchParam desc() { - desc = true; + return sortingOrder(SortingOrder.DESC); + } + + public GeoSearchParam sortingOrder(SortingOrder order) { + sortingOrder = order; return this; } 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); } } - if (asc) { - args.add(ASC); - } else if (desc) { - args.add(DESC); + if (sortingOrder != null) { + args.add(sortingOrder); } } } 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 new file mode 100644 index 0000000000..9866d8f4dc --- /dev/null +++ b/src/main/java/redis/clients/jedis/params/ModuleLoadExParams.java @@ -0,0 +1,41 @@ +package redis.clients.jedis.params; + +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 { + + private final List> configs = new ArrayList<>(); + private final List args = new ArrayList<>(); + + public ModuleLoadExParams() { + } + + public ModuleLoadExParams moduleLoadexParams() { + return new ModuleLoadExParams(); + } + + public ModuleLoadExParams config(String name, String value) { + this.configs.add(KeyValue.of(name, value)); + return this; + } + + public ModuleLoadExParams arg(String arg) { + this.args.add(arg); + return this; + } + + @Override + public void addParams(CommandArguments args) { + + this.configs.forEach(kv -> args.add(Keyword.CONFIG).add(kv.getKey()).add(kv.getValue())); + + if (!this.args.isEmpty()) { + 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 5e3627cc10..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,113 +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 */ - 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 eb44207d2a..6762acf301 100644 --- a/src/main/java/redis/clients/jedis/params/SortingParams.java +++ b/src/main/java/redis/clients/jedis/params/SortingParams.java @@ -1,13 +1,5 @@ package redis.clients.jedis.params; -import static redis.clients.jedis.Protocol.Keyword.ALPHA; -import static redis.clients.jedis.Protocol.Keyword.ASC; -import static redis.clients.jedis.Protocol.Keyword.BY; -import static redis.clients.jedis.Protocol.Keyword.DESC; -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; @@ -15,13 +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,22 +61,17 @@ 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 */ public SortingParams desc() { - params.add(DESC.getRaw()); - return this; + return sortingOrder(SortingOrder.DESC); } /** @@ -88,7 +79,16 @@ public SortingParams desc() { * @return the SortingParams Object */ public SortingParams asc() { - params.add(ASC.getRaw()); + return sortingOrder(SortingOrder.ASC); + } + + /** + * Get by the Sorting Order. + * @param order the Sorting order + * @return the SortingParams object + */ + public SortingParams sortingOrder(SortingOrder order) { + params.add(order.getRaw()); return this; } @@ -99,9 +99,9 @@ public SortingParams asc() { * @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; } @@ -111,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; } @@ -131,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; } @@ -153,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; @@ -161,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 d088df548a..6d5b5a411d 100644 --- a/src/main/java/redis/clients/jedis/params/ZIncrByParams.java +++ b/src/main/java/redis/clients/jedis/params/ZIncrByParams.java @@ -1,26 +1,21 @@ 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 Redis has INCR parameter for ZADD.
+ * Parameters for ZINCRBY commands. In fact, Redis doesn't have parameters for ZINCRBY. Instead + * Redis has INCR parameter for ZADD. + *

* When users call ZADD with INCR option, its restriction (only one member) and return type is same - * to ZINCRBY.
- * Document page for ZADD also describes INCR option to act like ZINCRBY.
- * http://redis.io/commands/zadd
- *
- * So we decided to wrap "ZADD with INCR option" to ZINCRBY.
- * https://github.com/xetorthio/jedis/issues/1067
- *
+ * to ZINCRBY. Document page for ZADD also describes INCR option to act like ZINCRBY. So we decided + * to wrap "ZADD with INCR option" to ZINCRBY. + *

* 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() { } @@ -34,7 +29,7 @@ public static ZIncrByParams zIncrByParams() { * @return ZIncrByParams */ public ZIncrByParams nx() { - addParam(NX); + this.existance = Keyword.NX; return this; } @@ -43,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/params/package-info.java b/src/main/java/redis/clients/jedis/params/package-info.java index 3127f0c062..bb7172480c 100644 --- a/src/main/java/redis/clients/jedis/params/package-info.java +++ b/src/main/java/redis/clients/jedis/params/package-info.java @@ -1,4 +1,4 @@ -/* - * This package contains the classes that represent optional parameters of Redis commands. +/** + * This package contains the classes that represent optional parameters of core Redis commands. */ package redis.clients.jedis.params; diff --git a/src/main/java/redis/clients/jedis/providers/ClusterConnectionProvider.java b/src/main/java/redis/clients/jedis/providers/ClusterConnectionProvider.java index 1fc0138e30..4c47f2094b 100644 --- a/src/main/java/redis/clients/jedis/providers/ClusterConnectionProvider.java +++ b/src/main/java/redis/clients/jedis/providers/ClusterConnectionProvider.java @@ -15,11 +15,12 @@ import redis.clients.jedis.ConnectionPool; import redis.clients.jedis.JedisClusterInfoCache; import redis.clients.jedis.exceptions.JedisClusterOperationException; -import redis.clients.jedis.exceptions.JedisConnectionException; import redis.clients.jedis.exceptions.JedisException; public class ClusterConnectionProvider implements ConnectionProvider { + private static final String INIT_NO_ERROR_PROPERTY = "jedis.cluster.initNoError"; + protected final JedisClusterInfoCache cache; public ClusterConnectionProvider(Set clusterNodes, JedisClientConfig clientConfig) { @@ -34,19 +35,33 @@ public ClusterConnectionProvider(Set clusterNodes, JedisClientConfi } private void initializeSlotsCache(Set startNodes, JedisClientConfig clientConfig) { + if (startNodes.isEmpty()) { + throw new JedisClusterOperationException("No nodes to initialize cluster slots cache."); + } + ArrayList startNodeList = new ArrayList<>(startNodes); Collections.shuffle(startNodeList); + JedisException firstException = null; for (HostAndPort hostAndPort : startNodeList) { try (Connection jedis = new Connection(hostAndPort, clientConfig)) { cache.discoverClusterNodesAndSlots(jedis); return; - } catch (JedisConnectionException e) { + } catch (JedisException e) { + if (firstException == null) { + firstException = e; + } // try next nodes } } - throw new JedisClusterOperationException("Could not initialize cluster slots cache."); + if (System.getProperty(INIT_NO_ERROR_PROPERTY) != null) { + return; + } + JedisClusterOperationException uninitializedException + = new JedisClusterOperationException("Could not initialize cluster slots cache."); + uninitializedException.addSuppressed(firstException); + throw uninitializedException; } @Override @@ -135,4 +150,9 @@ public Connection getConnectionFromSlot(int slot) { } } } + + @Override + public Map getConnectionMap() { + return Collections.unmodifiableMap(getNodes()); + } } diff --git a/src/main/java/redis/clients/jedis/providers/ConnectionProvider.java b/src/main/java/redis/clients/jedis/providers/ConnectionProvider.java index 8efafac33a..48543dd5cb 100644 --- a/src/main/java/redis/clients/jedis/providers/ConnectionProvider.java +++ b/src/main/java/redis/clients/jedis/providers/ConnectionProvider.java @@ -1,5 +1,7 @@ package redis.clients.jedis.providers; +import java.util.Collections; +import java.util.Map; import redis.clients.jedis.CommandArguments; import redis.clients.jedis.Connection; @@ -8,4 +10,9 @@ public interface ConnectionProvider extends AutoCloseable { Connection getConnection(); Connection getConnection(CommandArguments args); + + default Map getConnectionMap() { + final Connection c = getConnection(); + return Collections.singletonMap(c.toString(), c); + } } 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/PooledConnectionProvider.java b/src/main/java/redis/clients/jedis/providers/PooledConnectionProvider.java index e14db49471..f7b90e2953 100644 --- a/src/main/java/redis/clients/jedis/providers/PooledConnectionProvider.java +++ b/src/main/java/redis/clients/jedis/providers/PooledConnectionProvider.java @@ -1,5 +1,7 @@ package redis.clients.jedis.providers; +import java.util.Collections; +import java.util.Map; import org.apache.commons.pool2.PooledObjectFactory; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; @@ -14,21 +16,33 @@ public class PooledConnectionProvider implements ConnectionProvider { private final Pool pool; + private Object connectionMapKey = ""; public PooledConnectionProvider(HostAndPort hostAndPort) { this(new ConnectionFactory(hostAndPort)); + this.connectionMapKey = hostAndPort; } public PooledConnectionProvider(HostAndPort hostAndPort, JedisClientConfig clientConfig) { - this(new ConnectionFactory(hostAndPort, clientConfig)); + this(new ConnectionPool(hostAndPort, clientConfig)); + this.connectionMapKey = hostAndPort; + } + + public PooledConnectionProvider(HostAndPort hostAndPort, JedisClientConfig clientConfig, + GenericObjectPoolConfig poolConfig) { + this(new ConnectionFactory(hostAndPort, clientConfig), poolConfig); + this.connectionMapKey = hostAndPort; } public PooledConnectionProvider(PooledObjectFactory factory) { - this(factory, new GenericObjectPoolConfig<>()); + this(new ConnectionPool(factory)); + this.connectionMapKey = factory; } - public PooledConnectionProvider(PooledObjectFactory factory, GenericObjectPoolConfig poolConfig) { + public PooledConnectionProvider(PooledObjectFactory factory, + GenericObjectPoolConfig poolConfig) { this(new ConnectionPool(factory, poolConfig)); + this.connectionMapKey = factory; } private PooledConnectionProvider(Pool pool) { @@ -53,4 +67,9 @@ public Connection getConnection() { public Connection getConnection(CommandArguments args) { return pool.getResource(); } + + @Override + public Map> getConnectionMap() { + return Collections.singletonMap(connectionMapKey, pool); + } } diff --git a/src/main/java/redis/clients/jedis/providers/SentineledConnectionProvider.java b/src/main/java/redis/clients/jedis/providers/SentineledConnectionProvider.java new file mode 100644 index 0000000000..5058f07179 --- /dev/null +++ b/src/main/java/redis/clients/jedis/providers/SentineledConnectionProvider.java @@ -0,0 +1,280 @@ +package redis.clients.jedis.providers; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.Connection; +import redis.clients.jedis.ConnectionPool; +import redis.clients.jedis.HostAndPort; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisClientConfig; +import redis.clients.jedis.JedisPubSub; +import redis.clients.jedis.exceptions.JedisConnectionException; +import redis.clients.jedis.exceptions.JedisException; +import redis.clients.jedis.util.IOUtils; + +public class SentineledConnectionProvider implements ConnectionProvider { + + private static final Logger LOG = LoggerFactory.getLogger(SentineledConnectionProvider.class); + + protected static final long DEFAULT_SUBSCRIBE_RETRY_WAIT_TIME_MILLIS = 5000; + + private volatile HostAndPort currentMaster; + + private volatile ConnectionPool pool; + + private final String masterName; + + private final JedisClientConfig masterClientConfig; + + private final GenericObjectPoolConfig masterPoolConfig; + + protected final Collection sentinelListeners = new ArrayList<>(); + + private final JedisClientConfig sentinelClientConfig; + + private final long subscribeRetryWaitTimeMillis; + + private final Object initPoolLock = new Object(); + + public SentineledConnectionProvider(String masterName, final JedisClientConfig masterClientConfig, + Set sentinels, final JedisClientConfig sentinelClientConfig) { + this(masterName, masterClientConfig, /*poolConfig*/ null, sentinels, sentinelClientConfig); + } + + public SentineledConnectionProvider(String masterName, final JedisClientConfig masterClientConfig, + final GenericObjectPoolConfig poolConfig, + Set sentinels, final JedisClientConfig sentinelClientConfig) { + this(masterName, masterClientConfig, poolConfig, sentinels, sentinelClientConfig, + DEFAULT_SUBSCRIBE_RETRY_WAIT_TIME_MILLIS); + } + + public SentineledConnectionProvider(String masterName, final JedisClientConfig masterClientConfig, + final GenericObjectPoolConfig poolConfig, + Set sentinels, final JedisClientConfig sentinelClientConfig, + final long subscribeRetryWaitTimeMillis) { + + this.masterName = masterName; + this.masterClientConfig = masterClientConfig; + this.masterPoolConfig = poolConfig; + + this.sentinelClientConfig = sentinelClientConfig; + this.subscribeRetryWaitTimeMillis = subscribeRetryWaitTimeMillis; + + HostAndPort master = initSentinels(sentinels); + initMaster(master); + } + + @Override + public Connection getConnection() { + return pool.getResource(); + } + + @Override + public Connection getConnection(CommandArguments args) { + return pool.getResource(); + } + + @Override + public void close() { + sentinelListeners.forEach(SentinelListener::shutdown); + + pool.close(); + } + + public HostAndPort getCurrentMaster() { + return currentMaster; + } + + private void initMaster(HostAndPort master) { + synchronized (initPoolLock) { + if (!master.equals(currentMaster)) { + currentMaster = master; + + ConnectionPool newPool = masterPoolConfig != null + ? new ConnectionPool(currentMaster, masterClientConfig, masterPoolConfig) + : new ConnectionPool(currentMaster, masterClientConfig); + + ConnectionPool existingPool = pool; + pool = newPool; + LOG.info("Created connection pool to master at {}.", master); + + if (existingPool != null) { + // although we clear the pool, we still have to check the returned object in getResource, + // this call only clears idle instances, not borrowed instances + // existingPool.clear(); // necessary?? + existingPool.close(); + } + } + } + } + + private HostAndPort initSentinels(Set sentinels) { + + HostAndPort master = null; + boolean sentinelAvailable = false; + + LOG.debug("Trying to find master from available sentinels..."); + + for (HostAndPort sentinel : sentinels) { + + LOG.debug("Connecting to Sentinel {}...", sentinel); + + try (Jedis jedis = new Jedis(sentinel, sentinelClientConfig)) { + + List masterAddr = jedis.sentinelGetMasterAddrByName(masterName); + + // connected to sentinel... + sentinelAvailable = true; + + if (masterAddr == null || masterAddr.size() != 2) { + LOG.warn("Sentinel {} is not monitoring master {}.", sentinel, masterName); + continue; + } + + master = toHostAndPort(masterAddr); + LOG.debug("Redis master reported at {}.", master); + break; + } catch (JedisException e) { + // resolves #1036, it should handle JedisException there's another chance + // of raising JedisDataException + LOG.warn("Could not get master address from {}.", sentinel, e); + } + } + + if (master == null) { + if (sentinelAvailable) { + // can connect to sentinel, but master name seems to not monitored + throw new JedisException( + "Can connect to sentinel, but " + masterName + " seems to be not monitored."); + } else { + throw new JedisConnectionException( + "All sentinels down, cannot determine where " + masterName + " is running."); + } + } + + LOG.info("Redis master running at {}. Starting sentinel listeners...", master); + + for (HostAndPort sentinel : sentinels) { + + SentinelListener listener = new SentinelListener(sentinel); + // whether SentinelListener threads are alive or not, process can be stopped + listener.setDaemon(true); + sentinelListeners.add(listener); + listener.start(); + } + + return master; + } + + /** + * Must be of size 2. + */ + private static HostAndPort toHostAndPort(List masterAddr) { + return toHostAndPort(masterAddr.get(0), masterAddr.get(1)); + } + + private static HostAndPort toHostAndPort(String hostStr, String portStr) { + return new HostAndPort(hostStr, Integer.parseInt(portStr)); + } + + protected class SentinelListener extends Thread { + + protected final HostAndPort node; + protected volatile Jedis sentinelJedis; + protected AtomicBoolean running = new AtomicBoolean(false); + + public SentinelListener(HostAndPort node) { + super(String.format("%s-SentinelListener-[%s]", masterName, node.toString())); + this.node = node; + } + + @Override + public void run() { + + running.set(true); + + while (running.get()) { + + try { + // double check that it is not being shutdown + if (!running.get()) { + break; + } + + sentinelJedis = new Jedis(node, sentinelClientConfig); + + // code for active refresh + List masterAddr = sentinelJedis.sentinelGetMasterAddrByName(masterName); + if (masterAddr == null || masterAddr.size() != 2) { + LOG.warn("Can not get master {} address. Sentinel: {}.", masterName, node); + } else { + initMaster(toHostAndPort(masterAddr)); + } + + sentinelJedis.subscribe(new JedisPubSub() { + @Override + public void onMessage(String channel, String message) { + LOG.debug("Sentinel {} published: {}.", node, message); + + String[] switchMasterMsg = message.split(" "); + + if (switchMasterMsg.length > 3) { + + if (masterName.equals(switchMasterMsg[0])) { + initMaster(toHostAndPort(switchMasterMsg[3], switchMasterMsg[4])); + } else { + LOG.debug( + "Ignoring message on +switch-master for master {}. Our master is {}.", + switchMasterMsg[0], masterName); + } + + } else { + LOG.error("Invalid message received on sentinel {} on channel +switch-master: {}.", + node, message); + } + } + }, "+switch-master"); + + } catch (JedisException e) { + + if (running.get()) { + LOG.error("Lost connection to sentinel {}. Sleeping {}ms and retrying.", node, + subscribeRetryWaitTimeMillis, e); + try { + Thread.sleep(subscribeRetryWaitTimeMillis); + } catch (InterruptedException se) { + LOG.error("Sleep interrupted.", se); + } + } else { + LOG.debug("Unsubscribing from sentinel {}.", node); + } + } finally { + IOUtils.closeQuietly(sentinelJedis); + } + } + } + + // must not throw exception + public void shutdown() { + try { + LOG.debug("Shutting down listener on {}.", node); + running.set(false); + // This isn't good, the Jedis object is not thread safe + if (sentinelJedis != null) { + sentinelJedis.close(); + } + } catch (RuntimeException e) { + LOG.error("Error while shutting down.", e); + } + } + } +} diff --git a/src/main/java/redis/clients/jedis/providers/ShardedConnectionProvider.java b/src/main/java/redis/clients/jedis/providers/ShardedConnectionProvider.java index b1240a0eb5..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<>(); @@ -42,7 +46,7 @@ public ShardedConnectionProvider(List shards, JedisClientConfig cli public ShardedConnectionProvider(List shards, JedisClientConfig clientConfig, Hashing algo) { - this(shards, clientConfig, new GenericObjectPoolConfig(), algo); + this(shards, clientConfig, null, algo); } public ShardedConnectionProvider(List shards, JedisClientConfig clientConfig, @@ -69,7 +73,8 @@ private ConnectionPool setupNodeIfNotExist(final HostAndPort node) { ConnectionPool existingPool = resources.get(nodeKey); if (existingPool != null) return existingPool; - ConnectionPool nodePool = new ConnectionPool(node, clientConfig, poolConfig); + ConnectionPool nodePool = poolConfig == null ? new ConnectionPool(node, clientConfig) + : new ConnectionPool(node, clientConfig, poolConfig); resources.put(nodeKey, nodePool); return nodePool; } @@ -157,4 +162,9 @@ private HostAndPort getNodeFromHash(Long hash) { } return tail.get(tail.firstKey()); } + + @Override + public Map getConnectionMap() { + return Collections.unmodifiableMap(resources); + } } diff --git a/src/main/java/redis/clients/jedis/providers/package-info.java b/src/main/java/redis/clients/jedis/providers/package-info.java new file mode 100644 index 0000000000..c2adf902ab --- /dev/null +++ b/src/main/java/redis/clients/jedis/providers/package-info.java @@ -0,0 +1,4 @@ +/** + * This package contains the implementations of ConnectionProvider interface. + */ +package redis.clients.jedis.providers; 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/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 fa8c2254d6..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 xinfo stream mystream full. - * 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 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 a574d132aa..e768b536b8 100644 --- a/src/main/java/redis/clients/jedis/resps/StreamFullInfo.java +++ b/src/main/java/redis/clients/jedis/resps/StreamFullInfo.java @@ -7,9 +7,9 @@ import java.util.Map; /** - * This class holds information about a stream info with command xinfo stream mystream full. - * They can be access via getters. For future purpose there is also {@link #getStreamFullInfo()} method - * that returns a generic {@code Map} - in case where more info is returned from the server. + * This class holds information about a stream info with command {@code xinfo stream mystream full}. + * 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 3f0a483fd8..8354c86815 100644 --- a/src/main/java/redis/clients/jedis/resps/StreamGroupFullInfo.java +++ b/src/main/java/redis/clients/jedis/resps/StreamGroupFullInfo.java @@ -7,9 +7,9 @@ import java.util.Map; /** - * This class holds information about a stream group with command xinfo stream mystream full. - * They can be access via getters. For future purpose there is also {@link #getGroupFullInfo()} 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 with command {@code xinfo stream mystream full}. + * 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/resps/package-info.java b/src/main/java/redis/clients/jedis/resps/package-info.java index d9d14080b6..58a6de80a0 100644 --- a/src/main/java/redis/clients/jedis/resps/package-info.java +++ b/src/main/java/redis/clients/jedis/resps/package-info.java @@ -1,4 +1,4 @@ -/* - * This package contains the classes that represent different Redis responses. +/** + * This package contains custom responses of core Redis commands. */ package redis.clients.jedis.resps; diff --git a/src/main/java/redis/clients/jedis/search/Document.java b/src/main/java/redis/clients/jedis/search/Document.java index 48396dcc0a..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,55 +19,67 @@ 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) { - ret.set(SafeEncoder.encode(fields.get(i)), decode ? SafeEncoder.encode(fields.get(i + 1)) : fields.get(i + 1)); + byte[] rawKey = fields.get(i); + byte[] rawValue = fields.get(i + 1); + String key = SafeEncoder.encode(rawKey); + Object value = rawValue == null ? null : decode ? SafeEncoder.encode(rawValue) : rawValue; + ret.set(key, value); } } return ret; } - public Document set(String key, Object value) { - properties.put(key, value); - return this; + /** + * @return the document's id + */ + public String getId() { + return id; + } + + /** + * @return the document's score + */ + public Double getScore() { + return score; } /** @@ -74,7 +90,7 @@ public Document set(String key, Object value) { * @return the property value */ public Object get(String key) { - return properties.get(key); + return fields.get(key); } /** @@ -85,22 +101,20 @@ public Object get(String key) { * @return the property value */ public String getString(String key) { - Object value = properties.get(key); + Object value = fields.get(key); if (value instanceof String) { return (String) value; } return value instanceof byte[] ? SafeEncoder.encode((byte[]) value) : value.toString(); } - /** - * @return the document's score - */ - public double getScore() { - return score; + public boolean hasProperty(String key) { + return fields.containsKey(key); } - public byte[] getPayload() { - return payload; + public Document set(String key, Object value) { + fields.put(key, value); + return this; } /** @@ -110,25 +124,46 @@ public byte[] getPayload() { * @return the document itself */ public Document setScore(float score) { - this.score = score; + this.score = (double) score; return this; } - /** - * @return the document's id - */ - public String getId() { - return id; - } - - public boolean hasProperty(String key) { - return properties.containsKey(key); - } - @Override public String toString() { return "id:" + this.getId() + ", score: " + this.getScore() + - ", payload:" + SafeEncoder.encode(this.getPayload()) + ", properties:" + this.getProperties(); } + + static Builder 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/FTCreateParams.java b/src/main/java/redis/clients/jedis/search/FTCreateParams.java new file mode 100644 index 0000000000..5ea17e7ab0 --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/FTCreateParams.java @@ -0,0 +1,256 @@ +package redis.clients.jedis.search; + +import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.params.IParams; + +public class FTCreateParams implements IParams { + + private IndexDataType dataType; + private Collection prefix; + private String filter; + private String language; + private String languageField; + private Double score; + private String scoreField; + private boolean maxTextFields; + private boolean noOffsets; + private Long temporary; + private boolean noHL; + private boolean noFields; + private boolean noFreqs; + private Collection stopwords; + private boolean skipInitialScan; + + public FTCreateParams() { + } + + public static FTCreateParams createParams() { + return new FTCreateParams(); + } + + /** + * Currently supports HASH (default) and JSON. To index JSON, you must have the RedisJSON module + * installed. + */ + public FTCreateParams on(IndexDataType dataType) { + this.dataType = dataType; + return this; + } + + /** + * Tells the index which keys it should index. You can add several prefixes to index. + */ + public FTCreateParams prefix(String... prefixes) { + if (this.prefix == null) { + this.prefix = new ArrayList<>(prefixes.length); + } + Arrays.stream(prefixes).forEach(p -> this.prefix.add(p)); + return this; + } + + /** + * This method can be chained to add multiple prefixes. + * + * @see FTCreateParams#prefix(java.lang.String...) + */ + public FTCreateParams addPrefix(String prefix) { + if (this.prefix == null) { + this.prefix = new ArrayList<>(); + } + this.prefix.add(prefix); + return this; + } + + /** + * A filter expression with the full RediSearch aggregation expression language. + */ + public FTCreateParams filter(String filter) { + this.filter = filter; + return this; + } + + /** + * Indicates the default language for documents in the index. + */ + public FTCreateParams language(String defaultLanguage) { + this.language = defaultLanguage; + return this; + } + + /** + * Document attribute set as the document language. + */ + public FTCreateParams languageField(String languageAttribute) { + this.languageField = languageAttribute; + return this; + } + + /** + * Default score for documents in the index. + */ + public FTCreateParams score(double defaultScore) { + this.score = defaultScore; + return this; + } + + /** + * Document attribute that you use as the document rank based on the user ranking. + * Ranking must be between 0.0 and 1.0. + */ + public FTCreateParams scoreField(String scoreField) { + this.scoreField = scoreField; + return this; + } + + /** + * Forces RediSearch to encode indexes as if there were more than 32 text attributes. + */ + public FTCreateParams maxTextFields() { + this.maxTextFields = true; + return this; + } + + /** + * Does not store term offsets for documents. It saves memory, but does not allow exact searches + * or highlighting. + */ + public FTCreateParams noOffsets() { + this.noOffsets = true; + return this; + } + + /** + * Creates a lightweight temporary index that expires after a specified period of inactivity. + */ + public FTCreateParams temporary(long seconds) { + this.temporary = seconds; + return this; + } + + /** + * Conserves storage space and memory by disabling highlighting support. + */ + public FTCreateParams noHL() { + this.noHL = true; + return this; + } + + /** + * @see FTCreateParams#noHL() + */ + public FTCreateParams noHighlights() { + return noHL(); + } + + /** + * Does not store attribute bits for each term. It saves memory, but it does not allow filtering + * by specific attributes. + */ + public FTCreateParams noFields() { + this.noFields = true; + return this; + } + + /** + * Avoids saving the term frequencies in the index. It saves memory, but does not allow sorting + * based on the frequencies of a given term within the document. + */ + public FTCreateParams noFreqs() { + this.noFreqs = true; + return this; + } + + /** + * Sets the index with a custom stopword list, to be ignored during indexing and search time. + */ + public FTCreateParams stopwords(String... stopwords) { + this.stopwords = Arrays.asList(stopwords); + return this; + } + + /** + * The index does not have stopwords, not even the default ones. + */ + public FTCreateParams noStopwords() { + this.stopwords = Collections.emptyList(); + return this; + } + + /** + * Does not scan and index. + */ + public FTCreateParams skipInitialScan() { + this.skipInitialScan = true; + return this; + } + + @Override + public void addParams(CommandArguments args) { + + if (dataType != null) { + args.add(ON).add(dataType); + } + + if (prefix != null) { + args.add(PREFIX).add(prefix.size()).addObjects(prefix); + } + + if (filter != null) { + args.add(FILTER).add(filter); + } + + if (language != null) { + args.add(LANGUAGE).add(language); + } + if (languageField != null) { + args.add(LANGUAGE_FIELD).add(languageField); + } + + if (score != null) { + args.add(SCORE).add(score); + } + if (scoreField != null) { + args.add(SCORE_FIELD).add(scoreField); + } + + if (maxTextFields) { + args.add(MAXTEXTFIELDS); + } + + if (noOffsets) { + args.add(NOOFFSETS); + } + + if (temporary != null) { + args.add(TEMPORARY).add(temporary); + } + + if (noHL) { + args.add(NOHL); + } + + if (noFields) { + args.add(NOFIELDS); + } + + if (noFreqs) { + args.add(NOFREQS); + } + + if (stopwords != null) { + args.add(STOPWORDS).add(stopwords.size()); + stopwords.forEach(w -> args.add(w)); + } + + if (skipInitialScan) { + args.add(SKIPINITIALSCAN); + } + } +} diff --git a/src/main/java/redis/clients/jedis/search/FTProfileParams.java b/src/main/java/redis/clients/jedis/search/FTProfileParams.java new file mode 100644 index 0000000000..77bd43fc51 --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/FTProfileParams.java @@ -0,0 +1,34 @@ +package redis.clients.jedis.search; + +import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.LIMITED; + +import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.params.IParams; + +public class FTProfileParams implements IParams { + + private boolean limited; + + public FTProfileParams() { + } + + public static FTProfileParams profileParams() { + return new FTProfileParams(); + } + + /** + * Removes details of {@code reader} iterator. + */ + public FTProfileParams limited() { + this.limited = true; + return this; + } + + @Override + public void addParams(CommandArguments args) { + + if (limited) { + args.add(LIMITED); + } + } +} diff --git a/src/main/java/redis/clients/jedis/search/FTSearchParams.java b/src/main/java/redis/clients/jedis/search/FTSearchParams.java new file mode 100644 index 0000000000..1bb5597085 --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/FTSearchParams.java @@ -0,0 +1,602 @@ +package redis.clients.jedis.search; + +import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.*; + +import java.util.*; + +import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.Protocol; +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 + */ +public class FTSearchParams implements IParams { + + private boolean noContent = false; + private boolean verbatim = false; + private boolean noStopwords = false; + private boolean withScores = false; + private final List filters = new LinkedList<>(); + private Collection inKeys; + private Collection inFields; + private Collection returnFields; + private Collection returnFieldNames; + private boolean summarize; + private SummarizeParams summarizeParams; + private boolean highlight; + private HighlightParams highlightParams; + private Integer slop; + private Long timeout; + private boolean inOrder; + private String language; + private String expander; + private String scorer; + // private boolean explainScore; // TODO + private String sortBy; + private SortingOrder sortOrder; + private int[] limit; + private Map params; + private Integer dialect; + + public FTSearchParams() { + } + + public static FTSearchParams searchParams() { + return new FTSearchParams(); + } + + @Override + public void addParams(CommandArguments args) { + + if (noContent) { + args.add(NOCONTENT); + } + if (verbatim) { + args.add(VERBATIM); + } + if (noStopwords) { + args.add(NOSTOPWORDS); + } + if (withScores) { + args.add(WITHSCORES); + } + + if (!filters.isEmpty()) { + filters.forEach(filter -> filter.addParams(args)); + } + + if (inKeys != null && !inKeys.isEmpty()) { + args.add(INKEYS).add(inKeys.size()).addObjects(inKeys); + } + + if (inFields != null && !inFields.isEmpty()) { + args.add(INFIELDS).add(inFields.size()).addObjects(inFields); + } + + if (returnFieldNames != null && !returnFieldNames.isEmpty()) { + args.add(RETURN); + LazyRawable returnCountObject = new LazyRawable(); + args.add(returnCountObject); // holding a place for setting the total count later. + int returnCount = 0; + for (FieldName fn : returnFieldNames) { + returnCount += fn.addCommandArguments(args); + } + returnCountObject.setRaw(Protocol.toByteArray(returnCount)); + } else if (returnFields != null && !returnFields.isEmpty()) { + args.add(RETURN).add(returnFields.size()).addObjects(returnFields); + } + + if (summarizeParams != null) { + args.addParams(summarizeParams); + } else if (summarize) { + args.add(SUMMARIZE); + } + + if (highlightParams != null) { + args.addParams(highlightParams); + } else if (highlight) { + args.add(HIGHLIGHT); + } + + if (slop != null) { + args.add(SLOP).add(slop); + } + + if (timeout != null) { + args.add(TIMEOUT).add(timeout); + } + + if (inOrder) { + args.add(INORDER); + } + + if (language != null) { + args.add(LANGUAGE).add(language); + } + + if (expander != null) { + args.add(EXPANDER).add(expander); + } + + if (scorer != null) { + args.add(SCORER).add(scorer); + } +// +// if (explainScore) { +// args.add(EXPLAINSCORE); +// } + + if (sortBy != null) { + args.add(SORTBY).add(sortBy); + if (sortOrder != null) { + args.add(sortOrder); + } + } + + if (limit != null) { + args.add(LIMIT).add(limit[0]).add(limit[1]); + } + + if (params != null && !params.isEmpty()) { + args.add(PARAMS).add(params.size() * 2); + params.entrySet().forEach(entry -> args.add(entry.getKey()).add(entry.getValue())); + } + + if (dialect != null) { + args.add(DIALECT).add(dialect); + } + } + + /** + * Set the query not to return the contents of documents, and rather just return the ids + * + * @return the query itself + */ + public FTSearchParams noContent() { + this.noContent = true; + return this; + } + + /** + * Set the query to verbatim mode, disabling stemming and query expansion + * + * @return the query object + */ + public FTSearchParams verbatim() { + this.verbatim = true; + return this; + } + + /** + * Set the query not to filter for stopwords. In general this should not be used + * + * @return the query object + */ + public FTSearchParams noStopwords() { + this.noStopwords = true; + return this; + } + + /** + * Set the query to return a factored score for each results. This is useful to merge results from + * multiple queries. + * + * @return the query object itself + */ + public FTSearchParams withScores() { + this.withScores = true; + return this; + } + + public FTSearchParams filter(String field, double min, double max) { + return filter(new NumericFilter(field, min, max)); + } + + public FTSearchParams filter(String field, double min, boolean exclusiveMin, double max, boolean exclusiveMax) { + return filter(new NumericFilter(field, min, exclusiveMin, max, exclusiveMax)); + } + + public FTSearchParams filter(NumericFilter numericFilter) { + filters.add(numericFilter); + return this; + } + + public FTSearchParams geoFilter(String field, double lon, double lat, double radius, GeoUnit unit) { + return geoFilter(new GeoFilter(field, lon, lat, radius, unit)); + } + + public FTSearchParams geoFilter(GeoFilter geoFilter) { + filters.add(geoFilter); + return this; + } + + /** + * Limit the query to results that are limited to a specific set of keys + * + * @param keys a list of TEXT fields in the schemas + * @return the query object itself + */ + public FTSearchParams inKeys(String... keys) { + return inKeys(Arrays.asList(keys)); + } + + public FTSearchParams inKeys(Collection keys) { + this.inKeys = keys; + return this; + } + + /** + * Limit the query to results that are limited to a specific set of fields + * + * @param fields a list of TEXT fields in the schemas + * @return the query object itself + */ + public FTSearchParams inFields(String... fields) { + return inFields(Arrays.asList(fields)); + } + + public FTSearchParams inFields(Collection fields) { + if (this.inFields == null) { + this.inFields = new ArrayList<>(fields); + } else { + this.inFields.addAll(fields); + } + return this; + } + + /** + * Result's projection - the fields to return by the query + * + * @param fields a list of TEXT fields in the schemas + * @return the query object itself + */ + public FTSearchParams returnFields(String... fields) { + if (returnFieldNames != null) { + Arrays.stream(fields).forEach(f -> returnFieldNames.add(FieldName.of(f))); + } else { + if (returnFields == null) { + returnFields = new ArrayList<>(); + } + Arrays.stream(fields).forEach(f -> returnFields.add(f)); + } + return this; + } + + public FTSearchParams returnField(FieldName field) { + initReturnFieldNames(); + returnFieldNames.add(field); + return this; + } + + public FTSearchParams returnFields(FieldName... fields) { + return returnFields(Arrays.asList(fields)); + } + + public FTSearchParams returnFields(Collection fields) { + initReturnFieldNames(); + returnFieldNames.addAll(fields); + return this; + } + + private void initReturnFieldNames() { + if (returnFieldNames == null) { + returnFieldNames = new ArrayList<>(); + } + if (returnFields != null) { + returnFields.forEach(f -> returnFieldNames.add(FieldName.of(f))); + returnFields = null; + } + } + + public FTSearchParams summarize() { + this.summarize = true; + return this; + } + + public FTSearchParams summarize(SummarizeParams summarizeParams) { + this.summarizeParams = summarizeParams; + return this; + } + + public FTSearchParams highlight() { + this.highlight = true; + return this; + } + + public FTSearchParams highlight(HighlightParams highlightParams) { + this.highlightParams = highlightParams; + return this; + } + + /** + * Set the query custom scorer + *

+ * See http://redisearch.io for documentation on extending RediSearch + * + * @param scorer a custom scorer. + * + * @return the query object itself + */ + public FTSearchParams scorer(String scorer) { + this.scorer = scorer; + return this; + } +// +// public FTSearchParams explainScore() { +// this.explainScore = true; +// return this; +// } + + public FTSearchParams slop(int slop) { + this.slop = slop; + return this; + } + + public FTSearchParams timeout(long timeout) { + this.timeout = timeout; + return this; + } + + public FTSearchParams inOrder() { + this.inOrder = true; + return this; + } + + /** + * Set the query language, for stemming purposes + *

+ * See http://redisearch.io for documentation on languages and stemming + * + * @param language a language. + * + * @return the query object itself + */ + public FTSearchParams language(String language) { + this.language = language; + return this; + } + + /** + * Set the query to be sorted by a Sortable field defined in the schema + * + * @param sortBy the sorting field's name + * @param order the sorting order + * @return the query object itself + */ + public FTSearchParams sortBy(String sortBy, SortingOrder order) { + this.sortBy = sortBy; + this.sortOrder = order; + return this; + } + + /** + * Limit the results to a certain offset and limit + * + * @param offset the first result to show, zero based indexing + * @param num how many results we want to show + * @return the query itself, for builder-style syntax + */ + public FTSearchParams limit(int offset, int num) { + this.limit = new int[]{offset, num}; + return this; + } + + /** + * Parameters can be referenced in the query string by a $ , followed by the parameter name, + * e.g., $user , and each such reference in the search query to a parameter name is substituted + * by the corresponding parameter value. + * + * @param name + * @param value can be String, long or float + * @return the query object itself + */ + public FTSearchParams addParam(String name, Object value) { + if (params == null) { + params = new HashMap<>(); + } + params.put(name, value); + return this; + } + + public FTSearchParams params(Map paramValues) { + if (this.params == null) { + this.params = new HashMap<>(paramValues); + } else { + this.params.putAll(params); + } + return this; + } + + /** + * Set the dialect version to execute the query accordingly + * + * @param dialect integer + * @return the query object itself + */ + public FTSearchParams dialect(int dialect) { + this.dialect = 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; + } + + public boolean getWithScores() { + return withScores; + } + + /** + * NumericFilter wraps a range filter on a numeric field. It can be inclusive or exclusive + */ + public static class NumericFilter implements IParams { + + private final String field; + private final double min; + private final boolean exclusiveMin; + private final double max; + private final boolean exclusiveMax; + + public NumericFilter(String field, double min, double max) { + this(field, min, false, max, false); + } + + public NumericFilter(String field, double min, boolean exclusiveMin, double max, boolean exclusiveMax) { + this.field = field; + this.min = min; + this.max = max; + this.exclusiveMax = exclusiveMax; + this.exclusiveMin = exclusiveMin; + } + + @Override + public void addParams(CommandArguments args) { + args.add(FILTER).add(field) + .add(formatNum(min, exclusiveMin)) + .add(formatNum(max, exclusiveMax)); + } + + private Object formatNum(double num, boolean exclude) { + return exclude ? ("(" + num) : Protocol.toByteArray(num); + } + } + + /** + * GeoFilter encapsulates a radius filter on a geographical indexed fields + */ + public static class GeoFilter implements IParams { + + private final String field; + private final double lon; + private final double lat; + private final double radius; + private final GeoUnit unit; + + public GeoFilter(String field, double lon, double lat, double radius, GeoUnit unit) { + this.field = field; + this.lon = lon; + this.lat = lat; + this.radius = radius; + this.unit = unit; + } + + @Override + public void addParams(CommandArguments args) { + args.add(GEOFILTER).add(field) + .add(lon).add(lat) + .add(radius).add(unit); + } + } + + public static class SummarizeParams implements IParams { + + private Collection fields; + private Integer fragsNum; + private Integer fragSize; + private String separator; + + public SummarizeParams() { + } + + public SummarizeParams fields(String... fields) { + return fields(Arrays.asList(fields)); + } + + public SummarizeParams fields(Collection fields) { + this.fields = fields; + return this; + } + + public SummarizeParams fragsNum(int num) { + this.fragsNum = num; + return this; + } + + public SummarizeParams fragSize(int size) { + this.fragSize = size; + return this; + } + + public SummarizeParams separator(String separator) { + this.separator = separator; + return this; + } + + @Override + public void addParams(CommandArguments args) { + args.add(SUMMARIZE); + + if (fields != null) { + args.add(FIELDS).add(fields.size()).addObjects(fields); + } + if (fragsNum != null) { + args.add(FRAGS).add(fragsNum); + } + if (fragSize != null) { + args.add(LEN).add(fragSize); + } + if (separator != null) { + args.add(SEPARATOR).add(separator); + } + } + } + + public static SummarizeParams summarizeParams() { + return new SummarizeParams(); + } + + public static class HighlightParams implements IParams { + + private Collection fields; + private String[] tags; + + public HighlightParams() { + } + + public HighlightParams fields(String fields) { + return fields(Arrays.asList(fields)); + } + + public HighlightParams fields(Collection fields) { + this.fields = fields; + return this; + } + + public HighlightParams tags(String open, String close) { + this.tags = new String[]{open, close}; + return this; + } + + @Override + public void addParams(CommandArguments args) { + args.add(HIGHLIGHT); + + if (fields != null) { + args.add(FIELDS).add(fields.size()).addObjects(fields); + } + if (tags != null) { + args.add(TAGS).add(tags[0]).add(tags[1]); + } + } + } + + public static HighlightParams highlightParams() { + return new HighlightParams(); + } +} diff --git a/src/main/java/redis/clients/jedis/search/FTSpellCheckParams.java b/src/main/java/redis/clients/jedis/search/FTSpellCheckParams.java new file mode 100644 index 0000000000..439885a2a1 --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/FTSpellCheckParams.java @@ -0,0 +1,99 @@ +package redis.clients.jedis.search; + +import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.DIALECT; +import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.DISTANCE; +import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.EXCLUDE; +import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.INCLUDE; +import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.TERMS; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; + +import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.args.Rawable; +import redis.clients.jedis.params.IParams; +import redis.clients.jedis.util.KeyValue; + +public class FTSpellCheckParams implements IParams { + + private Collection> terms; + private Integer distance; + private Integer dialect; + + public FTSpellCheckParams() { + } + + public static FTSpellCheckParams spellCheckParams() { + return new FTSpellCheckParams(); + } + + /** + * Specifies an inclusion (INCLUDE) of a custom dictionary. + */ + public FTSpellCheckParams includeTerm(String dictionary) { + return addTerm(dictionary, INCLUDE); + } + + /** + * Specifies an exclusion (EXCLUDE) of a custom dictionary. + */ + public FTSpellCheckParams excludeTerm(String dictionary) { + return addTerm(dictionary, EXCLUDE); + } + + /** + * Specifies an inclusion (INCLUDE) or exclusion (EXCLUDE) of a custom dictionary. + */ + private FTSpellCheckParams addTerm(String dictionary, Rawable type) { + if (this.terms == null) { + this.terms = new ArrayList<>(); + } + this.terms.add(KeyValue.of(dictionary, type)); + return this; + } + + /** + * Maximum Levenshtein distance for spelling suggestions (default: 1, max: 4). + */ + public FTSpellCheckParams distance(int distance) { + this.distance = distance; + return this; + } + + /** + * Selects the dialect version under which to execute the query. + */ + public FTSpellCheckParams dialect(int dialect) { + this.dialect = 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) { + + if (terms != null) { + terms.forEach(kv -> args.add(TERMS).add(kv.getValue()).add(kv.getKey())); + } + + if (distance != null) { + args.add(DISTANCE).add(distance); + } + + if (dialect != null) { + args.add(DIALECT).add(dialect); + } + } +} diff --git a/src/main/java/redis/clients/jedis/search/FieldName.java b/src/main/java/redis/clients/jedis/search/FieldName.java index d75251a812..9a0a9329db 100644 --- a/src/main/java/redis/clients/jedis/search/FieldName.java +++ b/src/main/java/redis/clients/jedis/search/FieldName.java @@ -3,20 +3,15 @@ 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; public FieldName(String name) { - this(name, null); + this.name = name; } public FieldName(String name, String attribute) { @@ -25,40 +20,43 @@ public FieldName(String name, String attribute) { } public FieldName as(String attribute) { + if (attribute == null) { + throw new IllegalArgumentException("Setting null as field attribute is not allowed."); + } + if (this.attribute != null) { + throw new IllegalStateException("Attribute for this field is already set."); + } this.attribute = 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; } @@ -67,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/IndexDataType.java b/src/main/java/redis/clients/jedis/search/IndexDataType.java new file mode 100644 index 0000000000..9b8bcccb2f --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/IndexDataType.java @@ -0,0 +1,6 @@ +package redis.clients.jedis.search; + +public enum IndexDataType { + HASH, + JSON +} diff --git a/src/main/java/redis/clients/jedis/search/IndexDefinition.java b/src/main/java/redis/clients/jedis/search/IndexDefinition.java index 73a4f6ae8e..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,15 +89,6 @@ public IndexDefinition setScore(double score) { return this; } - public String getPayloadField() { - return payloadField; - } - - public IndexDefinition setPayloadField(String payloadField) { - this.payloadField = payloadField; - return this; - } - @Override public void addParams(CommandArguments args) { @@ -117,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)); @@ -151,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 e21588cf16..66cba96acf 100644 --- a/src/main/java/redis/clients/jedis/search/Query.java +++ b/src/main/java/redis/clients/jedis/search/Query.java @@ -7,9 +7,9 @@ import redis.clients.jedis.CommandArguments; import redis.clients.jedis.Protocol; -import redis.clients.jedis.args.Rawable; 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; /** @@ -139,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; @@ -151,14 +150,17 @@ 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; + private String _expander = null; public Query() { this("*"); @@ -189,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)); @@ -216,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)); } @@ -285,7 +279,7 @@ public void addParams(CommandArguments args) { } else if (returnFieldNames != null && returnFieldNames.length > 0) { args.add(SearchKeyword.RETURN.getRaw()); // final int returnCountIndex = args.size(); - DelayedRawable returnCountObject = new DelayedRawable(); + LazyRawable returnCountObject = new LazyRawable(); // args.add(null); // holding a place for setting the total count later. args.add(returnCountObject); // holding a place for setting the total count later. int returnCount = 0; @@ -305,23 +299,28 @@ public void addParams(CommandArguments args) { } } - if (_dialect != 0) { + if (_dialect != null) { args.add(SearchKeyword.DIALECT.getRaw()); args.add(_dialect); } - } - private static class DelayedRawable implements Rawable { + if (_slop >= 0) { + args.add(SearchKeyword.SLOP.getRaw()); + args.add(_slop); + } - private byte[] raw = null; + if (_timeout >= 0) { + args.add(SearchKeyword.TIMEOUT.getRaw()); + args.add(_timeout); + } - public void setRaw(byte[] raw) { - this.raw = raw; + if (_inOrder) { + args.add(SearchKeyword.INORDER.getRaw()); } - @Override - public byte[] getRaw() { - return raw; + if (_expander != null) { + args.add(SearchKeyword.EXPANDER.getRaw()); + args.add(SafeEncoder.encode(_expander)); } } @@ -349,12 +348,6 @@ public Query addFilter(Filter f) { return this; } - /* Set the query payload to be evaluated by the scoring function */ - public Query setPayload(byte[] payload) { - _payload = payload; - return this; - } - /** * Set the query to verbatim mode, disabling stemming and query expansion * @@ -404,21 +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 - * - */ - public Query setWithPayload() { - this._withPayloads = true; - return this; - } - /** * Set the query language, for stemming purposes *

@@ -565,4 +543,59 @@ public Query dialect(int dialect) { _dialect = 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 + * + * @param slop integer + * @return the query object itself + */ + public Query slop(int slop) { + _slop = slop; + return this; + } + + /** + * Set the timeout to execute the query accordingly + * + * @param timeout long + * @return the query object itself + */ + public Query timeout(long timeout) { + _timeout = timeout; + return this; + } + + /** + * Set the query terms appear in the same order in the document as in the query, regardless of the offsets between them + * + * @return the query object + */ + public Query setInOrder() { + this._inOrder = true; + return this; + } + + /** + * Set the query to use a custom query expander instead of the stemmer + * + * @param field the expander field's name + * @return the query object itself + */ + public Query setExpander(String field) { + _expander = field; + return this; + } } diff --git a/src/main/java/redis/clients/jedis/search/RediSearchCommands.java b/src/main/java/redis/clients/jedis/search/RediSearchCommands.java index 0321ecaadf..f361689aea 100644 --- a/src/main/java/redis/clients/jedis/search/RediSearchCommands.java +++ b/src/main/java/redis/clients/jedis/search/RediSearchCommands.java @@ -1,22 +1,66 @@ package redis.clients.jedis.search; +import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.Set; + +import redis.clients.jedis.resps.Tuple; import redis.clients.jedis.search.aggr.AggregationBuilder; import redis.clients.jedis.search.aggr.AggregationResult; +import redis.clients.jedis.search.schemafields.SchemaField; public interface RediSearchCommands { String ftCreate(String indexName, IndexOptions indexOptions, Schema schema); + default String ftCreate(String indexName, SchemaField... schemaFields) { + return ftCreate(indexName, Arrays.asList(schemaFields)); + } + + default String ftCreate(String indexName, FTCreateParams createParams, SchemaField... schemaFields) { + return ftCreate(indexName, createParams, Arrays.asList(schemaFields)); + } + + default String ftCreate(String indexName, Iterable schemaFields) { + return ftCreate(indexName, FTCreateParams.createParams(), schemaFields); + } + + String ftCreate(String indexName, FTCreateParams createParams, Iterable schemaFields); + default String ftAlter(String indexName, Schema.Field... fields) { return ftAlter(indexName, Schema.from(fields)); } String ftAlter(String indexName, Schema schema); + default String ftAlter(String indexName, SchemaField... schemaFields) { + return ftAlter(indexName, Arrays.asList(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, "*"); + } + + SearchResult ftSearch(String indexName, String query); + + SearchResult ftSearch(String indexName, String query, FTSearchParams params); + SearchResult ftSearch(String indexName, Query query); + @Deprecated SearchResult ftSearch(byte[] indexName, Query query); String ftExplain(String indexName, Query query); @@ -29,27 +73,63 @@ default String ftAlter(String indexName, Schema.Field... fields) { String ftCursorDel(String indexName, long cursorId); - String ftDropIndex(String indexName); + Map.Entry> ftProfileAggregate(String indexName, + FTProfileParams profileParams, AggregationBuilder aggr); - String ftDropIndexDD(String indexName); + Map.Entry> ftProfileSearch(String indexName, + FTProfileParams profileParams, Query query); + + Map.Entry> ftProfileSearch(String indexName, + FTProfileParams profileParams, String query, FTSearchParams searchParams); String ftSynUpdate(String indexName, String synonymGroupId, String... terms); Map> ftSynDump(String indexName); - Map ftInfo(String indexName); + long ftDictAdd(String dictionary, String... terms); - String ftAliasAdd(String aliasName, String indexName); + long ftDictDel(String dictionary, String... terms); - String ftAliasUpdate(String aliasName, String indexName); + Set ftDictDump(String dictionary); - String ftAliasDel(String aliasName); + long ftDictAddBySampleKey(String indexName, String dictionary, String... terms); + + long ftDictDelBySampleKey(String indexName, String dictionary, String... terms); + + Set ftDictDumpBySampleKey(String indexName, String dictionary); + + Map> ftSpellCheck(String index, String query); + + Map> ftSpellCheck(String index, String query, + FTSpellCheckParams spellCheckParams); - Map ftConfigGet(String option); + Map ftInfo(String indexName); + + Set ftTagVals(String indexName, String fieldName); + + Map ftConfigGet(String option); - Map ftConfigGet(String indexName, String option); + Map ftConfigGet(String indexName, String option); String ftConfigSet(String option, String value); String ftConfigSet(String indexName, String option, String value); + + long ftSugAdd(String key, String string, double score); + + long ftSugAddIncr(String key, String string, double score); + + List ftSugGet(String key, String prefix); + + List ftSugGet(String key, String prefix, boolean fuzzy, int max); + + List ftSugGetWithScores(String key, String prefix); + + List ftSugGetWithScores(String key, String prefix, boolean fuzzy, int max); + + boolean ftSugDel(String key, String string); + + long ftSugLen(String key); + + 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 ed767469e6..c5765a6f31 100644 --- a/src/main/java/redis/clients/jedis/search/RediSearchPipelineCommands.java +++ b/src/main/java/redis/clients/jedis/search/RediSearchPipelineCommands.java @@ -1,24 +1,67 @@ package redis.clients.jedis.search; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; + import redis.clients.jedis.Response; +import redis.clients.jedis.resps.Tuple; import redis.clients.jedis.search.aggr.AggregationBuilder; import redis.clients.jedis.search.aggr.AggregationResult; - -import java.util.List; -import java.util.Map; +import redis.clients.jedis.search.schemafields.SchemaField; public interface RediSearchPipelineCommands { Response ftCreate(String indexName, IndexOptions indexOptions, Schema schema); + default Response ftCreate(String indexName, SchemaField... schemaFields) { + return ftCreate(indexName, Arrays.asList(schemaFields)); + } + + default Response ftCreate(String indexName, FTCreateParams createParams, SchemaField... schemaFields) { + return ftCreate(indexName, createParams, Arrays.asList(schemaFields)); + } + + default Response ftCreate(String indexName, Iterable schemaFields) { + return ftCreate(indexName, FTCreateParams.createParams(), schemaFields); + } + + Response ftCreate(String indexName, FTCreateParams createParams, Iterable schemaFields); + default Response ftAlter(String indexName, Schema.Field... fields) { return ftAlter(indexName, Schema.from(fields)); } Response ftAlter(String indexName, Schema schema); + default Response ftAlter(String indexName, SchemaField... schemaFields) { + return ftAlter(indexName, Arrays.asList(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, "*"); + } + + Response ftSearch(String indexName, String query); + + Response ftSearch(String indexName, String query, FTSearchParams searchParams); + Response ftSearch(String indexName, Query query); + @Deprecated Response ftSearch(byte[] indexName, Query query); Response ftExplain(String indexName, Query query); @@ -27,31 +70,52 @@ default Response ftAlter(String indexName, Schema.Field... fields) { Response ftAggregate(String indexName, AggregationBuilder aggr); - Response ftCursorRead(String indexName, long cursorId, int count); + Response ftSynUpdate(String indexName, String synonymGroupId, String... terms); - Response ftCursorDel(String indexName, long cursorId); + Response>> ftSynDump(String indexName); - Response ftDropIndex(String indexName); + Response ftDictAdd(String dictionary, String... terms); - Response ftDropIndexDD(String indexName); + Response ftDictDel(String dictionary, String... terms); - Response ftSynUpdate(String indexName, String synonymGroupId, String... terms); + Response> ftDictDump(String dictionary); - Response>> ftSynDump(String indexName); + Response ftDictAddBySampleKey(String indexName, String dictionary, String... terms); - Response> ftInfo(String indexName); + Response ftDictDelBySampleKey(String indexName, String dictionary, String... terms); - Response ftAliasAdd(String aliasName, String indexName); + Response> ftDictDumpBySampleKey(String indexName, String dictionary); - Response ftAliasUpdate(String aliasName, String indexName); + Response>> ftSpellCheck(String index, String query); - Response ftAliasDel(String aliasName); + Response>> ftSpellCheck(String index, String query, + FTSpellCheckParams spellCheckParams); + + Response> ftInfo(String indexName); - Response> ftConfigGet(String option); + Response> ftTagVals(String indexName, String fieldName); - Response> ftConfigGet(String indexName, String option); + Response> ftConfigGet(String option); + + Response> ftConfigGet(String indexName, String option); Response ftConfigSet(String option, String value); Response ftConfigSet(String indexName, String option, String value); + + Response ftSugAdd(String key, String string, double score); + + Response ftSugAddIncr(String key, String string, double score); + + Response> ftSugGet(String key, String prefix); + + Response> ftSugGet(String key, String prefix, boolean fuzzy, int max); + + Response> ftSugGetWithScores(String key, String prefix); + + Response> ftSugGetWithScores(String key, String prefix, boolean fuzzy, int max); + + Response ftSugDel(String key, String string); + + Response ftSugLen(String key); } 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 new file mode 100644 index 0000000000..8702b4a307 --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/SearchBuilderFactory.java @@ -0,0 +1,187 @@ +package redis.clients.jedis.search; + +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.util.DoublePrecision; +import redis.clients.jedis.util.KeyValue; +import redis.clients.jedis.util.SafeEncoder; + +public final class SearchBuilderFactory { + + public static final Builder> SEARCH_PROFILE_PROFILE = new Builder>() { + + private final String ITERATORS_PROFILE_STR = "Iterators profile"; + private final String CHILD_ITERATORS_STR = "Child iterators"; + private final String RESULT_PROCESSORS_PROFILE_STR = "Result processors profile"; + + @Override + public Map build(Object data) { + List list = (List) SafeEncoder.encodeObject(data); + Map profileMap = new HashMap<>(list.size(), 1f); + + for (Object listObject : list) { + List attributeList = (List) listObject; + String attributeName = (String) attributeList.get(0); + Object attributeValue; + + if (attributeList.size() == 2) { + + Object value = attributeList.get(1); + if (attributeName.equals(ITERATORS_PROFILE_STR)) { + attributeValue = parseIterators(value); + } else if (attributeName.endsWith(" time")) { + attributeValue = DoublePrecision.parseEncodedFloatingPointNumber(value); + } else { + attributeValue = value; + } + + } else if (attributeList.size() > 2) { + + if (attributeName.equals(RESULT_PROCESSORS_PROFILE_STR)) { + List> resultProcessorsProfileList = new ArrayList<>(attributeList.size() - 1); + for (int i = 1; i < attributeList.size(); i++) { + resultProcessorsProfileList.add(parseResultProcessors(attributeList.get(i))); + } + attributeValue = resultProcessorsProfileList; + } else { + attributeValue = attributeList.subList(1, attributeList.size()); + } + + } else { + attributeValue = null; + } + + profileMap.put(attributeName, attributeValue); + } + return profileMap; + } + + private Map parseResultProcessors(Object data) { + List list = (List) data; + Map map = new HashMap<>(list.size() / 2, 1f); + for (int i = 0; i < list.size(); i += 2) { + String key = (String) list.get(i); + Object value = list.get(i + 1); + if (key.equals("Time")) { + value = DoublePrecision.parseEncodedFloatingPointNumber(value); + } + map.put(key, value); + } + return map; + } + + private Object parseIterators(Object data) { + if (!(data instanceof List)) return data; + List iteratorsAttributeList = (List) data; + int childIteratorsIndex = iteratorsAttributeList.indexOf(CHILD_ITERATORS_STR); + // https://github.com/RediSearch/RediSearch/issues/3205 patch. TODO: Undo if resolved in RediSearch. + if (childIteratorsIndex < 0) childIteratorsIndex = iteratorsAttributeList.indexOf("Child iterator"); + + Map iteratorsProfile; + if (childIteratorsIndex < 0) { + childIteratorsIndex = iteratorsAttributeList.size(); + iteratorsProfile = new HashMap<>(childIteratorsIndex / 2, 1f); + } else { + iteratorsProfile = new HashMap<>(1 + childIteratorsIndex / 2, 1f); + } + + for (int i = 0; i < childIteratorsIndex; i += 2) { + String key = (String) iteratorsAttributeList.get(i); + Object value = iteratorsAttributeList.get(i + 1); + if (key.equals("Time")) { + value = DoublePrecision.parseEncodedFloatingPointNumber(value); + } + iteratorsProfile.put(key, value); + } + + if (childIteratorsIndex + 1 < iteratorsAttributeList.size()) { + List childIteratorsList = new ArrayList(iteratorsAttributeList.size() - childIteratorsIndex - 1); + for (int i = childIteratorsIndex + 1; i < iteratorsAttributeList.size(); i++) { + childIteratorsList.add(parseIterators(iteratorsAttributeList.get(i))); + } + iteratorsProfile.put(CHILD_ITERATORS_STR, childIteratorsList); + } + return iteratorsProfile; + } + }; + + public static final Builder>> SEARCH_SYNONYM_GROUPS = new Builder>>() { + @Override + public Map> build(Object 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))); + } + return dump; + } + }; + + public static final Builder>> SEARCH_SPELLCHECK_RESPONSE + = new Builder>>() { + + private static final String TERM = "TERM"; + private static final String RESULTS = "results"; + + @Override + public Map> build(Object data) { + 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 rawData : rawDataList) { + List rawElements = (List) rawData; + + String header = STRING.build(rawElements.get(0)); + if (!TERM.equals(header)) { + throw new IllegalStateException("Unrecognized header: " + header); + } + String term = STRING.build(rawElements.get(1)); + + List> list = (List>) rawElements.get(2); + Map entries = new LinkedHashMap<>(list.size()); + list.forEach(entry -> entries.put(STRING.build(entry.get(1)), BuilderFactory.DOUBLE.build(entry.get(0)))); + + returnTerms.put(term, entries); + } + return returnTerms; + } + }; + + private SearchBuilderFactory() { + throw new InstantiationError("Must not instantiate this class"); + } +} diff --git a/src/main/java/redis/clients/jedis/search/SearchProtocol.java b/src/main/java/redis/clients/jedis/search/SearchProtocol.java index d2e2583773..7f2ad482fb 100644 --- a/src/main/java/redis/clients/jedis/search/SearchProtocol.java +++ b/src/main/java/redis/clients/jedis/search/SearchProtocol.java @@ -22,11 +22,18 @@ public enum SearchCommand implements ProtocolCommand { ALIASDEL("FT.ALIASDEL"), SYNUPDATE("FT.SYNUPDATE"), SYNDUMP("FT.SYNDUMP"), -// SUGADD("FT.SUGADD"), -// SUGGET("FT.SUGGET"), -// SUGDEL("FT.SUGDEL"), -// SUGLEN("FT.SUGLEN"), - DROPINDEX("FT.DROPINDEX"); + SUGADD("FT.SUGADD"), + SUGGET("FT.SUGGET"), + SUGDEL("FT.SUGDEL"), + SUGLEN("FT.SUGLEN"), + DROPINDEX("FT.DROPINDEX"), + DICTADD("FT.DICTADD"), + DICTDEL("FT.DICTDEL"), + DICTDUMP("FT.DICTDUMP"), + SPELLCHECK("FT.SPELLCHECK"), + TAGVALS("FT.TAGVALS"), + PROFILE("FT.PROFILE"), + _LIST("FT._LIST"); private final byte[] raw; @@ -42,11 +49,14 @@ public byte[] getRaw() { public enum SearchKeyword implements Rawable { - SCHEMA, VERBATIM, NOCONTENT, NOSTOPWORDS, WITHSCORES, WITHPAYLOADS, LANGUAGE, INFIELDS, SORTBY, - ASC, DESC, PAYLOAD, LIMIT, HIGHLIGHT, FIELDS, TAGS, SUMMARIZE, FRAGS, LEN, SEPARATOR, INKEYS, - RETURN, /*NOSAVE, PARTIAL, REPLACE,*/ FILTER, GEOFILTER, INCR, MAX, FUZZY, DD, /*DELETE,*/ DEL, - READ, COUNT, ADD, TEMPORARY, STOPWORDS, NOFREQS, NOFIELDS, NOOFFSETS, /*IF,*/ SET, GET, ON, - ASYNC, PREFIX, LANGUAGE_FIELD, SCORE_FIELD, SCORE, PAYLOAD_FIELD, SCORER, PARAMS, DIALECT; + 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 b980f8e7eb..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 @@ -70,15 +71,41 @@ public SearchResult build(Object data) { for (int i = 1; i < resp.size(); i += step) { + 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; - String id = new String((byte[]) resp.get(i)); - 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 d0cb9ea23e..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,51 +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 List getArgs() { - return Collections.unmodifiableList(args); + public AggregationBuilder verbatim() { + aggrArgs.add(SearchKeyword.VERBATIM); + return this; } - public void serializeRedisArgs(List redisArgs) { - for (String s : getArgs()) { - redisArgs.add(SafeEncoder.encode(s)); - } + public AggregationBuilder timeout(long timeout) { + aggrArgs.add(SearchKeyword.TIMEOUT); + aggrArgs.add(timeout); + return this; } - public String getArgsString() { - StringJoiner sj = new StringJoiner(" "); - for (String s : getArgs()) { - sj.add(s); + public AggregationBuilder params(Map params) { + 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) { + this.dialect = dialect; + return this; + } + + /** + * 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 cda4d6a4a1..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,58 +1,154 @@ package redis.clients.jedis.search.aggr; -import redis.clients.jedis.exceptions.JedisDataException; - 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; -/** - * Created by mnunberg on 2/22/18. - */ public class AggregationResult { - public final long totalResults; + private final long totalResults; + + private final List> results; - private long cursorId = -1; - private final List> results = new ArrayList<>(); + 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) { - List list = (List) resp; + private AggregationResult(Object resp) { + List list = (List) SafeEncoder.encodeObject(resp); + // the first element is always the number of results totalResults = (Long) list.get(0); + results = new ArrayList<>(list.size() - 1); for (int i = 1; i < list.size(); i++) { - List raw = (List) list.get(i); - Map cur = new HashMap<>(); - for (int j = 0; j < raw.size(); j += 2) { - Object r = raw.get(j); + 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; } - cur.put(new String((byte[]) r), raw.get(j + 1)); + map.put((String) r, mapList.get(j + 1)); } - results.add(cur); + results.add(map); } } + 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); + } + + /** + * @return results as {@link Row}s. + * @see #getResults() + */ + public List getRows() { + return results.stream().map(Row::new).collect(Collectors.toList()); } public Row getRow(int index) { - if (index >= results.size()) { - return null; - } 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..21f7060ee7 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,44 @@ */ public abstract class Reducer { - private String alias; + private final String name; private final String field; + private String alias; - protected Reducer(String field) { - this.field = field; - this.alias = null; - } - - protected Reducer() { - this(null); - } - - protected List getOwnArgs() { - if (field == null) { - return Collections.emptyList(); - } - List ret = new ArrayList<>(); - ret.add(field); - return ret; + protected Reducer(String name) { + this.name = name; + this.field = null; } - /** - * @return The name of the reducer - */ - public abstract String getName(); - - public final String getAlias() { - return alias; + protected Reducer(String name, String field) { + this.name = name; + this.field = field; } - public final Reducer setAlias(String alias) { + public final Reducer as(String alias) { this.alias = alias; return this; } - public final Reducer as(String alias) { - return setAlias(alias); - } + protected abstract List getOwnArgs(); - public final Reducer setAliasAsField() { - if (field == null || field.isEmpty()) { - throw new IllegalArgumentException("Cannot set to field name since no field exists"); - } - return setAlias(field); - } + public final void addArgs(List args) { - public void addArgs(List args) { - List ownArgs = getOwnArgs(); - args.add(Integer.toString(ownArgs.size())); + args.add(SearchKeyword.REDUCE); + args.add(name); + + 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/aggr/Row.java b/src/main/java/redis/clients/jedis/search/aggr/Row.java index b7dbe2601d..c56f21c7e4 100644 --- a/src/main/java/redis/clients/jedis/search/aggr/Row.java +++ b/src/main/java/redis/clients/jedis/search/aggr/Row.java @@ -1,12 +1,8 @@ package redis.clients.jedis.search.aggr; import java.util.Map; +import redis.clients.jedis.util.DoublePrecision; -/** - * Created by mnunberg on 5/17/18. - * - * Row in aggregation result-set - */ public class Row { private final Map fields; @@ -19,24 +15,33 @@ public boolean containsKey(String key) { return fields.containsKey(key); } + public Object get(String key) { + return fields.get(key); + } + public String getString(String key) { if (!containsKey(key)) { return ""; } - return new String((byte[]) fields.get(key)); + return (String) fields.get(key); } public long getLong(String key) { if (!containsKey(key)) { return 0; } - return Long.parseLong(getString(key)); + return Long.parseLong((String) fields.get(key)); } public double getDouble(String key) { if (!containsKey(key)) { return 0; } - return Double.parseDouble(getString(key)); + return DoublePrecision.parseFloatingPointNumber((String) fields.get(key)); + } + + @Override + public String toString() { + return String.valueOf(fields); } } diff --git a/src/main/java/redis/clients/jedis/search/aggr/package-info.java b/src/main/java/redis/clients/jedis/search/aggr/package-info.java index ecebca2390..bee071ea8a 100644 --- a/src/main/java/redis/clients/jedis/search/aggr/package-info.java +++ b/src/main/java/redis/clients/jedis/search/aggr/package-info.java @@ -1,4 +1,4 @@ -/* +/** * This package contains the classes related to Aggregation commands in RediSearch module. */ package redis.clients.jedis.search.aggr; diff --git a/src/main/java/redis/clients/jedis/search/package-info.java b/src/main/java/redis/clients/jedis/search/package-info.java index e406948657..f906f3b7e1 100644 --- a/src/main/java/redis/clients/jedis/search/package-info.java +++ b/src/main/java/redis/clients/jedis/search/package-info.java @@ -1,4 +1,4 @@ -/* - * This package contains the classes related to RediSearch module. +/** + * This package contains the classes and interfaces related to RediSearch module. */ package redis.clients.jedis.search; diff --git a/src/main/java/redis/clients/jedis/search/querybuilder/DisjunctNode.java b/src/main/java/redis/clients/jedis/search/querybuilder/DisjunctNode.java new file mode 100644 index 0000000000..d982072416 --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/querybuilder/DisjunctNode.java @@ -0,0 +1,24 @@ +package redis.clients.jedis.search.querybuilder; + +/** + * A disjunct node. evaluates to true if any of its children are false. Conversely, this node + * evaluates to false only iff all of its children are true, making it the exact inverse of + * {@link IntersectNode} + * + * In RS, it looks like: + * + * {@code -(@f1:v1 @f2:v2)} + * + * @see DisjunctUnionNode which evalutes to true if all its children are false. + */ +public class DisjunctNode extends IntersectNode { + @Override + public String toString(Parenthesize mode) { + String ret = super.toString(Parenthesize.NEVER); + if (shouldParenthesize(mode)) { + return "-(" + ret + ")"; + } else { + return "-" + ret; + } + } +} diff --git a/src/main/java/redis/clients/jedis/search/querybuilder/DisjunctUnionNode.java b/src/main/java/redis/clients/jedis/search/querybuilder/DisjunctUnionNode.java new file mode 100644 index 0000000000..36be78bf31 --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/querybuilder/DisjunctUnionNode.java @@ -0,0 +1,17 @@ +package redis.clients.jedis.search.querybuilder; + +/** + * A disjunct union node is the inverse of a {@link UnionNode}. It evaluates to true only iff + * all its children are false. Conversely, it evaluates to false if any of its + * children are true. + * + * As an RS query it looks like {@code -(@f1:v1|@f2:v2)} + * + * @see DisjunctNode which evaluates to true if any of its children are false. + */ +public class DisjunctUnionNode extends DisjunctNode { + @Override + protected String getJoinString() { + return "|"; + } +} diff --git a/src/main/java/redis/clients/jedis/search/querybuilder/DoubleRangeValue.java b/src/main/java/redis/clients/jedis/search/querybuilder/DoubleRangeValue.java new file mode 100644 index 0000000000..75fc3843be --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/querybuilder/DoubleRangeValue.java @@ -0,0 +1,38 @@ +package redis.clients.jedis.search.querybuilder; + +/** + * @author mnunberg on 2/23/18. + */ +public class DoubleRangeValue extends RangeValue { + + private final double from; + private final double to; + + private static void appendNum(StringBuilder sb, double n, boolean inclusive) { + if (!inclusive) { + sb.append("("); + } + if (n == Double.NEGATIVE_INFINITY) { + sb.append("-inf"); + } else if (n == Double.POSITIVE_INFINITY) { + sb.append("inf"); + } else { + sb.append(n); + } + } + + public DoubleRangeValue(double from, double to) { + this.from = from; + this.to = to; + } + + @Override + protected void appendFrom(StringBuilder sb, boolean inclusive) { + appendNum(sb, from, inclusive); + } + + @Override + protected void appendTo(StringBuilder sb, boolean inclusive) { + appendNum(sb, to, inclusive); + } +} diff --git a/src/main/java/redis/clients/jedis/search/querybuilder/GeoValue.java b/src/main/java/redis/clients/jedis/search/querybuilder/GeoValue.java new file mode 100644 index 0000000000..3c6727b217 --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/querybuilder/GeoValue.java @@ -0,0 +1,33 @@ +package redis.clients.jedis.search.querybuilder; + +import java.util.Locale; +import redis.clients.jedis.args.GeoUnit; + +/** + * Created by mnunberg on 2/23/18. + */ +public class GeoValue extends Value { + + private final GeoUnit unit; + private final double lon; + private final double lat; + private final double radius; + + public GeoValue(double lon, double lat, double radius, GeoUnit unit) { + this.lon = lon; + this.lat = lat; + this.radius = radius; + this.unit = unit; + } + + @Override + public String toString() { + return "[" + lon + " " + lat + " " + radius + + " " + unit.name().toLowerCase(Locale.ENGLISH) + "]"; + } + + @Override + public boolean isCombinable() { + return false; + } +} diff --git a/src/main/java/redis/clients/jedis/search/querybuilder/IntersectNode.java b/src/main/java/redis/clients/jedis/search/querybuilder/IntersectNode.java new file mode 100644 index 0000000000..979618647f --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/querybuilder/IntersectNode.java @@ -0,0 +1,13 @@ +package redis.clients.jedis.search.querybuilder; + +/** + * The intersection node evaluates to true if any of its children are true. + * + * In RS: {@code @f1:v1 @f2:v2} + */ +public class IntersectNode extends QueryNode { + @Override + protected String getJoinString() { + return " "; + } +} diff --git a/src/main/java/redis/clients/jedis/search/querybuilder/LongRangeValue.java b/src/main/java/redis/clients/jedis/search/querybuilder/LongRangeValue.java new file mode 100644 index 0000000000..ffa072aa5a --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/querybuilder/LongRangeValue.java @@ -0,0 +1,40 @@ +package redis.clients.jedis.search.querybuilder; + +public class LongRangeValue extends RangeValue { + + private final long from; + private final long to; + + @Override + public boolean isCombinable() { + return false; + } + + private static void appendNum(StringBuilder sb, long n, boolean inclusive) { + if (!inclusive) { + sb.append("("); + } + if (n == Long.MIN_VALUE) { + sb.append("-inf"); + } else if (n == Long.MAX_VALUE) { + sb.append("inf"); + } else { + sb.append(Long.toString(n)); + } + } + + public LongRangeValue(long from, long to) { + this.from = from; + this.to = to; + } + + @Override + protected void appendFrom(StringBuilder sb, boolean inclusive) { + appendNum(sb, from, inclusive); + } + + @Override + protected void appendTo(StringBuilder sb, boolean inclusive) { + appendNum(sb, to, inclusive); + } +} diff --git a/src/main/java/redis/clients/jedis/search/querybuilder/Node.java b/src/main/java/redis/clients/jedis/search/querybuilder/Node.java new file mode 100644 index 0000000000..12e71e5d69 --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/querybuilder/Node.java @@ -0,0 +1,50 @@ +package redis.clients.jedis.search.querybuilder; + +import redis.clients.jedis.search.Query; + +/** + * Created by mnunberg on 2/23/18. + * + * Base node interface + */ +public interface Node { + + enum Parenthesize { + + /** + * Always encapsulate + */ + ALWAYS, + + /** + * 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 + * parenthesized. + */ + + NEVER, + /** + * Determine encapsulation based on number of children. If the node only has one child, it is + * not parenthesized, if it has more than one child, it is parenthesized + */ + + DEFAULT + } + + /** + * Returns the string form of this node. + * + * @param mode Whether the string should be encapsulated in parentheses {@code (...)} + * @return The string query. + */ + String toString(Parenthesize mode); + + /** + * Returns the string form of this node. This may be passed to + * {@link redis.clients.jedis.UnifiedJedis#ftSearch(String, Query)} + * + * @return The query string. + */ + @Override + String toString(); +} diff --git a/src/main/java/redis/clients/jedis/search/querybuilder/OptionalNode.java b/src/main/java/redis/clients/jedis/search/querybuilder/OptionalNode.java new file mode 100644 index 0000000000..7a9c728a05 --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/querybuilder/OptionalNode.java @@ -0,0 +1,22 @@ +package redis.clients.jedis.search.querybuilder; + +/** + * Created by mnunberg on 2/23/18. + * + * The optional node affects scoring and ordering. If it evaluates to true, the result is ranked + * higher. It is helpful to combine it with a {@link UnionNode} to rank a document higher if it + * meets one of several criteria. + * + * In RS: {@code ~(@lang:en @country:us)}. + */ +public class OptionalNode extends IntersectNode { + + @Override + public String toString(Parenthesize mode) { + String ret = super.toString(Parenthesize.NEVER); + if (shouldParenthesize(mode)) { + return "~(" + ret + ")"; + } + return "~" + ret; + } +} diff --git a/src/main/java/redis/clients/jedis/search/querybuilder/QueryBuilders.java b/src/main/java/redis/clients/jedis/search/querybuilder/QueryBuilders.java new file mode 100644 index 0000000000..92576b80c5 --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/querybuilder/QueryBuilders.java @@ -0,0 +1,155 @@ +package redis.clients.jedis.search.querybuilder; + +import java.util.Arrays; + +import static redis.clients.jedis.search.querybuilder.Values.value; + +/** + * Created by mnunberg on 2/23/18. + * + * This class contains methods to construct query nodes. These query nodes can be added to parent + * query nodes (building a chain) or used as the root query node. + */ +public class QueryBuilders { + private QueryBuilders() { + throw new InstantiationError("Must not instantiate this class"); + } + + /** + * Create a new intersection node with child nodes. An intersection node is true if all its + * children are also true + * + * @param n sub-condition to add + * @return The node + */ + public static QueryNode intersect(Node... n) { + return new IntersectNode().add(n); + } + + /** + * Create a new intersection node with a field-value pair. + * + * @param field The field that should contain this value. If this value is empty, then any field + * will be checked. + * @param values Value to check for. The node will be true only if the field (or any field) + * contains all of the values + * @return The node + */ + public static QueryNode intersect(String field, Value... values) { + return new IntersectNode().add(field, values); + } + + /** + * Helper method to create a new intersection node with a string value. + * + * @param field The field to check. If left null or empty, all fields will be checked. + * @param stringValue The value to check + * @return The node + */ + public static QueryNode intersect(String field, String stringValue) { + return intersect(field, value(stringValue)); + } + + /** + * Create a union node. Union nodes evaluate to true if any of its children are true + * + * @param n Child node + * @return The union node + */ + public static QueryNode union(Node... n) { + return new UnionNode().add(n); + } + + /** + * Create a union node which can match an one or more values + * + * @param field Field to check. If empty, all fields are checked + * @param values Values to search for. The node evaluates to true if {@code field} matches any of + * the values + * @return The union node + */ + public static QueryNode union(String field, Value... values) { + return new UnionNode().add(field, values); + } + + /** + * Convenience method to match one or more strings. This is equivalent to + * {@code union(field, value(v1), value(v2), value(v3)) ...} + * + * @param field Field to match + * @param values Strings to check for + * @return The union node + */ + public static QueryNode union(String field, String... values) { + return union(field, (Value[]) Arrays.stream(values).map(Values::value).toArray()); + } + + /** + * Create a disjunct node. Disjunct nodes are true iff any of its children are not + * true. Conversely, this node evaluates to false if all its children are true. + * + * @param n Child nodes to add + * @return The disjunct node + */ + public static QueryNode disjunct(Node... n) { + return new DisjunctNode().add(n); + } + + /** + * Create a disjunct node using one or more values. The node will evaluate to true iff the field + * does not match any of the values. + * + * @param field Field to check for (empty or null for any field) + * @param values The values to check for + * @return The node + */ + public static QueryNode disjunct(String field, Value... values) { + return new DisjunctNode().add(field, values); + } + + /** + * Create a disjunct node using one or more values. The node will evaluate to true iff the field + * does not match any of the values. + * + * @param field Field to check for (empty or null for any field) + * @param values The values to check for + * @return The node + */ + public static QueryNode disjunct(String field, String... values) { + return disjunct(field, (Value[]) Arrays.stream(values).map(Values::value).toArray()); + } + + /** + * Create a disjunct union node. This node evaluates to true if all of its children are not + * true. Conversely, this node evaluates as false if any of its children are true. + * + * @param n + * @return The node + */ + public static QueryNode disjunctUnion(Node... n) { + return new DisjunctUnionNode().add(n); + } + + public static QueryNode disjunctUnion(String field, Value... values) { + return new DisjunctUnionNode().add(field, values); + } + + public static QueryNode disjunctUnion(String field, String... values) { + return disjunctUnion(field, (Value[]) Arrays.stream(values).map(Values::value).toArray()); + } + + /** + * Create an optional node. Optional nodes do not affect which results are returned but they + * influence ordering and scoring. + * + * @param n The node to evaluate as optional + * @return The new node + */ + public static QueryNode optional(Node... n) { + return new OptionalNode().add(n); + } + + public static QueryNode optional(String field, Value... values) { + return new OptionalNode().add(field, values); + } +} diff --git a/src/main/java/redis/clients/jedis/search/querybuilder/QueryNode.java b/src/main/java/redis/clients/jedis/search/querybuilder/QueryNode.java new file mode 100644 index 0000000000..bc64374a5a --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/querybuilder/QueryNode.java @@ -0,0 +1,92 @@ +package redis.clients.jedis.search.querybuilder; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.StringJoiner; + +public abstract class QueryNode implements Node { + + private final List children = new ArrayList<>(); + + protected abstract String getJoinString(); + + /** + * Add a match criteria to this node + * + * @param field The field to check. If null or empty, then any field is checked + * @param values Values to check for. + * @return The current node, for chaining. + */ + public QueryNode add(String field, Value... values) { + children.add(new ValueNode(field, getJoinString(), values)); + return this; + } + + /** + * Convenience method to add a list of string values + * + * @param field Field to check for + * @param values One or more string values. + * @return The current node, for chaining. + */ + public QueryNode add(String field, String... values) { + children.add(new ValueNode(field, getJoinString(), values)); + return this; + } + + /** + * Add a list of values from a collection + * + * @param field The field to check + * @param values Collection of values to match + * @return The current node for chaining. + */ + public QueryNode add(String field, Collection values) { + return add(field, values.toArray(new Value[0])); + } + + /** + * Add children nodes to this node. + * + * @param nodes Children nodes to add + * @return The current node, for chaining. + */ + public QueryNode add(Node... nodes) { + children.addAll(Arrays.asList(nodes)); + return this; + } + + protected boolean shouldParenthesize(Parenthesize mode) { + if (mode == Parenthesize.ALWAYS) { + return true; + } + if (mode == Parenthesize.NEVER) { + return false; + } + return children.size() > 1; + } + + @Override + public String toString(Parenthesize parenMode) { + StringBuilder sb = new StringBuilder(); + StringJoiner sj = new StringJoiner(getJoinString()); + if (shouldParenthesize(parenMode)) { + sb.append('('); + } + for (Node n : children) { + sj.add(n.toString(parenMode)); + } + sb.append(sj.toString()); + if (shouldParenthesize(parenMode)) { + sb.append(')'); + } + return sb.toString(); + } + + @Override + public String toString() { + return toString(Parenthesize.DEFAULT); + } +} diff --git a/src/main/java/redis/clients/jedis/search/querybuilder/RangeValue.java b/src/main/java/redis/clients/jedis/search/querybuilder/RangeValue.java new file mode 100644 index 0000000000..9d05657c33 --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/querybuilder/RangeValue.java @@ -0,0 +1,40 @@ +package redis.clients.jedis.search.querybuilder; + +/** + * @author mnunberg on 2/23/18. + */ +public abstract class RangeValue extends Value { + + private boolean inclusiveMin = true; + private boolean inclusiveMax = true; + + @Override + public boolean isCombinable() { + return false; + } + + protected abstract void appendFrom(StringBuilder sb, boolean inclusive); + + protected abstract void appendTo(StringBuilder sb, boolean inclusive); + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append('['); + appendFrom(sb, inclusiveMin); + sb.append(' '); + appendTo(sb, inclusiveMax); + sb.append(']'); + return sb.toString(); + } + + public RangeValue inclusiveMin(boolean val) { + inclusiveMin = val; + return this; + } + + public RangeValue inclusiveMax(boolean val) { + inclusiveMax = val; + return this; + } +} diff --git a/src/main/java/redis/clients/jedis/search/querybuilder/UnionNode.java b/src/main/java/redis/clients/jedis/search/querybuilder/UnionNode.java new file mode 100644 index 0000000000..8066df1bc6 --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/querybuilder/UnionNode.java @@ -0,0 +1,11 @@ +package redis.clients.jedis.search.querybuilder; + +/** + * Created by mnunberg on 2/23/18. + */ +public class UnionNode extends QueryNode { + @Override + protected String getJoinString() { + return "|"; + } +} diff --git a/src/main/java/redis/clients/jedis/search/querybuilder/Value.java b/src/main/java/redis/clients/jedis/search/querybuilder/Value.java new file mode 100644 index 0000000000..54e7755fa9 --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/querybuilder/Value.java @@ -0,0 +1,13 @@ +package redis.clients.jedis.search.querybuilder; + +/** + * Created by mnunberg on 2/23/18. + */ +public abstract class Value { + public boolean isCombinable() { + return false; + } + + @Override + public abstract String toString(); +} diff --git a/src/main/java/redis/clients/jedis/search/querybuilder/ValueNode.java b/src/main/java/redis/clients/jedis/search/querybuilder/ValueNode.java new file mode 100644 index 0000000000..5bcb587001 --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/querybuilder/ValueNode.java @@ -0,0 +1,82 @@ +package redis.clients.jedis.search.querybuilder; + +import java.util.StringJoiner; + +/** + * Created by mnunberg on 2/23/18. + */ +public class ValueNode implements Node { + + private final Value[] values; + private final String field; + private final String joinString; + + public ValueNode(String field, String joinstr, Value... values) { + this.field = field; + this.values = values; + this.joinString = joinstr; + } + + private static Value[] fromStrings(String[] values) { + Value[] objs = new Value[values.length]; + for (int i = 0; i < values.length; i++) { + objs[i] = Values.value(values[i]); + } + return objs; + } + + public ValueNode(String field, String joinstr, String... values) { + this(field, joinstr, fromStrings(values)); + } + + private String formatField() { + if (field == null || field.isEmpty()) { + return ""; + } + return '@' + field + ':'; + } + + private String toStringCombinable(Parenthesize mode) { + StringBuilder sb = new StringBuilder(formatField()); + if (values.length > 1 || mode == Parenthesize.ALWAYS) { + sb.append('('); + } + StringJoiner sj = new StringJoiner(joinString); + for (Value v : values) { + sj.add(v.toString()); + } + sb.append(sj.toString()); + if (values.length > 1 || mode == Parenthesize.ALWAYS) { + sb.append(')'); + } + return sb.toString(); + } + + private String toStringDefault(Parenthesize mode) { + boolean useParen = mode == Parenthesize.ALWAYS; + if (!useParen) { + useParen = mode != Parenthesize.NEVER && values.length > 1; + } + StringBuilder sb = new StringBuilder(); + if (useParen) { + sb.append('('); + } + StringJoiner sj = new StringJoiner(joinString); + for (Value v : values) { + sj.add(formatField() + v.toString()); + } + sb.append(sj.toString()); + if (useParen) { + sb.append(')'); + } + return sb.toString(); + } + + @Override + public String toString(Parenthesize mode) { + if (values[0].isCombinable()) { + return toStringCombinable(mode); + } + return toStringDefault(mode); + } +} diff --git a/src/main/java/redis/clients/jedis/search/querybuilder/Values.java b/src/main/java/redis/clients/jedis/search/querybuilder/Values.java new file mode 100644 index 0000000000..67256f2359 --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/querybuilder/Values.java @@ -0,0 +1,99 @@ +package redis.clients.jedis.search.querybuilder; + +import redis.clients.jedis.GeoCoordinate; +import redis.clients.jedis.args.GeoUnit; + +import java.util.StringJoiner; + +/** + * Created by mnunberg on 2/23/18. + */ +public class Values { + private Values() { + throw new InstantiationError("Must not instantiate this class"); + } + + private abstract static class ScalableValue extends Value { + @Override + public boolean isCombinable() { + return true; + } + } + + public static Value value(String s) { + return new ScalableValue() { + @Override + public String toString() { + return s; + } + }; + } + + public static GeoValue geo(GeoCoordinate coord, double radius, GeoUnit unit) { + return new GeoValue(coord.getLongitude(), coord.getLatitude(), radius, unit); + } + + public static RangeValue between(double from, double to) { + return new DoubleRangeValue(from, to); + } + + public static RangeValue between(int from, int to) { + return new LongRangeValue(from, to); + } + + public static RangeValue eq(double d) { + return new DoubleRangeValue(d, d); + } + + public static RangeValue eq(int i) { + return new LongRangeValue(i, i); + } + + public static RangeValue lt(double d) { + return new DoubleRangeValue(Double.NEGATIVE_INFINITY, d).inclusiveMax(false); + } + + public static RangeValue lt(int d) { + return new LongRangeValue(Long.MIN_VALUE, d).inclusiveMax(false); + } + + public static RangeValue gt(double d) { + return new DoubleRangeValue(d, Double.POSITIVE_INFINITY).inclusiveMin(false); + } + + public static RangeValue gt(int d) { + return new LongRangeValue(d, Long.MAX_VALUE).inclusiveMin(false); + } + + public static RangeValue le(double d) { + return lt(d).inclusiveMax(true); + } + + public static RangeValue le(int d) { + return lt(d).inclusiveMax(true); + } + + public static RangeValue ge(double d) { + return gt(d).inclusiveMin(true); + } + + public static RangeValue ge(int d) { + return gt(d).inclusiveMin(true); + } + + public static Value tags(String... tags) { + if (tags.length == 0) { + throw new IllegalArgumentException("Must have at least one tag"); + } + StringJoiner sj = new StringJoiner(" | "); + for (String s : tags) { + sj.add(s); + } + return new Value() { + @Override + public String toString() { + return "{" + sj.toString() + "}"; + } + }; + } +} diff --git a/src/main/java/redis/clients/jedis/search/schemafields/GeoField.java b/src/main/java/redis/clients/jedis/search/schemafields/GeoField.java new file mode 100644 index 0000000000..7ea421ab4f --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/schemafields/GeoField.java @@ -0,0 +1,37 @@ +package redis.clients.jedis.search.schemafields; + +import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.GEO; + +import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.search.FieldName; + +public class GeoField extends SchemaField { + + public GeoField(String fieldName) { + super(fieldName); + } + + public GeoField(FieldName fieldName) { + super(fieldName); + } + + public static GeoField of(String fieldName) { + return new GeoField(fieldName); + } + + public static GeoField of(FieldName fieldName) { + return new GeoField(fieldName); + } + + @Override + public GeoField as(String attribute) { + super.as(attribute); + return this; + } + + @Override + public void addParams(CommandArguments args) { + args.addParams(fieldName); + args.add(GEO); + } +} 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/NumericField.java b/src/main/java/redis/clients/jedis/search/schemafields/NumericField.java new file mode 100644 index 0000000000..e1e39ef724 --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/schemafields/NumericField.java @@ -0,0 +1,66 @@ +package redis.clients.jedis.search.schemafields; + +import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.NOINDEX; +import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.NUMERIC; +import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.SORTABLE; + +import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.search.FieldName; + +public class NumericField extends SchemaField { + + private boolean sortable; + private boolean noIndex; + + public NumericField(String fieldName) { + super(fieldName); + } + + public NumericField(FieldName fieldName) { + super(fieldName); + } + + public static NumericField of(String fieldName) { + return new NumericField(fieldName); + } + + public static NumericField of(FieldName fieldName) { + return new NumericField(fieldName); + } + + @Override + public NumericField as(String attribute) { + super.as(attribute); + return this; + } + + /** + * Sorts the results by the value of this field. + */ + public NumericField sortable() { + this.sortable = true; + return this; + } + + /** + * Avoid indexing. + */ + public NumericField noIndex() { + this.noIndex = true; + return this; + } + + @Override + public void addParams(CommandArguments args) { + args.addParams(fieldName); + args.add(NUMERIC); + + if (sortable) { + args.add(SORTABLE); + } + + if (noIndex) { + args.add(NOINDEX); + } + } +} diff --git a/src/main/java/redis/clients/jedis/search/schemafields/SchemaField.java b/src/main/java/redis/clients/jedis/search/schemafields/SchemaField.java new file mode 100644 index 0000000000..8678780da2 --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/schemafields/SchemaField.java @@ -0,0 +1,30 @@ +package redis.clients.jedis.search.schemafields; + +import redis.clients.jedis.params.IParams; +import redis.clients.jedis.search.FieldName; + +public abstract class SchemaField implements IParams { + + protected final FieldName fieldName; + + public SchemaField(String fieldName) { + this.fieldName = new FieldName(fieldName); + } + + public SchemaField(FieldName fieldName) { + this.fieldName = fieldName; + } + + 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 new file mode 100644 index 0000000000..407c4dbddc --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/schemafields/TagField.java @@ -0,0 +1,127 @@ +package redis.clients.jedis.search.schemafields; + +import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.*; + +import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.search.FieldName; +import redis.clients.jedis.util.SafeEncoder; + +public class TagField extends SchemaField { + + private boolean sortable; + private boolean sortableUNF; + private boolean noIndex; + private byte[] separator; + private boolean caseSensitive; + private boolean withSuffixTrie; + + public TagField(String fieldName) { + super(fieldName); + } + + public TagField(FieldName fieldName) { + super(fieldName); + } + + public static TagField of(String fieldName) { + return new TagField(fieldName); + } + + public static TagField of(FieldName fieldName) { + return new TagField(fieldName); + } + + @Override + public TagField as(String attribute) { + super.as(attribute); + return this; + } + + /** + * Sorts the results by the value of this field. + */ + public TagField sortable() { + this.sortable = true; + return this; + } + + /** + * Sorts the results by the value of this field without normalization. + */ + public TagField sortableUNF() { + this.sortableUNF = true; + return this; + } + + /** + * @see TextField#sortableUNF() + */ + public TagField sortableUnNormalizedForm() { + return sortableUNF(); + } + + /** + * Avoid indexing. + */ + public TagField noIndex() { + this.noIndex = true; + return this; + } + + /** + * Indicates how the text contained in the attribute is to be split into individual tags. + */ + public TagField separator(char separator) { + if (separator < 128) { + this.separator = new byte[]{(byte) separator}; + } else { + this.separator = SafeEncoder.encode(String.valueOf(separator)); + } + return this; + } + + /** + * Keeps the original letter cases of the tags. + */ + public TagField caseSensitive() { + this.caseSensitive = true; + return this; + } + + /** + * Keeps a suffix trie with all terms which match the suffix. It is used to optimize + * contains and suffix queries. + */ + public TagField withSuffixTrie() { + this.withSuffixTrie = true; + return this; + } + + @Override + public void addParams(CommandArguments args) { + args.addParams(fieldName); + args.add(TAG); + + if (separator != null) { + 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) { + args.add(SORTABLE); + } + + if (noIndex) { + args.add(NOINDEX); + } + } +} diff --git a/src/main/java/redis/clients/jedis/search/schemafields/TextField.java b/src/main/java/redis/clients/jedis/search/schemafields/TextField.java new file mode 100644 index 0000000000..573cae90a3 --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/schemafields/TextField.java @@ -0,0 +1,136 @@ +package redis.clients.jedis.search.schemafields; + +import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.*; + +import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.search.FieldName; + +public class TextField extends SchemaField { + + private boolean sortable; + private boolean sortableUNF; + private boolean noStem; + private boolean noIndex; + private String phoneticMatcher; + private Double weight; + private boolean withSuffixTrie; + + public TextField(String fieldName) { + super(fieldName); + } + + public TextField(FieldName fieldName) { + super(fieldName); + } + + public static TextField of(String fieldName) { + return new TextField(fieldName); + } + + public static TextField of(FieldName fieldName) { + return new TextField(fieldName); + } + + @Override + public TextField as(String attribute) { + super.as(attribute); + return this; + } + + /** + * Sorts the results by the value of this field. + */ + public TextField sortable() { + this.sortable = true; + return this; + } + + /** + * Sorts the results by the value of this field without normalization. + */ + public TextField sortableUNF() { + this.sortableUNF = true; + return this; + } + + /** + * @see TextField#sortableUNF() + */ + public TextField sortableUnNormalizedForm() { + return sortableUNF(); + } + + /** + * Disable stemming when indexing. + */ + public TextField noStem() { + this.noStem = true; + return this; + } + + /** + * Avoid indexing. + */ + public TextField noIndex() { + this.noIndex = true; + return this; + } + + /** + * Perform phonetic matching. + */ + public TextField phonetic(String matcher) { + this.phoneticMatcher = matcher; + return this; + } + + /** + * Declares the importance of this attribute when calculating result accuracy. This is a + * multiplication factor. + */ + public TextField weight(double weight) { + this.weight = weight; + return this; + } + + /** + * Keeps a suffix trie with all terms which match the suffix. It is used to optimize + * contains and suffix queries. + */ + public TextField withSuffixTrie() { + this.withSuffixTrie = true; + return this; + } + + @Override + public void addParams(CommandArguments args) { + args.addParams(fieldName); + args.add(TEXT); + + if (weight != null) { + args.add(WEIGHT).add(weight); + } + + if (noStem) { + args.add(NOSTEM); + } + + if (phoneticMatcher != null) { + args.add(PHONETIC).add(phoneticMatcher); + } + + 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/search/schemafields/VectorField.java b/src/main/java/redis/clients/jedis/search/schemafields/VectorField.java new file mode 100644 index 0000000000..02287a5be3 --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/schemafields/VectorField.java @@ -0,0 +1,101 @@ +package redis.clients.jedis.search.schemafields; + +import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.VECTOR; + +import java.util.LinkedHashMap; +import java.util.Map; +import redis.clients.jedis.CommandArguments; +import redis.clients.jedis.search.FieldName; + +public class VectorField extends SchemaField { + + public enum VectorAlgorithm { + FLAT, + HNSW + } + + private final VectorAlgorithm algorithm; + private final Map attributes; + + public VectorField(String fieldName, VectorAlgorithm algorithm, Map attributes) { + super(fieldName); + this.algorithm = algorithm; + this.attributes = attributes; + } + + public VectorField(FieldName fieldName, VectorAlgorithm algorithm, Map attributes) { + super(fieldName); + this.algorithm = algorithm; + this.attributes = attributes; + } + + @Override + public VectorField as(String attribute) { + super.as(attribute); + return this; + } + + @Override + public void addParams(CommandArguments args) { + args.addParams(fieldName); + args.add(VECTOR); + + args.add(algorithm); + args.add(attributes.size() * 2); + attributes.forEach((name, value) -> args.add(name).add(value)); + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private FieldName fieldName; + private VectorAlgorithm algorithm; + private Map attributes; + + private Builder() { + } + + public VectorField build() { + if (fieldName == null || algorithm == null || attributes == null || attributes.isEmpty()) { + throw new IllegalArgumentException("All required VectorField parameters are not set."); + } + return new VectorField(fieldName, algorithm, attributes); + } + + public Builder fieldName(String fieldName) { + this.fieldName = FieldName.of(fieldName); + return this; + } + + public Builder fieldName(FieldName fieldName) { + this.fieldName = fieldName; + return this; + } + + public Builder as(String attribute) { + this.fieldName.as(attribute); + return this; + } + + public Builder algorithm(VectorAlgorithm algorithm) { + this.algorithm = algorithm; + return this; + } + + public Builder attributes(Map attributes) { + this.attributes = attributes; + return this; + } + + public Builder addAttribute(String name, Object value) { + if (this.attributes == null) { + this.attributes = new LinkedHashMap<>(); + } + this.attributes.put(name, value); + return this; + } + } +} diff --git a/src/main/java/redis/clients/jedis/timeseries/AggregationType.java b/src/main/java/redis/clients/jedis/timeseries/AggregationType.java index 46a95232f2..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; @@ -8,7 +9,8 @@ public enum AggregationType implements Rawable { AVG, SUM, MIN, MAX, RANGE, COUNT, FIRST, LAST, STD_P("STD.P"), STD_S("STD.S"), - VAR_P("VAR.P"), VAR_S("VAR.S"); + VAR_P("VAR.P"), VAR_S("VAR.S"), + TWA; private final byte[] raw; @@ -24,4 +26,12 @@ private AggregationType(String alt) { public byte[] getRaw() { return raw; } + + public static AggregationType safeValueOf(String str) { + try { + 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 b5fca662e7..c002b94c08 100644 --- a/src/main/java/redis/clients/jedis/timeseries/RedisTimeSeriesCommands.java +++ b/src/main/java/redis/clients/jedis/timeseries/RedisTimeSeriesCommands.java @@ -97,8 +97,11 @@ public interface RedisTimeSeriesCommands { /** * {@code TS.RANGE key fromTimestamp toTimestamp - * [FILTER_BY_TS TS1 TS2 ..] [FILTER_BY_VALUE min max] - * [COUNT count] [ALIGN value] [AGGREGATION aggregationType timeBucket]} + * [LATEST] + * [FILTER_BY_TS ts...] + * [FILTER_BY_VALUE min max] + * [COUNT count] + * [[ALIGN value] AGGREGATION aggregator bucketDuration [BUCKETTIMESTAMP bt] [EMPTY]]} * * @param key * @param rangeParams @@ -118,8 +121,11 @@ public interface RedisTimeSeriesCommands { /** * {@code TS.REVRANGE key fromTimestamp toTimestamp - * [FILTER_BY_TS TS1 TS2 ..] [FILTER_BY_VALUE min max] - * [COUNT count] [ALIGN value] [AGGREGATION aggregationType timeBucket]} + * [LATEST] + * [FILTER_BY_TS TS...] + * [FILTER_BY_VALUE min max] + * [COUNT count] + * [[ALIGN value] AGGREGATION aggregator bucketDuration [BUCKETTIMESTAMP bt] [EMPTY]]} * * @param key * @param rangeParams @@ -128,70 +134,82 @@ public interface RedisTimeSeriesCommands { List tsRevRange(String key, TSRangeParams rangeParams); /** - * {@code TS.MRANGE fromTimestamp toTimestamp} + * {@code TS.MRANGE fromTimestamp toTimestamp FILTER filter...} * * @param fromTimestamp * @param toTimestamp * @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 - * [FILTER_BY_TS TS1 TS2 ..] [FILTER_BY_VALUE min max] - * [WITHLABELS | SELECTED_LABELS label1 ..] - * [COUNT count] [ALIGN value] - * [AGGREGATION aggregationType timeBucket] - * FILTER filter.. - * [GROUPBY