mirror of
https://github.com/predis/predis.git
synced 2026-08-19 21:41:49 +00:00
Compare commits
75 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| be75254ab6 | |||
| 07105e0506 | |||
| 07dc6ba6d2 | |||
| 5142011581 | |||
| c4b9c34d86 | |||
| f49e13ee3a | |||
| 6e3e2c0e78 | |||
| c35c422eda | |||
| 1b5ed7d516 | |||
| 5df852f227 | |||
| 9418df1924 | |||
| 0e4b3829a7 | |||
| 65f6127fab | |||
| 7ff24b19ae | |||
| 2babfc91d7 | |||
| fdd52d0284 | |||
| 48a861053e | |||
| 7bf1f6eb29 | |||
| 067b051900 | |||
| df4a318b80 | |||
| a904a3a273 | |||
| 8b240d15a5 | |||
| 02e2a7e1cc | |||
| 9a22450a65 | |||
| ac933cc548 | |||
| 355faa099f | |||
| 549889b198 | |||
| d1c657aac5 | |||
| b196809d3a | |||
| 52489ea703 | |||
| ba66e22c92 | |||
| 37aa6fb515 | |||
| deed24c418 | |||
| 93895d02b6 | |||
| 275606843e | |||
| 976c9daa4f | |||
| 205ae75bd8 | |||
| a5f46d0913 | |||
| b36c2f928f | |||
| bf6e97e7fb | |||
| da40e1253c | |||
| bac46bfdb7 | |||
| 7631d317fd | |||
| aaec13d074 | |||
| 52bdcf0c1f | |||
| 1726db0f47 | |||
| 8fbd34c6b3 | |||
| 0a92618fa1 | |||
| d8bb9ac46e | |||
| 274e0c17cd | |||
| c27dafa40d | |||
| 8c2aac4f66 | |||
| 5d22ed775a | |||
| c5fdfc81ef | |||
| cbef71090b | |||
| 4dc72458e8 | |||
| e83b393e09 | |||
| ed90750c1f | |||
| 45b18eb2e0 | |||
| d44f07339a | |||
| a9d18b182c | |||
| 5c8b19ebaa | |||
| 577bd39872 | |||
| 6372661dbf | |||
| 4846e2ab94 | |||
| 92b284967e | |||
| 08d5298080 | |||
| d88153b63e | |||
| b1d3255ed9 | |||
| cbf394b882 | |||
| c6bf644872 | |||
| 16bdd83d23 | |||
| 912af82bfd | |||
| 2d74db1bde | |||
| c5ee202179 |
+1
-1
@@ -3,4 +3,4 @@ skip=./.git
|
||||
check-hidden=
|
||||
check-filenames=
|
||||
builtin=clear,rare,informal,usage,code,names
|
||||
ignore-words-list=master,masters,slave,slaves,whitelist,cas,exat,smove,SUGGET,sugget,ro
|
||||
ignore-words-list=master,masters,slave,slaves,whitelist,cas,exat,smove,SUGGET,sugget,ro,DOF,dof
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
coverage_clover: build/logs/clover-*.xml
|
||||
@@ -17,6 +17,9 @@ max_line_length = 150
|
||||
[*.{md,yml,yaml,neon,sh}]
|
||||
indent_size = 2
|
||||
|
||||
[VERSION]
|
||||
insert_final_newline = false
|
||||
|
||||
[tests/**.php]
|
||||
max_line_length = unset
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
/examples export-ignore
|
||||
/tests export-ignore
|
||||
/.codespellrc export-ignore linguist-language=INI
|
||||
/.coveralls.yml export-ignore
|
||||
/.editorconfig export-ignore
|
||||
/.gitattributes export-ignore
|
||||
/.gitignore export-ignore
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
---
|
||||
|
||||
services:
|
||||
|
||||
redis-official:
|
||||
image: ${REDIS_IMAGE_NAME:-redis:7.4}
|
||||
container_name: redis-standalone
|
||||
healthcheck:
|
||||
test: [ "CMD", "redis-cli", "PING" ]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
ports:
|
||||
- "6379:6379"
|
||||
profiles:
|
||||
- all
|
||||
- official
|
||||
- standalone
|
||||
|
||||
redis-clients:
|
||||
image: ${REDIS_IMAGE_NAME:-redislabs/client-libs-test:7.4.2}
|
||||
container_name: redis-standalone
|
||||
environment:
|
||||
- TLS_ENABLED=yes
|
||||
- REDIS_CLUSTER=no
|
||||
- PORT=6379
|
||||
- TLS_PORT=6666
|
||||
command: ${REDIS_EXTRA_ARGS:---enable-debug-command yes --enable-module-command yes --tls-auth-clients optional --save ""}
|
||||
ports:
|
||||
- 6379:6379
|
||||
- 6666:6666 # TLS port
|
||||
volumes:
|
||||
- "./dockers/standalone:/redis/work"
|
||||
profiles:
|
||||
- all
|
||||
- clients
|
||||
- standalone
|
||||
|
||||
redis-cluster:
|
||||
image: ${REDIS_IMAGE_NAME:-redislabs/client-libs-test:7.4.2}
|
||||
container_name: redis-cluster
|
||||
environment:
|
||||
- REDIS_CLUSTER=yes
|
||||
- NODES=6
|
||||
- REPLICAS=1
|
||||
- TLS_ENABLED=yes
|
||||
- PORT=16379
|
||||
- TLS_PORT=27379
|
||||
command: ${REDIS_EXTRA_ARGS:---enable-debug-command yes --enable-module-command yes --tls-auth-clients optional --save ""}
|
||||
ports:
|
||||
- "6372-6377:16379-16384"
|
||||
volumes:
|
||||
- "./dockers/cluster:/redis/work"
|
||||
profiles:
|
||||
- all
|
||||
- clients
|
||||
- cluster
|
||||
|
||||
redis-stack:
|
||||
image: ${REDIS_STACK_IMAGE_NAME:-redislabs/client-libs-test:rs-7.4.0-v2}
|
||||
container_name: redis-stack
|
||||
ports:
|
||||
- "6479:6379"
|
||||
environment:
|
||||
- REDIS_CLUSTER=no
|
||||
- PORT=6379
|
||||
command: ${REDIS_EXTRA_ARGS:---enable-debug-command yes --enable-module-command yes --save ""}
|
||||
volumes:
|
||||
- "./dockers/redis-stack:/redis/work"
|
||||
profiles:
|
||||
- all
|
||||
- clients
|
||||
- stack
|
||||
@@ -136,7 +136,7 @@ jobs:
|
||||
EXPECTED="LICENSE,README.md,autoload.php,composer.json"
|
||||
CURRENT="$(
|
||||
git archive HEAD \
|
||||
| tar --list --exclude="src" --exclude="src/*" --exclude="bin" --exclude="bin/*" --exclude="docker" --exclude="docker/*" \
|
||||
| tar --list --exclude="src" --exclude="src/*" --exclude="bin" --exclude="bin/*" \
|
||||
| paste --serial --delimiters=","
|
||||
)"
|
||||
echo "CURRENT =${CURRENT}"
|
||||
@@ -165,3 +165,32 @@ jobs:
|
||||
|
||||
- name: Search for misspellings
|
||||
run: $(python -m site --user-base)/bin/codespell
|
||||
|
||||
changelog:
|
||||
|
||||
name: Changelog
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
|
||||
if: >-
|
||||
github.event_name == 'pull_request' &&
|
||||
!contains(github.event.head_commit.message, 'nochangelog') &&
|
||||
!contains(github.event.head_commit.message, 'no-changelog') &&
|
||||
!contains(github.event.head_commit.message, 'no changelog') &&
|
||||
!contains(github.event.pull_request.labels.*.name, 'no-changelog')
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Check for CHANGELOG entry
|
||||
env:
|
||||
TARGET: ${{ github.event.pull_request.base.ref }}
|
||||
run: |
|
||||
FILES_CHANGED=$(git diff --name-only origin/$TARGET...HEAD | grep -E 'CHANGELOG\.md' -c)
|
||||
if [ "$FILES_CHANGED" != "1" ]; then
|
||||
echo "CHANGELOG.md was not updated";
|
||||
exit 1;
|
||||
fi;
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
name: Stack
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- v2.**
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
|
||||
predis:
|
||||
name: PHP ${{ matrix.php }} (Redis Stack ${{ matrix.redis }})
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
services:
|
||||
redis:
|
||||
image: redis/redis-stack-server:${{ matrix.redis }}
|
||||
options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3
|
||||
ports:
|
||||
- 6379:6379
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php:
|
||||
- '7.2'
|
||||
- '7.3'
|
||||
- '7.4'
|
||||
- '8.0'
|
||||
- '8.1'
|
||||
- '8.2'
|
||||
redis:
|
||||
- latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup PHP with Composer and extensions
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
extensions: relay
|
||||
|
||||
- name: Get Composer cache directory
|
||||
id: composer-cache
|
||||
run: echo "directory=$(composer config cache-dir)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Cache Composer dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ steps.composer-cache.outputs.directory }}
|
||||
key: tests-php-${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: tests-php-${{ matrix.php }}-composer
|
||||
|
||||
- name: Install Composer dependencies
|
||||
env:
|
||||
PHP_VERSION: ${{ matrix.php }}
|
||||
run: composer install --ansi --no-progress --prefer-dist
|
||||
|
||||
- name: Run tests
|
||||
run: vendor/bin/phpunit --group realm-stack
|
||||
|
||||
- name: Run tests using Relay
|
||||
run: vendor/bin/phpunit --group realm-stack -c phpunit.relay.xml
|
||||
+125
-65
@@ -22,36 +22,86 @@ jobs:
|
||||
matrix:
|
||||
php:
|
||||
- '7.2'
|
||||
- '7.3'
|
||||
- '8.0'
|
||||
- '8.3'
|
||||
- '8.4'
|
||||
redis:
|
||||
- '4.0'
|
||||
- '6.2'
|
||||
- '7.2'
|
||||
- '7.4'
|
||||
- '8.0'
|
||||
- '8.1'
|
||||
- '8.2'
|
||||
redis:
|
||||
- 3
|
||||
- 4
|
||||
- 5
|
||||
- 6
|
||||
- 7
|
||||
|
||||
services:
|
||||
redis:
|
||||
image: redis:${{ matrix.redis }}
|
||||
options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3
|
||||
ports:
|
||||
- 6379:6379
|
||||
|
||||
steps:
|
||||
|
||||
- name: Resolve container name
|
||||
run: |
|
||||
# Mapping of original redis versions to client test containers
|
||||
declare -A redis_clients_version_mapping=(
|
||||
["8.0"]="8.0-RC2-pre"
|
||||
["7.4"]="7.4.2"
|
||||
["7.2"]="7.2.7"
|
||||
["6.2"]="6.2.17"
|
||||
)
|
||||
|
||||
# Mapping of redis version to stack version
|
||||
declare -A redis_stack_version_mapping=(
|
||||
["7.4"]="rs-7.4.0-v3"
|
||||
["7.2"]="rs-7.2.0-v15"
|
||||
["6.2"]="rs-6.2.6-v19"
|
||||
)
|
||||
|
||||
if [[ -v redis_clients_version_mapping[${{ matrix.redis }}] ]]; then
|
||||
echo "REDIS_IMAGE_NAME=redislabs/client-libs-test:${redis_clients_version_mapping[${{ matrix.redis }}]}" >> $GITHUB_ENV
|
||||
echo "REDIS_STACK_IMAGE_NAME=redislabs/client-libs-test:${redis_stack_version_mapping[${{ matrix.redis }}]}" >> $GITHUB_ENV
|
||||
echo "DOCKER_SERVICE=redis-clients" >> $GITHUB_ENV
|
||||
|
||||
redis_major_version=$(echo "${{ matrix.redis }}" | grep -oP '^\d+')
|
||||
|
||||
# Some configuration options available since Redis > 7
|
||||
if (( redis_major_version < 7 )); then
|
||||
echo "REDIS_EXTRA_ARGS="--tls-auth-clients optional --save ''"" >> $GITHUB_ENV
|
||||
else
|
||||
# Since 8.0 modules are bundled with core
|
||||
echo "REDIS_STACK_SERVER_PORT=6379" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
else
|
||||
echo "REDIS_IMAGE_NAME=redis:${{ matrix.redis }}" >> $GITHUB_ENV
|
||||
echo "DOCKER_SERVICE=redis-official" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup PHP with Composer and extensions
|
||||
- name: Start Redis standalone image
|
||||
uses: hoverkraft-tech/compose-action@v2.0.1
|
||||
with:
|
||||
compose-file: .github/docker-compose.yml
|
||||
services: ${{ env.DOCKER_SERVICE }}
|
||||
|
||||
- name: Start Redis stack image
|
||||
id: stack_infra
|
||||
uses: hoverkraft-tech/compose-action@v2.0.1
|
||||
if: ${{ matrix.redis >= '6.2' && matrix.redis < '8.0' }}
|
||||
with:
|
||||
compose-file: .github/docker-compose.yml
|
||||
services: redis-stack
|
||||
|
||||
- name: Start Redis cluster image
|
||||
id: cluster_infra
|
||||
uses: hoverkraft-tech/compose-action@v2.0.1
|
||||
if: ${{ matrix.redis > '4.0' }}
|
||||
with:
|
||||
compose-file: .github/docker-compose.yml
|
||||
services: redis-cluster
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
extensions: relay
|
||||
coverage: ${{ (matrix.php == '8.1' && matrix.redis == '7') && 'xdebug' || 'none' }}
|
||||
coverage: ${{ (matrix.php == '8.4' && matrix.redis == '7.4') && 'xdebug' || 'none' }}
|
||||
|
||||
- name: Install Composer dependencies
|
||||
uses: ramsey/composer-install@v2
|
||||
@@ -60,64 +110,74 @@ jobs:
|
||||
composer-options: ${{ matrix.php == '8.0' && '--ignore-platform-reqs' || '' }}
|
||||
|
||||
- name: Run tests
|
||||
if: ${{ matrix.php != '8.1' || matrix.redis != '7' }}
|
||||
if: ${{ matrix.php != '8.4' || matrix.redis != '7.4' }}
|
||||
run: vendor/bin/phpunit
|
||||
|
||||
- name: Run tests with coverage
|
||||
if: ${{ matrix.php == '8.1' && matrix.redis == '7' }}
|
||||
run: vendor/bin/phpunit --coverage-clover build/logs/clover.xml --coverage-filter ./src
|
||||
if: ${{ matrix.php == '8.4' && matrix.redis == '7.4' }}
|
||||
run: vendor/bin/phpunit --coverage-php build/cov/coverage-predis.cov --coverage-filter ./src
|
||||
|
||||
- name: Run tests using Relay
|
||||
if: ${{ matrix.redis >= '6' }}
|
||||
if: ${{ matrix.php != '8.4' && matrix.redis >= '6.2' }}
|
||||
run: vendor/bin/phpunit -c phpunit.relay.xml
|
||||
|
||||
- name: Send coverage to Coveralls
|
||||
- name: Run tests using Relay with coverage
|
||||
if: ${{ matrix.php == '8.4' && matrix.redis == '7.4' }}
|
||||
run: vendor/bin/phpunit -c phpunit.relay.xml --coverage-php build/cov/coverage-relay.cov --coverage-filter ./src
|
||||
|
||||
- name: Run stack tests
|
||||
if: ${{ (matrix.php != '8.4' || matrix.redis != '7.4') && matrix.redis >= '6.2' }}
|
||||
run: vendor/bin/phpunit --group realm-stack
|
||||
|
||||
- name: Run stack tests with coverage
|
||||
if: ${{ matrix.php == '8.4' && matrix.redis == '7.4' && steps.stack_infra.conclusion == 'success' }}
|
||||
run: vendor/bin/phpunit --group realm-stack --coverage-php build/cov/coverage-stack.cov --coverage-filter ./src
|
||||
env:
|
||||
COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
if: ${{ env.COVERALLS_REPO_TOKEN && matrix.php == '8.1' && matrix.redis == '7' }}
|
||||
run: |
|
||||
wget "https://github.com/php-coveralls/php-coveralls/releases/download/v2.5.3/php-coveralls.phar"
|
||||
php ./php-coveralls.phar -v
|
||||
REDIS_STACK_SERVER_PORT: 6479
|
||||
|
||||
predis-cluster:
|
||||
- name: Run stack tests using Relay
|
||||
if: ${{ matrix.php != '8.4' && matrix.redis == '7.4' }}
|
||||
run: vendor/bin/phpunit --group realm-stack -c phpunit.relay.xml
|
||||
|
||||
name: PHP ${{ matrix.php }} (Redis Cluster latest)
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php:
|
||||
- '7.2'
|
||||
- '7.3'
|
||||
- '7.4'
|
||||
- '8.0'
|
||||
- '8.1'
|
||||
- '8.2'
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Run redis cluster
|
||||
uses: isbang/compose-action@v1.4.1
|
||||
with:
|
||||
compose-file: "./docker/unstable_cluster/docker-compose.yml"
|
||||
|
||||
- name: Setup PHP with Composer and extensions
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
extensions: relay
|
||||
coverage: ${{ (matrix.php == '8.1') && 'xdebug' || 'none' }}
|
||||
|
||||
- name: Install Composer dependencies
|
||||
uses: ramsey/composer-install@v2
|
||||
with:
|
||||
dependency-versions: highest
|
||||
composer-options: ${{ matrix.php == '8.0' && '--ignore-platform-reqs' || '' }}
|
||||
- name: Run stack tests using Relay with coverage
|
||||
if: ${{ matrix.php == '8.4' && matrix.redis == '7.4' }}
|
||||
run: vendor/bin/phpunit --group realm-stack -c phpunit.relay.xml --coverage-php build/cov/coverage-stack-relay.cov --coverage-filter ./src
|
||||
env:
|
||||
REDIS_STACK_SERVER_PORT: 6479
|
||||
|
||||
- name: Run tests against cluster
|
||||
if: ${{ (matrix.php != '8.4' || matrix.redis != '7.4') && steps.cluster_infra.conclusion == 'success' }}
|
||||
run: |
|
||||
sleep 5 # Timeout to make sure that docker image is setup
|
||||
vendor/bin/phpunit --group cluster
|
||||
|
||||
- name: Run tests against cluster with coverage
|
||||
if: ${{ matrix.php == '8.4' && matrix.redis == '7.4' && steps.cluster_infra.conclusion == 'success' }}
|
||||
run: |
|
||||
vendor/bin/phpunit --group cluster --coverage-php build/cov/coverage-cluster.cov --coverage-filter ./src
|
||||
|
||||
- name: Run tests against cluster using Relay
|
||||
if: ${{ matrix.php != '8.4' && matrix.redis == '7.4' }}
|
||||
run: |
|
||||
vendor/bin/phpunit -c phpunit.relay.xml --group cluster
|
||||
|
||||
- name: Merge coverage reports
|
||||
if: ${{ matrix.php == '8.4' && matrix.redis == '7.4' }}
|
||||
run: php vendor/bin/phpcov merge --clover build/logs/clover.xml build/cov
|
||||
|
||||
- name: Send coverage to Coveralls
|
||||
uses: coverallsapp/github-action@v2
|
||||
if: ${{ matrix.php == '8.4' && matrix.redis == '7.4' }}
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
parallel: true
|
||||
|
||||
finish:
|
||||
name: Finish Coverall
|
||||
needs: predis
|
||||
if: ${{ always() }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Coveralls Finished
|
||||
uses: coverallsapp/github-action@v2
|
||||
with:
|
||||
parallel-finished: true
|
||||
|
||||
+25
-16
@@ -4,27 +4,34 @@ $PREDIS_HEADER = <<<EOS
|
||||
This file is part of the Predis package.
|
||||
|
||||
(c) 2009-2020 Daniele Alessandri
|
||||
(c) 2021-2023 Till Krüss
|
||||
(c) 2021-2025 Till Krüss
|
||||
|
||||
For the full copyright and license information, please view the LICENSE
|
||||
file that was distributed with this source code.
|
||||
EOS;
|
||||
|
||||
return (new PhpCsFixer\Config)
|
||||
->setRules([
|
||||
'@PHP71Migration' => true,
|
||||
'header_comment' => ['header' => $PREDIS_HEADER],
|
||||
'@Symfony' => true,
|
||||
'phpdoc_separation' => false,
|
||||
'phpdoc_annotation_without_dot' => false,
|
||||
'no_superfluous_phpdoc_tags' => false,
|
||||
'no_unneeded_curly_braces' => false,
|
||||
'global_namespace_import' => true,
|
||||
'yoda_style' => false,
|
||||
'single_line_throw' => false,
|
||||
'concat_space' => ['spacing' => 'one'],
|
||||
'increment_style' => false,
|
||||
])
|
||||
$fixer = new PhpCsFixer\Config;
|
||||
|
||||
$fixer->setParallelConfig(
|
||||
\PhpCsFixer\Runner\Parallel\ParallelConfigFactory::detect()
|
||||
);
|
||||
|
||||
$fixer->setRules([
|
||||
'@PHP71Migration' => true,
|
||||
'header_comment' => ['header' => $PREDIS_HEADER],
|
||||
'@Symfony' => true,
|
||||
'phpdoc_separation' => false,
|
||||
'phpdoc_annotation_without_dot' => false,
|
||||
'no_superfluous_phpdoc_tags' => false,
|
||||
'no_unneeded_curly_braces' => false,
|
||||
'no_unneeded_braces' => false,
|
||||
'global_namespace_import' => true,
|
||||
'yoda_style' => false,
|
||||
'single_line_throw' => false,
|
||||
'concat_space' => ['spacing' => 'one'],
|
||||
'increment_style' => false,
|
||||
'trailing_comma_in_multiline' => ['after_heredoc' => true, 'elements' => ['array_destructuring', 'arrays']]
|
||||
])
|
||||
->setFinder(
|
||||
PhpCsFixer\Finder::create()
|
||||
->in(__DIR__ . '/bin')
|
||||
@@ -32,3 +39,5 @@ return (new PhpCsFixer\Config)
|
||||
->in(__DIR__ . '/src')
|
||||
->in(__DIR__ . '/tests')
|
||||
);
|
||||
|
||||
return $fixer;
|
||||
|
||||
@@ -1,5 +1,63 @@
|
||||
## Changelog
|
||||
|
||||
## v2.4.1 (2025-11-12)
|
||||
### Fixed
|
||||
- Fixed return type for `ZCOUNT` to be `int` (#1546)
|
||||
- Removed automatic `conn_uid` parameter assignment (#1551)
|
||||
|
||||
## v2.4.0 (2025-04-30)
|
||||
### Added
|
||||
- Added new hash-field expiration commands (#1520)
|
||||
- Added missing `FT._LIST` and `BITFIELD_RO` commands (#1521)
|
||||
|
||||
### Changed
|
||||
- Update `WATCH` command to accept `string|string[]` (#1476)
|
||||
- Optimize cluster slotmap with compact slot range object (#1493)
|
||||
|
||||
### Fixed
|
||||
- Fixed `EVAL_RO` cluster support (#1449)
|
||||
- Fixed PHP 8.4 compatibility with `stream_context_set_option()` (#1503)
|
||||
- Prevent named arguments runtime failure (#1509)
|
||||
- Mark `GEOSEARCH` as read-only to ensure execution on replica (#1481)
|
||||
- Fixed protocol loss during redis cluster `MOVED` / `ASK` (#1530)
|
||||
|
||||
### Maintenance
|
||||
- Added CI testing with Redis 8.0 (#1510)
|
||||
- Added test coverage for compatibility with Redis 8.0 (#1513)
|
||||
- Use parallel on PHP-CS-Fixer (#1489)
|
||||
|
||||
## v2.3.0 (2024-11-21)
|
||||
### Added
|
||||
- Added `GeoShapeField` field (#1467)
|
||||
- Added hash expiration commands (#1456)
|
||||
- Added support for time series `IGNORE` filter (#1458)
|
||||
- Added `XREAD` commands (#1459)
|
||||
- Added `NOVALUES` argument support to `HSCAN` (#1459)
|
||||
- Added support for search `INDEXMISSING` and `INDEXEMPTY` arguments (#1464)
|
||||
|
||||
### Changed
|
||||
- Explicitly mark nullable parameters as nullable (#1448)
|
||||
- Filter out available replicas based on link status flag (#1440)
|
||||
- Respect `prefix` for `ZPOPMIN`, `ZPOPMAX`, `ZMSCORE`, `LMOVE`, `BLMOVE`, `SMISMEMBER` and `GEOSEARCH` (#1451, #1453, #1455, #1468)
|
||||
- Updated test infrastructure (#1510)
|
||||
|
||||
### Fixed
|
||||
- Fixed Relay support when using Redis Cluster (#1397)
|
||||
- Fixed `cmsincrby()` type annotation (#1333)
|
||||
- Fixed `set()` type annotation (#1394)
|
||||
- Fixed operator precedence in connection factory (#1405)
|
||||
- Fixed a bug with `null` arguments in `set()` method (#1470, #1471)
|
||||
|
||||
## v2.2.2 (2023-09-13)
|
||||
|
||||
### Added
|
||||
- Added `client_info` client parameter
|
||||
- Added support for `CLUSTER` container command
|
||||
|
||||
### Fixed
|
||||
- Fixed `EXPIRETIME` not using `prefix`
|
||||
- Disabled `CLIENT SETINFO` calls by default
|
||||
|
||||
## v2.2.1 (2023-08-15)
|
||||
|
||||
### Added
|
||||
|
||||
@@ -33,7 +33,7 @@ but significantly reduces bytes sent over the network and Redis memory usage.
|
||||
|
||||
Without Relay, Predis will not serialize data and will never do that by default. The reason
|
||||
behind this decision is that serialization is usually something that developers prefer to
|
||||
customize depending on their needs and can not be easilygeneralized when using Redis because
|
||||
customize depending on their needs and can not be easily generalized when using Redis because
|
||||
of the many possible access patterns for your data. This does not mean that it is impossible
|
||||
to have such a feature since you can leverage the extensibility of this library to define
|
||||
your own serialization-aware commands. You can find more details about how to do that
|
||||
@@ -81,65 +81,17 @@ An exception to this rule is [`SORT`](http://redis.io/commands/sort) for which m
|
||||
|
||||
## When should I use Relay? ##
|
||||
|
||||
If you care about performance, __always__. [Relay](https://github.com/cachewerk/relay) is free to use.
|
||||
If you care about performance, __always__. [Relay][relay] is free to use.
|
||||
|
||||
## When should I use PhpRedis? ###
|
||||
|
||||
Predis is fast enough when Redis is located on the same machine as PHP, more on that later.
|
||||
Predis is fast enough when Redis is located on the same machine as PHP.
|
||||
|
||||
[PhpRedis](https://github.com/phpredis/phpredis) (and Relay) perform significantly better when
|
||||
network I/O is involved, due to their ability to compress data by ~75%. Fewer bytes and received
|
||||
sent over the network [means faster operations](https://akalongman.medium.com/phpredis-vs-predis-comparison-on-real-production-data-a819b48cbadb),
|
||||
and potentially cost savings when network traffic isn't free (e.g. AWS Elasticache Inter-AZ transfer costs).
|
||||
[PhpRedis][phpredis] and [Relay][relay] perform significantly better when network I/O is involved,
|
||||
due to its ability to compress data by ~75%. Fewer bytes and received sent over the network
|
||||
[means faster operations][performance], and potentially cost savings when network traffic isn't
|
||||
free (e.g. AWS ElastiCache Inter-AZ transfer costs).
|
||||
|
||||
## Predis is a pure-PHP implementation: it can not be fast enough! ##
|
||||
|
||||
It really depends, but most of the times the answer is: _yes, it is fast enough_. I will give you a
|
||||
couple of easy numbers with a simple test that uses a single client and is executed by PHP 5.5.6
|
||||
against a local instance of Redis 2.8 that runs under Ubuntu 13.10 on a Intel Q6600:
|
||||
|
||||
```
|
||||
21000 SET/sec using 12 bytes for both key and value.
|
||||
21000 GET/sec while retrieving the very same values.
|
||||
0.130 seconds to fetch 30000 keys using _KEYS *_.
|
||||
```
|
||||
|
||||
How does it compare with [__PhpRedis__](http://github.com/phpredis/phpredis), a nice C extension
|
||||
providing an efficient client for Redis?
|
||||
|
||||
```
|
||||
30100 SET/sec using 12 bytes for both key and value
|
||||
29400 GET/sec while retrieving the very same values
|
||||
0.035 seconds to fetch 30000 keys using "KEYS *"".
|
||||
```
|
||||
|
||||
Wow __PhpRedis__ seems much faster! Well, we are comparing a C extension with a pure-PHP library so
|
||||
lower numbers are quite expected but there is a fundamental flaw in them: is this really how you are
|
||||
going to use Redis in your application? Are you really going to send thousands of commands using a
|
||||
for-loop on each page request using a single client instance? If so... well I guess you are probably
|
||||
doing something wrong. Also, if you need to `SET` or `GET` multiple keys you should definitely use
|
||||
commands such as `MSET` and `MGET`. You can also use pipelining to get more performances when this
|
||||
technique can be used.
|
||||
|
||||
There is one more thing: we have tested the overhead of Predis by connecting on a localhost instance
|
||||
of Redis but how these numbers change when we hit the physical network by connecting to remote Redis
|
||||
instances?
|
||||
|
||||
```
|
||||
Using Predis:
|
||||
3200 SET/sec using 12 bytes for both key and value
|
||||
3200 GET/sec while retrieving the very same values
|
||||
0.132 seconds to fetch 30000 keys using "KEYS *".
|
||||
|
||||
Using PhpRedis:
|
||||
3500 SET/sec using 12 bytes for both key and value
|
||||
3500 GET/sec while retrieving the very same values
|
||||
0.045 seconds to fetch 30000 keys using "KEYS *".
|
||||
```
|
||||
|
||||
There you go, you get almost the same average numbers and the reason is simple: network latency is a
|
||||
real performance killer and you cannot do (almost) anything about that. As a disclaimer, remember
|
||||
that we are measuring the overhead of client libraries implementations and the effects of network
|
||||
round-trip times, so we are not really measuring how fast Redis is. Redis shines best with thousands
|
||||
of concurrent clients doing requests! Also, actual performances should be measured according to how
|
||||
your application will use Redis.
|
||||
[phpredis]: https://github.com/phpredis/phpredis
|
||||
[relay]: [https://github.com/phpredis/phpredis](https://github.com/cachewerk/relay)
|
||||
[performance]: https://akalongman.medium.com/phpredis-vs-predis-comparison-on-real-production-data-a819b48cbadb
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2009-2020 Daniele Alessandri (original work)
|
||||
Copyright (c) 2021-2023 Till Krüss (modified work)
|
||||
Copyright (c) 2021-2024 Till Krüss (modified work)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
[![Build status][ico-build]][link-actions]
|
||||
[![Coverage Status][ico-coverage]][link-coverage]
|
||||
|
||||
A flexible and feature-complete [Redis](http://redis.io) client for PHP 7.2 and newer.
|
||||
A flexible and feature-complete [Redis](http://redis.io) / [Valkey](https://github.com/valkey-io/valkey) client for PHP 7.2 and newer.
|
||||
|
||||
More details about this project can be found on the [frequently asked questions](FAQ.md).
|
||||
|
||||
|
||||
## Main features ##
|
||||
|
||||
- Support for Redis from __3.0__ to __7.0__.
|
||||
- Support for Redis from __3.0__ to __8.0__.
|
||||
- Support for clustering using client-side sharding and pluggable keyspace distributors.
|
||||
- Support for [redis-cluster](http://redis.io/topics/cluster-tutorial) (Redis >= 3.0).
|
||||
- Support for master-slave replication setups and [redis-sentinel](http://redis.io/topics/sentinel).
|
||||
@@ -138,6 +138,50 @@ it is still desired to have control of when the connection is opened or closed:
|
||||
achieved by invoking `$client->connect()` and `$client->disconnect()`. Please note that the effect
|
||||
of these methods on aggregate connections may differ depending on each specific implementation.
|
||||
|
||||
#### Persistent connections ####
|
||||
|
||||
To increase a performance of your application you may set up a client to use persistent TCP connection, this way
|
||||
client saves a time on socket creation and connection handshake. By default, connection is created on first-command
|
||||
execution and will be automatically closed by GC before the process is being killed.
|
||||
However, if your application is backed by PHP-FPM the processes are idle, and you may set up it to be persistent and
|
||||
reusable across multiple script execution within the same process.
|
||||
|
||||
To enable the persistent connection mode you should provide following configuration:
|
||||
|
||||
```php
|
||||
// Standalone
|
||||
$client = new Predis\Client(['persistent' => true]);
|
||||
|
||||
// Cluster
|
||||
$client = new Predis\Client(
|
||||
['tcp://host:port', 'tcp://host:port', 'tcp://host:port'],
|
||||
['cluster' => 'redis', 'parameters' => ['persistent' => true]]
|
||||
);
|
||||
```
|
||||
|
||||
**Important**
|
||||
|
||||
If you operate on multiple clients within the same application, and they communicate with the same resource, by default
|
||||
they will share the same socket (that's the default behaviour of persistent sockets). So in this case you would need
|
||||
to additionally provide a `conn_uid` identifier for each client, this way each client will create its own socket so
|
||||
the connection context won't be shared across clients. This socket behaviour explained
|
||||
[here](https://www.php.net/manual/en/function.stream-socket-client.php#105393)
|
||||
|
||||
```php
|
||||
// Standalone
|
||||
$client1 = new Predis\Client(['persistent' => true, 'conn_uid' => 'id_1']);
|
||||
$client2 = new Predis\Client(['persistent' => true, 'conn_uid' => 'id_2']);
|
||||
|
||||
// Cluster
|
||||
$client1 = new Predis\Client(
|
||||
['tcp://host:port', 'tcp://host:port', 'tcp://host:port'],
|
||||
['cluster' => 'redis', 'parameters' => ['persistent' => true, 'conn_uid' => 'id_1']]
|
||||
);
|
||||
$client2 = new Predis\Client(
|
||||
['tcp://host:port', 'tcp://host:port', 'tcp://host:port'],
|
||||
['cluster' => 'redis', 'parameters' => ['persistent' => true, 'conn_uid' => 'id_2']]
|
||||
);
|
||||
```
|
||||
|
||||
### Client configuration ###
|
||||
|
||||
|
||||
+3
-2
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "predis/predis",
|
||||
"type": "library",
|
||||
"description": "A flexible and feature-complete Redis client for PHP.",
|
||||
"description": "A flexible and feature-complete Redis/Valkey client for PHP.",
|
||||
"keywords": ["nosql", "redis", "predis"],
|
||||
"homepage": "http://github.com/predis/predis",
|
||||
"license": "MIT",
|
||||
@@ -27,7 +27,8 @@
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^3.3",
|
||||
"phpstan/phpstan": "^1.9",
|
||||
"phpunit/phpunit": "^8.0 || ~9.4.4"
|
||||
"phpunit/phpunit": "^8.0 || ^9.4",
|
||||
"phpunit/phpcov": "^6.0 || ^8.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-relay": "Faster connection with in-memory caching (>=0.6.2)"
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
FROM redis/redis-stack-server:latest as rss
|
||||
|
||||
COPY create_cluster.sh /create_cluster.sh
|
||||
RUN ls -R /opt/redis-stack
|
||||
RUN chmod a+x /create_cluster.sh
|
||||
|
||||
ENTRYPOINT [ "/create_cluster.sh"]
|
||||
@@ -1,47 +0,0 @@
|
||||
#! /bin/bash
|
||||
|
||||
mkdir -p /nodes
|
||||
touch /nodes/nodemap
|
||||
if [ -z ${START_PORT} ]; then
|
||||
START_PORT=6372
|
||||
fi
|
||||
if [ -z ${END_PORT} ]; then
|
||||
END_PORT=6377
|
||||
fi
|
||||
if [ ! -z "$3" ]; then
|
||||
START_PORT=$2
|
||||
START_PORT=$3
|
||||
fi
|
||||
echo "STARTING: ${START_PORT}"
|
||||
echo "ENDING: ${END_PORT}"
|
||||
|
||||
for PORT in `seq ${START_PORT} ${END_PORT}`; do
|
||||
mkdir -p /nodes/$PORT
|
||||
if [[ -e /redis.conf ]]; then
|
||||
cp /redis.conf /nodes/$PORT/redis.conf
|
||||
else
|
||||
touch /nodes/$PORT/redis.conf
|
||||
fi
|
||||
cat << EOF >> /nodes/$PORT/redis.conf
|
||||
port ${PORT}
|
||||
cluster-enabled yes
|
||||
daemonize yes
|
||||
logfile /redis.log
|
||||
dir /nodes/$PORT
|
||||
EOF
|
||||
|
||||
set -x
|
||||
/opt/redis-stack/bin/redis-server /nodes/$PORT/redis.conf
|
||||
sleep 1
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Redis failed to start, exiting."
|
||||
continue
|
||||
fi
|
||||
echo 127.0.0.1:$PORT >> /nodes/nodemap
|
||||
done
|
||||
if [ -z "${REDIS_PASSWORD}" ]; then
|
||||
echo yes | /opt/redis-stack/bin/redis-cli --cluster create `seq -f 127.0.0.1:%g ${START_PORT} ${END_PORT}` --cluster-replicas 1
|
||||
else
|
||||
echo yes | opt/redis-stack/bin/redis-cli -a ${REDIS_PASSWORD} --cluster create `seq -f 127.0.0.1:%g ${START_PORT} ${END_PORT}` --cluster-replicas 1
|
||||
fi
|
||||
tail -f /redis.log
|
||||
@@ -1,17 +0,0 @@
|
||||
version: "3.9"
|
||||
services:
|
||||
cluster:
|
||||
container_name: redis-cluster
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- "6372:6372"
|
||||
- "6373:6373"
|
||||
- "6374:6374"
|
||||
- "6375:6375"
|
||||
- "6376:6376"
|
||||
- "6377:6378"
|
||||
volumes:
|
||||
- "./redis.conf:/redis.conf:ro"
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
# Redis Cluster config file will be shared across all nodes.
|
||||
# Do not change the following configurations that are already set:
|
||||
# port, cluster-enabled, daemonize, logfile, dir
|
||||
protected-mode no
|
||||
loadmodule /opt/redis-stack/lib/redisearch.so
|
||||
loadmodule /opt/redis-stack/lib/redisgraph.so
|
||||
loadmodule /opt/redis-stack/lib/redistimeseries.so
|
||||
loadmodule /opt/redis-stack/lib/rejson.so
|
||||
loadmodule /opt/redis-stack/lib/redisbloom.so
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -32,7 +32,7 @@ function zpop($client, $key)
|
||||
'cas' => true, // Initialize with support for CAS operations
|
||||
'watch' => $key, // Key that needs to be WATCHed to detect changes
|
||||
'retry' => 3, // Number of retries on aborted transactions, after
|
||||
// which the client bails out with an exception.
|
||||
// which the client bails out with an exception.
|
||||
];
|
||||
|
||||
$client->transaction($options, function ($tx) use ($key, &$element) {
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
<groups>
|
||||
<exclude>
|
||||
<group>relay-incompatible</group>
|
||||
<group>relay-resp3</group>
|
||||
<group>realm-webdis</group>
|
||||
<group>realm-stack</group>
|
||||
<group>ext-curl</group>
|
||||
@@ -39,6 +40,7 @@
|
||||
<const name="REDIS_SERVER_PORT" value="6379" />
|
||||
<const name="REDIS_SERVER_DBNUM" value="0" />
|
||||
<env name="USE_RELAY" value="true" />
|
||||
<env name="REDIS_STACK_SERVER_PORT" value="6479" />
|
||||
|
||||
<!-- Redis Cluster -->
|
||||
<!-- Only master nodes endpoints included -->
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
<const name="REDIS_SERVER_PORT" value="6379" />
|
||||
<const name="REDIS_SERVER_DBNUM" value="0" />
|
||||
<env name="USE_RELAY" value="false" />
|
||||
<env name="REDIS_STACK_SERVER_PORT" value="6479" />
|
||||
|
||||
<!-- Redis Cluster -->
|
||||
<!-- Only master nodes endpoints included -->
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
+9
-9
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -53,7 +53,7 @@ use Traversable;
|
||||
*/
|
||||
class Client implements ClientInterface, IteratorAggregate
|
||||
{
|
||||
public const VERSION = '2.2.1';
|
||||
public const VERSION = '2.4.2-dev';
|
||||
|
||||
/** @var OptionsInterface */
|
||||
private $options;
|
||||
@@ -472,7 +472,7 @@ class Client implements ClientInterface, IteratorAggregate
|
||||
*
|
||||
* @return Pipeline|array
|
||||
*/
|
||||
protected function createPipeline(array $options = null, $callable = null)
|
||||
protected function createPipeline(?array $options = null, $callable = null)
|
||||
{
|
||||
if (isset($options['atomic']) && $options['atomic']) {
|
||||
$class = Atomic::class;
|
||||
@@ -520,12 +520,12 @@ class Client implements ClientInterface, IteratorAggregate
|
||||
/**
|
||||
* Actual transaction context initializer method.
|
||||
*
|
||||
* @param array $options Options for the context.
|
||||
* @param mixed $callable Optional callable used to execute the context.
|
||||
* @param array|null $options Options for the context.
|
||||
* @param mixed $callable Optional callable used to execute the context.
|
||||
*
|
||||
* @return MultiExecTransaction|array
|
||||
*/
|
||||
protected function createTransaction(array $options = null, $callable = null)
|
||||
protected function createTransaction(?array $options = null, $callable = null)
|
||||
{
|
||||
$transaction = new MultiExecTransaction($this, $options);
|
||||
|
||||
@@ -552,12 +552,12 @@ class Client implements ClientInterface, IteratorAggregate
|
||||
/**
|
||||
* Actual publish/subscribe context initializer method.
|
||||
*
|
||||
* @param array $options Options for the context.
|
||||
* @param mixed $callable Optional callable used to execute the context.
|
||||
* @param array|null $options Options for the context.
|
||||
* @param mixed $callable Optional callable used to execute the context.
|
||||
*
|
||||
* @return PubSubConsumer|null
|
||||
*/
|
||||
protected function createPubSub(array $options = null, $callable = null)
|
||||
protected function createPubSub(?array $options = null, $callable = null)
|
||||
{
|
||||
if ($this->connection instanceof RelayConnection) {
|
||||
$pubsub = new RelayPubSubConsumer($this, $options);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -39,10 +39,13 @@ use Predis\Command\Argument\TimeSeries\MRangeArguments;
|
||||
use Predis\Command\Argument\TimeSeries\RangeArguments;
|
||||
use Predis\Command\CommandInterface;
|
||||
use Predis\Command\Redis\Container\ACL;
|
||||
use Predis\Command\Redis\Container\CLUSTER;
|
||||
use Predis\Command\Redis\Container\FunctionContainer;
|
||||
use Predis\Command\Redis\Container\Json\JSONDEBUG;
|
||||
use Predis\Command\Redis\Container\Search\FTCONFIG;
|
||||
use Predis\Command\Redis\Container\Search\FTCURSOR;
|
||||
use Predis\Command\Redis\HGETEX;
|
||||
use Predis\Command\Redis\HSETEX;
|
||||
|
||||
/**
|
||||
* Interface defining a client-side context such as a pipeline or transaction.
|
||||
@@ -64,8 +67,8 @@ use Predis\Command\Redis\Container\Search\FTCURSOR;
|
||||
* @method $this randomkey()
|
||||
* @method $this rename($key, $target)
|
||||
* @method $this renamenx($key, $target)
|
||||
* @method $this scan($cursor, array $options = null)
|
||||
* @method $this sort($key, array $options = null)
|
||||
* @method $this scan($cursor, ?array $options = null)
|
||||
* @method $this sort($key, ?array $options = null)
|
||||
* @method $this sort_ro(string $key, ?string $byPattern = null, ?LimitOffsetCount $limit = null, array $getPatterns = [], ?string $sorting = null, bool $alpha = false)
|
||||
* @method $this ttl($key)
|
||||
* @method $this type($key)
|
||||
@@ -82,6 +85,7 @@ use Predis\Command\Redis\Container\Search\FTCURSOR;
|
||||
* @method $this bitcount(string $key, $start = null, $end = null, string $index = 'byte')
|
||||
* @method $this bitop($operation, $destkey, $key)
|
||||
* @method $this bitfield($key, $subcommand, ...$subcommandArg)
|
||||
* @method $this bitfield_ro(string $key, ?array $encodingOffsetMap = null)
|
||||
* @method $this bitpos($key, $bit, $start = null, $end = null, string $index = 'byte')
|
||||
* @method $this blmpop(int $timeout, array $keys, string $modifier = 'left', int $count = 1)
|
||||
* @method $this bzpopmax(array $keys, int $timeout)
|
||||
@@ -110,6 +114,7 @@ use Predis\Command\Redis\Container\Search\FTCURSOR;
|
||||
* @method $this failover(?To $to = null, bool $abort = false, int $timeout = -1)
|
||||
* @method $this fcall(string $function, array $keys, ...$args)
|
||||
* @method $this fcall_ro(string $function, array $keys, ...$args)
|
||||
* @method $this ft_list()
|
||||
* @method $this ftaggregate(string $index, string $query, ?AggregateArguments $arguments = null)
|
||||
* @method $this ftaliasadd(string $alias, string $index)
|
||||
* @method $this ftaliasdel(string $alias)
|
||||
@@ -153,8 +158,17 @@ use Predis\Command\Redis\Container\Search\FTCURSOR;
|
||||
* @method $this strlen($key)
|
||||
* @method $this hdel($key, array $fields)
|
||||
* @method $this hexists($key, $field)
|
||||
* @method $this hexpire(string $key, int $seconds, array $fields, string $flag = null)
|
||||
* @method $this hexpireat(string $key, int $unixTimeSeconds, array $fields, string $flag = null)
|
||||
* @method $this hexpiretime(string $key, array $fields)
|
||||
* @method $this hpersist(string $key, array $fields)
|
||||
* @method $this hpexpire(string $key, int $milliseconds, array $fields, string $flag = null)
|
||||
* @method $this hpexpireat(string $key, int $unixTimeMilliseconds, array $fields, string $flag = null)
|
||||
* @method $this hpexpiretime(string $key, array $fields)
|
||||
* @method $this hget($key, $field)
|
||||
* @method $this hgetex(string $key, array $fields, string $modifier = HGETEX::NULL)
|
||||
* @method $this hgetall($key)
|
||||
* @method $this hgetdel(string $key, array $fields)
|
||||
* @method $this hincrby($key, $field, $increment)
|
||||
* @method $this hincrbyfloat($key, $field, $increment)
|
||||
* @method $this hkeys($key)
|
||||
@@ -162,9 +176,12 @@ use Predis\Command\Redis\Container\Search\FTCURSOR;
|
||||
* @method $this hmget($key, array $fields)
|
||||
* @method $this hmset($key, array $dictionary)
|
||||
* @method $this hrandfield(string $key, int $count = 1, bool $withValues = false)
|
||||
* @method $this hscan($key, $cursor, array $options = null)
|
||||
* @method $this hscan($key, $cursor, ?array $options = null)
|
||||
* @method $this hset($key, $field, $value)
|
||||
* @method $this hsetex(string $key, array $fieldValueMap, string $setModifier = HSETEX::SET_NULL, string $ttlModifier = HSETEX::TTL_NULL, int|bool $ttlModifierValue = false)
|
||||
* @method $this hsetnx($key, $field, $value)
|
||||
* @method $this httl(string $key, array $fields)
|
||||
* @method $this hpttl(string $key, array $fields)
|
||||
* @method $this hvals($key)
|
||||
* @method $this hstrlen($key, $field)
|
||||
* @method $this jsonarrappend(string $key, string $path = '$', ...$value)
|
||||
@@ -224,7 +241,7 @@ use Predis\Command\Redis\Container\Search\FTCURSOR;
|
||||
* @method $this spop($key, $count = null)
|
||||
* @method $this srandmember($key, $count = null)
|
||||
* @method $this srem($key, $member)
|
||||
* @method $this sscan($key, $cursor, array $options = null)
|
||||
* @method $this sscan($key, $cursor, ?array $options = null)
|
||||
* @method $this sunion(array|string $keys)
|
||||
* @method $this sunionstore($destination, array|string $keys)
|
||||
* @method $this tdigestadd(string $key, float ...$value)
|
||||
@@ -254,7 +271,7 @@ use Predis\Command\Redis\Container\Search\FTCURSOR;
|
||||
* @method $this tsdecrby(string $key, float $value, ?DecrByArguments $arguments = null)
|
||||
* @method $this tsdel(string $key, int $fromTimestamp, int $toTimestamp)
|
||||
* @method $this tsdeleterule(string $sourceKey, string $destKey)
|
||||
* @method $this tsget(string $key, GetArguments $arguments = null)
|
||||
* @method $this tsget(string $key, ?GetArguments $arguments = null)
|
||||
* @method $this tsincrby(string $key, float $value, ?IncrByArguments $arguments = null)
|
||||
* @method $this tsinfo(string $key, ?InfoArguments $arguments = null)
|
||||
* @method $this tsmadd(mixed ...$keyTimestampValue)
|
||||
@@ -276,22 +293,22 @@ use Predis\Command\Redis\Container\Search\FTCURSOR;
|
||||
* @method $this zmpop(array $keys, string $modifier = 'min', int $count = 1)
|
||||
* @method $this zmscore(string $key, string ...$member)
|
||||
* @method $this zrandmember(string $key, int $count = 1, bool $withScores = false)
|
||||
* @method $this zrange($key, $start, $stop, array $options = null)
|
||||
* @method $this zrangebyscore($key, $min, $max, array $options = null)
|
||||
* @method $this zrange($key, $start, $stop, ?array $options = null)
|
||||
* @method $this zrangebyscore($key, $min, $max, ?array $options = null)
|
||||
* @method $this zrangestore(string $destination, string $source, int|string $min, string|int $max, string|bool $by = false, bool $reversed = false, bool $limit = false, int $offset = 0, int $count = 0)
|
||||
* @method $this zrank($key, $member)
|
||||
* @method $this zrem($key, $member)
|
||||
* @method $this zremrangebyrank($key, $start, $stop)
|
||||
* @method $this zremrangebyscore($key, $min, $max)
|
||||
* @method $this zrevrange($key, $start, $stop, array $options = null)
|
||||
* @method $this zrevrangebyscore($key, $max, $min, array $options = null)
|
||||
* @method $this zrevrange($key, $start, $stop, ?array $options = null)
|
||||
* @method $this zrevrangebyscore($key, $max, $min, ?array $options = null)
|
||||
* @method $this zrevrank($key, $member)
|
||||
* @method $this zunion(array $keys, int[] $weights = [], string $aggregate = 'sum', bool $withScores = false)
|
||||
* @method $this zunionstore(string $destination, array $keys, int[] $weights = [], string $aggregate = 'sum')
|
||||
* @method $this zscore($key, $member)
|
||||
* @method $this zscan($key, $cursor, array $options = null)
|
||||
* @method $this zrangebylex($key, $start, $stop, array $options = null)
|
||||
* @method $this zrevrangebylex($key, $start, $stop, array $options = null)
|
||||
* @method $this zscan($key, $cursor, ?array $options = null)
|
||||
* @method $this zrangebylex($key, $start, $stop, ?array $options = null)
|
||||
* @method $this zrevrangebylex($key, $start, $stop, ?array $options = null)
|
||||
* @method $this zremrangebylex($key, $min, $max)
|
||||
* @method $this zlexcount($key, $min, $max)
|
||||
* @method $this pexpiretime(string $key)
|
||||
@@ -311,7 +328,7 @@ use Predis\Command\Redis\Container\Search\FTCURSOR;
|
||||
* @method $this evalsha($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
|
||||
* @method $this evalsha_ro(string $sha1, array $keys, ...$argument)
|
||||
* @method $this script($subcommand, $argument = null)
|
||||
* @method $this shutdown(bool $noSave = null, bool $now = false, bool $force = false, bool $abort = false)
|
||||
* @method $this shutdown(?bool $noSave = null, bool $now = false, bool $force = false, bool $abort = false)
|
||||
* @method $this auth($password)
|
||||
* @method $this echo($message)
|
||||
* @method $this ping($message = null)
|
||||
@@ -334,12 +351,13 @@ use Predis\Command\Redis\Container\Search\FTCURSOR;
|
||||
* @method $this geohash($key, array $members)
|
||||
* @method $this geopos($key, array $members)
|
||||
* @method $this geodist($key, $member1, $member2, $unit = null)
|
||||
* @method $this georadius($key, $longitude, $latitude, $radius, $unit, array $options = null)
|
||||
* @method $this georadiusbymember($key, $member, $radius, $unit, array $options = null)
|
||||
* @method $this georadius($key, $longitude, $latitude, $radius, $unit, ?array $options = null)
|
||||
* @method $this georadiusbymember($key, $member, $radius, $unit, ?array $options = null)
|
||||
* @method $this geosearch(string $key, FromInterface $from, ByInterface $by, ?string $sorting = null, int $count = -1, bool $any = false, bool $withCoord = false, bool $withDist = false, bool $withHash = false)
|
||||
* @method $this geosearchstore(string $destination, string $source, FromInterface $from, ByInterface $by, ?string $sorting = null, int $count = -1, bool $any = false, bool $storeDist = false)
|
||||
*
|
||||
* Container commands
|
||||
* @property CLUSTER $cluster
|
||||
* @property FunctionContainer $function
|
||||
* @property FTCONFIG $ftconfig
|
||||
* @property FTCURSOR $ftcursor
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
+46
-25
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -40,10 +40,13 @@ use Predis\Command\Argument\TimeSeries\RangeArguments;
|
||||
use Predis\Command\CommandInterface;
|
||||
use Predis\Command\FactoryInterface;
|
||||
use Predis\Command\Redis\Container\ACL;
|
||||
use Predis\Command\Redis\Container\CLUSTER;
|
||||
use Predis\Command\Redis\Container\FunctionContainer;
|
||||
use Predis\Command\Redis\Container\Json\JSONDEBUG;
|
||||
use Predis\Command\Redis\Container\Search\FTCONFIG;
|
||||
use Predis\Command\Redis\Container\Search\FTCURSOR;
|
||||
use Predis\Command\Redis\HGETEX;
|
||||
use Predis\Command\Redis\HSETEX;
|
||||
use Predis\Configuration\OptionsInterface;
|
||||
use Predis\Connection\ConnectionInterface;
|
||||
use Predis\Response\Status;
|
||||
@@ -73,8 +76,8 @@ use Predis\Response\Status;
|
||||
* @method string|null randomkey()
|
||||
* @method mixed rename(string $key, string $target)
|
||||
* @method int renamenx(string $key, string $target)
|
||||
* @method array scan($cursor, array $options = null)
|
||||
* @method array sort(string $key, array $options = null)
|
||||
* @method array scan($cursor, ?array $options = null)
|
||||
* @method array sort(string $key, ?array $options = null)
|
||||
* @method array sort_ro(string $key, ?string $byPattern = null, ?LimitOffsetCount $limit = null, array $getPatterns = [], ?string $sorting = null, bool $alpha = false)
|
||||
* @method int ttl(string $key)
|
||||
* @method mixed type(string $key)
|
||||
@@ -91,6 +94,7 @@ use Predis\Response\Status;
|
||||
* @method int bitcount(string $key, $start = null, $end = null, string $index = 'byte')
|
||||
* @method int bitop($operation, $destkey, $key)
|
||||
* @method array|null bitfield(string $key, $subcommand, ...$subcommandArg)
|
||||
* @method array|null bitfield_ro(string $key, ?array $encodingOffsetMap = null)
|
||||
* @method int bitpos(string $key, $bit, $start = null, $end = null, string $index = 'byte')
|
||||
* @method array blmpop(int $timeout, array $keys, string $modifier = 'left', int $count = 1)
|
||||
* @method array bzpopmax(array $keys, int $timeout)
|
||||
@@ -108,7 +112,7 @@ use Predis\Response\Status;
|
||||
* @method array cfinsertnx(string $key, int $capacity = -1, bool $noCreate = false, string ...$item)
|
||||
* @method Status cfreserve(string $key, int $capacity, int $bucketSize = -1, int $maxIterations = -1, int $expansion = -1)
|
||||
* @method array cfscandump(string $key, int $iterator)
|
||||
* @method array cmsincrby(string $key, string|int...$itemIncrementDictionary)
|
||||
* @method array cmsincrby(string $key, string|int ...$itemIncrementDictionary)
|
||||
* @method array cmsinfo(string $key)
|
||||
* @method Status cmsinitbydim(string $key, int $width, int $depth)
|
||||
* @method Status cmsinitbyprob(string $key, float $errorRate, float $probability)
|
||||
@@ -119,6 +123,7 @@ use Predis\Response\Status;
|
||||
* @method Status failover(?To $to = null, bool $abort = false, int $timeout = -1)
|
||||
* @method mixed fcall(string $function, array $keys, ...$args)
|
||||
* @method mixed fcall_ro(string $function, array $keys, ...$args)
|
||||
* @method array ft_list()
|
||||
* @method array ftaggregate(string $index, string $query, ?AggregateArguments $arguments = null)
|
||||
* @method Status ftaliasadd(string $alias, string $index)
|
||||
* @method Status ftaliasdel(string $alias)
|
||||
@@ -154,7 +159,7 @@ use Predis\Response\Status;
|
||||
* @method mixed mset(array $dictionary)
|
||||
* @method int msetnx(array $dictionary)
|
||||
* @method Status psetex(string $key, $milliseconds, $value)
|
||||
* @method Status set(string $key, $value, $expireResolution = null, $expireTTL = null, $flag = null)
|
||||
* @method Status|null set(string $key, $value, $expireResolution = null, $expireTTL = null, $flag = null)
|
||||
* @method int setbit(string $key, $offset, $value)
|
||||
* @method Status setex(string $key, $seconds, $value)
|
||||
* @method int setnx(string $key, $value)
|
||||
@@ -162,8 +167,17 @@ use Predis\Response\Status;
|
||||
* @method int strlen(string $key)
|
||||
* @method int hdel(string $key, array $fields)
|
||||
* @method int hexists(string $key, string $field)
|
||||
* @method array|null hexpire(string $key, int $seconds, array $fields, string $flag = null)
|
||||
* @method array|null hexpireat(string $key, int $unixTimeSeconds, array $fields, string $flag = null)
|
||||
* @method array|null hexpiretime(string $key, array $fields)
|
||||
* @method array|null hpersist(string $key, array $fields)
|
||||
* @method array|null hpexpire(string $key, int $milliseconds, array $fields, string $flag = null)
|
||||
* @method array|null hpexpireat(string $key, int $unixTimeMilliseconds, array $fields, string $flag = null)
|
||||
* @method array|null hpexpiretime(string $key, array $fields)
|
||||
* @method string|null hget(string $key, string $field)
|
||||
* @method array|null hgetex(string $key, array $fields, string $modifier = HGETEX::NULL, int|bool $modifierValue = false)
|
||||
* @method array hgetall(string $key)
|
||||
* @method array hgetdel(string $key, array $fields)
|
||||
* @method int hincrby(string $key, string $field, int $increment)
|
||||
* @method string hincrbyfloat(string $key, string $field, int|float $increment)
|
||||
* @method array hkeys(string $key)
|
||||
@@ -171,9 +185,12 @@ use Predis\Response\Status;
|
||||
* @method array hmget(string $key, array $fields)
|
||||
* @method mixed hmset(string $key, array $dictionary)
|
||||
* @method array hrandfield(string $key, int $count = 1, bool $withValues = false)
|
||||
* @method array hscan(string $key, $cursor, array $options = null)
|
||||
* @method array hscan(string $key, $cursor, ?array $options = null)
|
||||
* @method int hset(string $key, string $field, string $value)
|
||||
* @method int hsetex(string $key, array $fieldValueMap, string $setModifier = HSETEX::SET_NULL, string $ttlModifier = HSETEX::TTL_NULL, int|bool $ttlModifierValue = false)
|
||||
* @method int hsetnx(string $key, string $field, string $value)
|
||||
* @method array|null httl(string $key, array $fields)
|
||||
* @method array|null hpttl(string $key, array $fields)
|
||||
* @method array hvals(string $key)
|
||||
* @method int hstrlen(string $key, string $field)
|
||||
* @method array jsonarrappend(string $key, string $path = '$', ...$value)
|
||||
@@ -230,10 +247,10 @@ use Predis\Response\Status;
|
||||
* @method string[] smembers(string $key)
|
||||
* @method array smismember(string $key, string ...$members)
|
||||
* @method int smove(string $source, string $destination, string $member)
|
||||
* @method string|array|null spop(string $key, int $count = null)
|
||||
* @method string|null srandmember(string $key, int $count = null)
|
||||
* @method string|array|null spop(string $key, ?int $count = null)
|
||||
* @method string|null srandmember(string $key, ?int $count = null)
|
||||
* @method int srem(string $key, array|string $member)
|
||||
* @method array sscan(string $key, int $cursor, array $options = null)
|
||||
* @method array sscan(string $key, int $cursor, ?array $options = null)
|
||||
* @method string[] sunion(array|string $keys)
|
||||
* @method int sunionstore(string $destination, array|string $keys)
|
||||
* @method int touch(string[]|string $keyOrKeys, string ...$keys = null)
|
||||
@@ -264,7 +281,7 @@ use Predis\Response\Status;
|
||||
* @method int tsdecrby(string $key, float $value, ?DecrByArguments $arguments = null)
|
||||
* @method int tsdel(string $key, int $fromTimestamp, int $toTimestamp)
|
||||
* @method Status tsdeleterule(string $sourceKey, string $destKey)
|
||||
* @method array tsget(string $key, GetArguments $arguments = null)
|
||||
* @method array tsget(string $key, ?GetArguments $arguments = null)
|
||||
* @method int tsincrby(string $key, float $value, ?IncrByArguments $arguments = null)
|
||||
* @method array tsinfo(string $key, ?InfoArguments $arguments = null)
|
||||
* @method array tsmadd(mixed ...$keyTimestampValue)
|
||||
@@ -274,15 +291,16 @@ use Predis\Response\Status;
|
||||
* @method array tsqueryindex(string ...$filterExpression)
|
||||
* @method array tsrange(string $key, $fromTimestamp, $toTimestamp, ?RangeArguments $arguments = null)
|
||||
* @method array tsrevrange(string $key, $fromTimestamp, $toTimestamp, ?RangeArguments $arguments = null)
|
||||
* @method string xadd(string $key, array $dictionary, string $id = '*', array $options = null)
|
||||
* @method string xadd(string $key, array $dictionary, string $id = '*', ?array $options = null)
|
||||
* @method int xdel(string $key, string ...$id)
|
||||
* @method int xlen(string $key)
|
||||
* @method array xrevrange(string $key, string $end, string $start, ?int $count = null)
|
||||
* @method array xrange(string $key, string $start, string $end, ?int $count = null)
|
||||
* @method string xtrim(string $key, array|string $strategy, string $threshold, array $options = null)
|
||||
* @method string xtrim(string $key, array|string $strategy, string $threshold, ?array $options = null)
|
||||
* @method array|null xread(int $count = null, int $block = null, array $streams = null, string ...$id)
|
||||
* @method int zadd(string $key, array $membersAndScoresDictionary)
|
||||
* @method int zcard(string $key)
|
||||
* @method string zcount(string $key, int|string $min, int|string $max)
|
||||
* @method int zcount(string $key, int|string $min, int|string $max)
|
||||
* @method array zdiff(array $keys, bool $withScores = false)
|
||||
* @method int zdiffstore(string $destination, array $keys)
|
||||
* @method string zincrby(string $key, int $increment, string $member)
|
||||
@@ -294,22 +312,22 @@ use Predis\Response\Status;
|
||||
* @method array zpopmin(string $key, int $count = 1)
|
||||
* @method array zpopmax(string $key, int $count = 1)
|
||||
* @method mixed zrandmember(string $key, int $count = 1, bool $withScores = false)
|
||||
* @method array zrange(string $key, int|string $start, int|string $stop, array $options = null)
|
||||
* @method array zrangebyscore(string $key, int|string $min, int|string $max, array $options = null)
|
||||
* @method array zrange(string $key, int|string $start, int|string $stop, ?array $options = null)
|
||||
* @method array zrangebyscore(string $key, int|string $min, int|string $max, ?array $options = null)
|
||||
* @method int zrangestore(string $destination, string $source, int|string $min, int|string $max, string|bool $by = false, bool $reversed = false, bool $limit = false, int $offset = 0, int $count = 0)
|
||||
* @method int|null zrank(string $key, string $member)
|
||||
* @method int zrem(string $key, string ...$member)
|
||||
* @method int zremrangebyrank(string $key, int|string $start, int|string $stop)
|
||||
* @method int zremrangebyscore(string $key, int|string $min, int|string $max)
|
||||
* @method array zrevrange(string $key, int|string $start, int|string $stop, array $options = null)
|
||||
* @method array zrevrangebyscore(string $key, int|string $max, int|string $min, array $options = null)
|
||||
* @method array zrevrange(string $key, int|string $start, int|string $stop, ?array $options = null)
|
||||
* @method array zrevrangebyscore(string $key, int|string $max, int|string $min, ?array $options = null)
|
||||
* @method int|null zrevrank(string $key, string $member)
|
||||
* @method array zunion(array $keys, int[] $weights = [], string $aggregate = 'sum', bool $withScores = false)
|
||||
* @method int zunionstore(string $destination, array $keys, int[] $weights = [], string $aggregate = 'sum')
|
||||
* @method string|null zscore(string $key, string $member)
|
||||
* @method array zscan(string $key, int $cursor, array $options = null)
|
||||
* @method array zrangebylex(string $key, string $start, string $stop, array $options = null)
|
||||
* @method array zrevrangebylex(string $key, string $start, string $stop, array $options = null)
|
||||
* @method array zscan(string $key, int $cursor, ?array $options = null)
|
||||
* @method array zrangebylex(string $key, string $start, string $stop, ?array $options = null)
|
||||
* @method array zrevrangebylex(string $key, string $start, string $stop, ?array $options = null)
|
||||
* @method int zremrangebylex(string $key, string $min, string $max)
|
||||
* @method int zlexcount(string $key, string $min, string $max)
|
||||
* @method int pexpiretime(string $key)
|
||||
@@ -323,16 +341,16 @@ use Predis\Response\Status;
|
||||
* @method mixed multi()
|
||||
* @method mixed unwatch()
|
||||
* @method array waitaof(int $numLocal, int $numReplicas, int $timeout)
|
||||
* @method mixed watch(string $key)
|
||||
* @method mixed watch(string[]|string $keyOrKeys)
|
||||
* @method mixed eval(string $script, int $numkeys, string ...$keyOrArg = null)
|
||||
* @method mixed eval_ro(string $script, array $keys, ...$argument)
|
||||
* @method mixed evalsha(string $script, int $numkeys, string ...$keyOrArg = null)
|
||||
* @method mixed evalsha_ro(string $sha1, array $keys, ...$argument)
|
||||
* @method mixed script($subcommand, $argument = null)
|
||||
* @method Status shutdown(bool $noSave = null, bool $now = false, bool $force = false, bool $abort = false)
|
||||
* @method Status shutdown(?bool $noSave = null, bool $now = false, bool $force = false, bool $abort = false)
|
||||
* @method mixed auth(string $password)
|
||||
* @method string echo(string $message)
|
||||
* @method mixed ping(string $message = null)
|
||||
* @method mixed ping(?string $message = null)
|
||||
* @method mixed select(int $database)
|
||||
* @method mixed bgrewriteaof()
|
||||
* @method mixed bgsave()
|
||||
@@ -352,17 +370,20 @@ use Predis\Response\Status;
|
||||
* @method array geohash(string $key, array $members)
|
||||
* @method array geopos(string $key, array $members)
|
||||
* @method string|null geodist(string $key, $member1, $member2, $unit = null)
|
||||
* @method array georadius(string $key, $longitude, $latitude, $radius, $unit, array $options = null)
|
||||
* @method array georadiusbymember(string $key, $member, $radius, $unit, array $options = null)
|
||||
* @method array georadius(string $key, $longitude, $latitude, $radius, $unit, ?array $options = null)
|
||||
* @method array georadiusbymember(string $key, $member, $radius, $unit, ?array $options = null)
|
||||
* @method array geosearch(string $key, FromInterface $from, ByInterface $by, ?string $sorting = null, int $count = -1, bool $any = false, bool $withCoord = false, bool $withDist = false, bool $withHash = false)
|
||||
* @method int geosearchstore(string $destination, string $source, FromInterface $from, ByInterface $by, ?string $sorting = null, int $count = -1, bool $any = false, bool $storeDist = false)
|
||||
*
|
||||
* Container commands
|
||||
* @property CLUSTER $cluster
|
||||
* @property FunctionContainer $function
|
||||
* @property FTCONFIG $ftconfig
|
||||
* @property FTCURSOR $ftcursor
|
||||
* @property JSONDEBUG $jsondebug
|
||||
* @property ACL $acl
|
||||
*
|
||||
* @no-named-arguments
|
||||
*/
|
||||
interface ClientInterface
|
||||
{
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -163,6 +163,8 @@ abstract class ClusterStrategy implements StrategyInterface
|
||||
/* scripting */
|
||||
'EVAL' => [$this, 'getKeyFromScriptingCommands'],
|
||||
'EVALSHA' => [$this, 'getKeyFromScriptingCommands'],
|
||||
'EVAL_RO' => [$this, 'getKeyFromScriptingCommands'],
|
||||
'EVALSHA_RO' => [$this, 'getKeyFromScriptingCommands'],
|
||||
|
||||
/* server */
|
||||
'INFO' => [$this, 'getFakeKey'],
|
||||
@@ -174,6 +176,9 @@ abstract class ClusterStrategy implements StrategyInterface
|
||||
'GEODIST' => $getKeyFromFirstArgument,
|
||||
'GEORADIUS' => [$this, 'getKeyFromGeoradiusCommands'],
|
||||
'GEORADIUSBYMEMBER' => [$this, 'getKeyFromGeoradiusCommands'],
|
||||
|
||||
/* cluster */
|
||||
'CLUSTER' => [$this, 'getFakeKey'],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Cluster;
|
||||
|
||||
/**
|
||||
* Represents the gap between slot ranges.
|
||||
*/
|
||||
class NullSlotRange extends SlotRange
|
||||
{
|
||||
public function __construct(int $start, int $end)
|
||||
{
|
||||
parent::__construct($start, $end, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -23,9 +23,9 @@ class PredisStrategy extends ClusterStrategy
|
||||
protected $distributor;
|
||||
|
||||
/**
|
||||
* @param DistributorInterface $distributor Optional distributor instance.
|
||||
* @param DistributorInterface|null $distributor Optional distributor instance.
|
||||
*/
|
||||
public function __construct(DistributorInterface $distributor = null)
|
||||
public function __construct(?DistributorInterface $distributor = null)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -25,9 +25,9 @@ class RedisStrategy extends ClusterStrategy
|
||||
protected $hashGenerator;
|
||||
|
||||
/**
|
||||
* @param HashGeneratorInterface $hashGenerator Hash generator instance.
|
||||
* @param HashGeneratorInterface|null $hashGenerator Hash generator instance.
|
||||
*/
|
||||
public function __construct(HashGeneratorInterface $hashGenerator = null)
|
||||
public function __construct(?HashGeneratorInterface $hashGenerator = null)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Cluster;
|
||||
|
||||
use ArrayAccess;
|
||||
use ArrayIterator;
|
||||
use Countable;
|
||||
use IteratorAggregate;
|
||||
use OutOfBoundsException;
|
||||
use Predis\Connection\NodeConnectionInterface;
|
||||
use ReturnTypeWillChange;
|
||||
use Traversable;
|
||||
|
||||
/**
|
||||
* Slot map for redis-cluster.
|
||||
*/
|
||||
class SimpleSlotMap implements ArrayAccess, IteratorAggregate, Countable
|
||||
{
|
||||
private $slots = [];
|
||||
|
||||
/**
|
||||
* Checks if the given slot is valid.
|
||||
*
|
||||
* @param int $slot Slot index.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValid($slot)
|
||||
{
|
||||
return $slot >= 0x0000 && $slot <= 0x3FFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given slot range is valid.
|
||||
*
|
||||
* @param int $first Initial slot of the range.
|
||||
* @param int $last Last slot of the range.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValidRange($first, $last)
|
||||
{
|
||||
return $first >= 0x0000 && $first <= 0x3FFF && $last >= 0x0000 && $last <= 0x3FFF && $first <= $last;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the slot map.
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$this->slots = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the slot map is empty.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmpty()
|
||||
{
|
||||
return empty($this->slots);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current slot map as a dictionary of $slot => $node.
|
||||
*
|
||||
* The order of the slots in the dictionary is not guaranteed.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return $this->slots;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of unique nodes in the slot map.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getNodes()
|
||||
{
|
||||
return array_keys(array_flip($this->slots));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns the specified slot range to a node.
|
||||
*
|
||||
* @param int $first Initial slot of the range.
|
||||
* @param int $last Last slot of the range.
|
||||
* @param NodeConnectionInterface|string $connection ID or connection instance.
|
||||
*
|
||||
* @throws OutOfBoundsException
|
||||
*/
|
||||
public function setSlots($first, $last, $connection)
|
||||
{
|
||||
if (!static::isValidRange($first, $last)) {
|
||||
throw new OutOfBoundsException("Invalid slot range $first-$last for `$connection`");
|
||||
}
|
||||
|
||||
$this->slots += array_fill($first, $last - $first + 1, (string) $connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the specified slot range.
|
||||
*
|
||||
* @param int $first Initial slot of the range.
|
||||
* @param int $last Last slot of the range.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSlots($first, $last)
|
||||
{
|
||||
if (!static::isValidRange($first, $last)) {
|
||||
throw new OutOfBoundsException("Invalid slot range $first-$last");
|
||||
}
|
||||
|
||||
return array_intersect_key($this->slots, array_fill($first, $last - $first + 1, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified slot is assigned.
|
||||
*
|
||||
* @param int $slot Slot index.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetExists($slot)
|
||||
{
|
||||
return isset($this->slots[$slot]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the node assigned to the specified slot.
|
||||
*
|
||||
* @param int $slot Slot index.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetGet($slot)
|
||||
{
|
||||
return $this->slots[$slot] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns the specified slot to a node.
|
||||
*
|
||||
* @param int $slot Slot index.
|
||||
* @param NodeConnectionInterface|string $connection ID or connection instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetSet($slot, $connection)
|
||||
{
|
||||
if (!static::isValid($slot)) {
|
||||
throw new OutOfBoundsException("Invalid slot $slot for `$connection`");
|
||||
}
|
||||
|
||||
$this->slots[(int) $slot] = (string) $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the node assigned to the specified slot.
|
||||
*
|
||||
* @param int $slot Slot index.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetUnset($slot)
|
||||
{
|
||||
unset($this->slots[$slot]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current number of assigned slots.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function count()
|
||||
{
|
||||
return count($this->slots);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over the slot map.
|
||||
*
|
||||
* @return Traversable<int, string>
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
return new ArrayIterator($this->slots);
|
||||
}
|
||||
}
|
||||
+226
-18
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -22,11 +22,16 @@ use ReturnTypeWillChange;
|
||||
use Traversable;
|
||||
|
||||
/**
|
||||
* Slot map for redis-cluster.
|
||||
* Compact slot map for redis-cluster.
|
||||
*/
|
||||
class SlotMap implements ArrayAccess, IteratorAggregate, Countable
|
||||
{
|
||||
private $slots = [];
|
||||
/**
|
||||
* Slot ranges list.
|
||||
*
|
||||
* @var SlotRange[]
|
||||
*/
|
||||
private $slotRanges = [];
|
||||
|
||||
/**
|
||||
* Checks if the given slot is valid.
|
||||
@@ -37,7 +42,7 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
|
||||
*/
|
||||
public static function isValid($slot)
|
||||
{
|
||||
return $slot >= 0x0000 && $slot <= 0x3FFF;
|
||||
return $slot >= 0 && $slot <= SlotRange::MAX_SLOTS;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,7 +55,7 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
|
||||
*/
|
||||
public static function isValidRange($first, $last)
|
||||
{
|
||||
return $first >= 0x0000 && $first <= 0x3FFF && $last >= 0x0000 && $last <= 0x3FFF && $first <= $last;
|
||||
return SlotRange::isValidRange($first, $last);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,7 +63,7 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$this->slots = [];
|
||||
$this->slotRanges = [];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,7 +73,7 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
|
||||
*/
|
||||
public function isEmpty()
|
||||
{
|
||||
return empty($this->slots);
|
||||
return empty($this->slotRanges);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,7 +85,13 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return $this->slots;
|
||||
return array_reduce(
|
||||
$this->slotRanges,
|
||||
function ($carry, $slotRange) {
|
||||
return $carry + $slotRange->toArray();
|
||||
},
|
||||
[]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,7 +101,22 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
|
||||
*/
|
||||
public function getNodes()
|
||||
{
|
||||
return array_keys(array_flip($this->slots));
|
||||
return array_unique(array_map(
|
||||
function ($slotRange) {
|
||||
return $slotRange->getConnection();
|
||||
},
|
||||
$this->slotRanges
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of slot ranges.
|
||||
*
|
||||
* @return SlotRange[]
|
||||
*/
|
||||
public function getSlotRanges()
|
||||
{
|
||||
return $this->slotRanges;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,7 +134,31 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
|
||||
throw new OutOfBoundsException("Invalid slot range $first-$last for `$connection`");
|
||||
}
|
||||
|
||||
$this->slots += array_fill($first, $last - $first + 1, (string) $connection);
|
||||
$targetSlotRange = new SlotRange($first, $last, (string) $connection);
|
||||
|
||||
// Get gaps of slot ranges list.
|
||||
$gaps = $this->getGaps($this->slotRanges);
|
||||
|
||||
$results = $this->slotRanges;
|
||||
|
||||
foreach ($gaps as $gap) {
|
||||
if (!$gap->hasIntersectionWith($targetSlotRange)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get intersection of the gap and target slot range.
|
||||
$results[] = new SlotRange(
|
||||
max($gap->getStart(), $targetSlotRange->getStart()),
|
||||
min($gap->getEnd(), $targetSlotRange->getEnd()),
|
||||
$targetSlotRange->getConnection()
|
||||
);
|
||||
}
|
||||
|
||||
$this->sortSlotRanges($results);
|
||||
|
||||
$results = $this->compactSlotRanges($results);
|
||||
|
||||
$this->slotRanges = $results;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,7 +167,7 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
|
||||
* @param int $first Initial slot of the range.
|
||||
* @param int $last Last slot of the range.
|
||||
*
|
||||
* @return array
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public function getSlots($first, $last)
|
||||
{
|
||||
@@ -125,7 +175,28 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
|
||||
throw new OutOfBoundsException("Invalid slot range $first-$last");
|
||||
}
|
||||
|
||||
return array_intersect_key($this->slots, array_fill($first, $last - $first + 1, null));
|
||||
$placeHolder = new NullSlotRange($first, $last);
|
||||
|
||||
$intersections = [];
|
||||
foreach ($this->slotRanges as $slotRange) {
|
||||
if (!$placeHolder->hasIntersectionWith($slotRange)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$intersections[] = new SlotRange(
|
||||
max($placeHolder->getStart(), $slotRange->getStart()),
|
||||
min($placeHolder->getEnd(), $slotRange->getEnd()),
|
||||
$slotRange->getConnection()
|
||||
);
|
||||
}
|
||||
|
||||
return array_reduce(
|
||||
$intersections,
|
||||
function ($carry, $slotRange) {
|
||||
return $carry + $slotRange->toArray();
|
||||
},
|
||||
[]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -138,7 +209,7 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetExists($slot)
|
||||
{
|
||||
return isset($this->slots[$slot]);
|
||||
return $this->findRangeBySlot($slot) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,7 +222,9 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetGet($slot)
|
||||
{
|
||||
return $this->slots[$slot] ?? null;
|
||||
$found = $this->findRangeBySlot($slot);
|
||||
|
||||
return $found ? $found->getConnection() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -169,7 +242,8 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
|
||||
throw new OutOfBoundsException("Invalid slot $slot for `$connection`");
|
||||
}
|
||||
|
||||
$this->slots[(int) $slot] = (string) $connection;
|
||||
$this->offsetUnset($slot);
|
||||
$this->setSlots($slot, $slot, $connection);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -182,7 +256,26 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetUnset($slot)
|
||||
{
|
||||
unset($this->slots[$slot]);
|
||||
if (!static::isValid($slot)) {
|
||||
throw new OutOfBoundsException("Invalid slot $slot");
|
||||
}
|
||||
|
||||
$results = [];
|
||||
foreach ($this->slotRanges as $slotRange) {
|
||||
if (!$slotRange->hasSlot($slot)) {
|
||||
$results[] = $slotRange;
|
||||
}
|
||||
|
||||
if (static::isValidRange($slotRange->getStart(), $slot - 1)) {
|
||||
$results[] = new SlotRange($slotRange->getStart(), $slot - 1, $slotRange->getConnection());
|
||||
}
|
||||
|
||||
if (static::isValidRange($slot + 1, $slotRange->getEnd())) {
|
||||
$results[] = new SlotRange($slot + 1, $slotRange->getEnd(), $slotRange->getConnection());
|
||||
}
|
||||
}
|
||||
|
||||
$this->slotRanges = $results;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,7 +286,12 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
|
||||
#[ReturnTypeWillChange]
|
||||
public function count()
|
||||
{
|
||||
return count($this->slots);
|
||||
return array_sum(array_map(
|
||||
function ($slotRange) {
|
||||
return $slotRange->count();
|
||||
},
|
||||
$this->slotRanges
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -204,6 +302,116 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
|
||||
#[ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
return new ArrayIterator($this->slots);
|
||||
return new ArrayIterator($this->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the slot range which contains the specific slot index.
|
||||
*
|
||||
* @param int $slot Slot index.
|
||||
*
|
||||
* @return SlotRange|false The slot range object or false if not found.
|
||||
*/
|
||||
protected function findRangeBySlot(int $slot)
|
||||
{
|
||||
foreach ($this->slotRanges as $slotRange) {
|
||||
if ($slotRange->hasSlot($slot)) {
|
||||
return $slotRange;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get gaps between sorted slot ranges with NullSlotRange object.
|
||||
*
|
||||
* @param SlotRange[] $slotRanges
|
||||
*
|
||||
* @return SlotRange[]
|
||||
*/
|
||||
protected function getGaps(array $slotRanges)
|
||||
{
|
||||
if (empty($slotRanges)) {
|
||||
return [
|
||||
new NullSlotRange(0, SlotRange::MAX_SLOTS),
|
||||
];
|
||||
}
|
||||
$gaps = [];
|
||||
$count = count($slotRanges);
|
||||
$i = 0;
|
||||
foreach ($slotRanges as $key => $slotRange) {
|
||||
$start = $slotRange->getStart();
|
||||
$end = $slotRange->getEnd();
|
||||
if (static::isValidRange($i, $start - 1)) {
|
||||
$gaps[] = new NullSlotRange($i, $start - 1);
|
||||
}
|
||||
|
||||
$i = $end + 1;
|
||||
|
||||
if ($key === $count - 1) {
|
||||
if (static::isValidRange($i, SlotRange::MAX_SLOTS)) {
|
||||
$gaps[] = new NullSlotRange($i, SlotRange::MAX_SLOTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $gaps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort slot ranges by start index.
|
||||
*
|
||||
* @param SlotRange[] $slotRanges
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function sortSlotRanges(array &$slotRanges)
|
||||
{
|
||||
usort(
|
||||
$slotRanges,
|
||||
function (SlotRange $a, SlotRange $b) {
|
||||
if ($a->getStart() == $b->getStart()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $a->getStart() < $b->getStart() ? -1 : 1;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compact adjacent slot ranges with the same connection.
|
||||
*
|
||||
* @param SlotRange[] $slotRanges
|
||||
*
|
||||
* @return SlotRange[]
|
||||
*/
|
||||
protected function compactSlotRanges(array $slotRanges)
|
||||
{
|
||||
if (empty($slotRanges)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$compacted = [];
|
||||
$count = count($slotRanges);
|
||||
$i = 0;
|
||||
$carry = $slotRanges[0];
|
||||
while ($i < $count) {
|
||||
$next = $slotRanges[$i + 1] ?? null;
|
||||
if (
|
||||
!is_null($next)
|
||||
&& ($carry->getEnd() + 1) === $next->getStart()
|
||||
&& $carry->getConnection() === $next->getConnection()
|
||||
) {
|
||||
$carry = new SlotRange($carry->getStart(), $next->getEnd(), $carry->getConnection());
|
||||
} else {
|
||||
$compacted[] = $carry;
|
||||
$carry = $next;
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
|
||||
return array_values($compacted);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Predis\Cluster;
|
||||
|
||||
use Countable;
|
||||
use OutOfBoundsException;
|
||||
|
||||
/**
|
||||
* Represents a range of slots in a Redis cluster.
|
||||
*/
|
||||
class SlotRange implements Countable
|
||||
{
|
||||
/**
|
||||
* Maximum number of slots in a Redis cluster is 16384.
|
||||
*/
|
||||
public const MAX_SLOTS = 0x3FFF;
|
||||
|
||||
/**
|
||||
* Starting slot of the range.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $start;
|
||||
|
||||
/**
|
||||
* Ending slot of the range.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $end;
|
||||
|
||||
/**
|
||||
* Connection to the server hosting this slot range.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
public function __construct(int $start, int $end, string $connection)
|
||||
{
|
||||
if (!static::isValidRange($start, $end)) {
|
||||
throw new OutOfBoundsException("Invalid slot range $start-$end for `$connection`");
|
||||
}
|
||||
$this->start = $start;
|
||||
$this->end = $end;
|
||||
$this->connection = $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a slot range is valid.
|
||||
*
|
||||
* @param int $first
|
||||
* @param int $last
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValidRange($first, $last)
|
||||
{
|
||||
return $first >= 0 && $first <= self::MAX_SLOTS && $last >= 0x0000 && $last <= self::MAX_SLOTS && $first <= $last;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the start slot index of this range.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getStart()
|
||||
{
|
||||
return $this->start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the end slot index of this range.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getEnd()
|
||||
{
|
||||
return $this->end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the connection to the server hosting this slot range.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getConnection()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specific slot is contained in this range.
|
||||
*
|
||||
* @param int $slot
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasSlot(int $slot)
|
||||
{
|
||||
return $this->start <= $slot && $this->end >= $slot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of connection strings for each slot in this range.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return array_fill($this->start, $this->end - $this->start + 1, $this->connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of slots in this range.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
return $this->end - $this->start + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this range has an intersection with the given slot range.
|
||||
*
|
||||
* @param SlotRange $slotRange
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasIntersectionWith(SlotRange $slotRange): bool
|
||||
{
|
||||
return $this->start <= $slotRange->getEnd() && $this->end >= $slotRange->getStart();
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -176,13 +176,13 @@ abstract class CursorBasedIterator implements Iterator
|
||||
$this->fetch();
|
||||
}
|
||||
|
||||
if ($this->elements) {
|
||||
$this->extractNext();
|
||||
} elseif ($this->cursor) {
|
||||
goto tryFetch;
|
||||
} else {
|
||||
$this->valid = false;
|
||||
}
|
||||
if ($this->elements) {
|
||||
$this->extractNext();
|
||||
} elseif ($this->cursor) {
|
||||
goto tryFetch;
|
||||
} else {
|
||||
$this->valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file is part of the Predis package.
|
||||
*
|
||||
* (c) 2009-2020 Daniele Alessandri
|
||||
* (c) 2021-2023 Till Krüss
|
||||
* (c) 2021-2025 Till Krüss
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user