Compare commits

..

82 Commits

Author SHA1 Message Date
vladvildanov ebdd22ff61 Added this PR to changelog 2025-03-20 15:01:28 +02:00
vladvildanov 25b33f50ae Merge branch 'vv-added-missing-types' of github.com:predis/predis into vv-added-missing-types 2025-03-20 15:00:36 +02:00
vladvildanov 3864a7b125 Updated CHANGELOG.md 2025-03-20 15:00:21 +02:00
Vladyslav Vildanov 6f4ac2a012 Merge branch 'v2.x' into vv-added-missing-types 2025-03-20 14:45:42 +02:00
vladvildanov 72f6baef26 Added missing types for commands API 2025-03-20 14:44:36 +02:00
messikiller 7bf1f6eb29 optimize redis cluster slotmap with compact slot range object (#1493)
Co-authored-by: heqiming <heqiming@kingsoft.com>
Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
Co-authored-by: Vladyslav Vildanov <117659936+vladvildanov@users.noreply.github.com>
2025-03-19 09:24:53 -07:00
Vladyslav Vildanov 067b051900 Added missing FT._LIST and BITFIELD_RO commands (#1521)
* Added missing FT._LIST and BITFIELD_RO commands

* Codestyle fixes
2025-03-19 09:57:52 +02:00
Till Krüss df4a318b80 remove performance rambling from FAQ 2025-03-18 12:50:00 -07:00
Vladyslav Vildanov a904a3a273 Backport #1517 (#1518)
* Backport #1517

* Added versions restrictions

* Removed Relay for cluster with coverage

* Added phpcov package
2025-03-05 19:29:38 +02:00
Vladyslav Vildanov 8b240d15a5 Backport #1512 (#1515)
* Backport #1512
* Removed outdated test
2025-02-25 09:12:10 -08:00
Vladyslav Vildanov 02e2a7e1cc Added test coverage for compatibility with Redis 8.0 (#1513)
* Added testing with 8.0

* Removed old service

* Moved checkout stage above image

* Changed service name

* Override config options for Redis < 7

* Exported to github env

* Print major version output

* Added double quotes

* Test fixes

* Merge cluster and standalone infrastructure

* Removed separate cluster job and merge together with standalone

* Merge stack tests into main test job

* Fixed annotation condition

* tweaks

* Moved docker-compose.yml to root folder

* Added compose file to expected

* fixed in v0.10.1

* move docker file

* Added -all profile in docker-compose

* Removed redis official image, reduce test matrix, moved docker-compose.yml

* Revert docker-compose moving

* Added test coverage to verify compatibility with 8.0

* Mark tests as relay-incompatible

* Codestyle fix

* Marked as relay-incompatible

---------

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2025-02-24 09:22:45 -08:00
Vladyslav Vildanov 9a22450a65 Added testing with 8.0 (#1510)
* Added testing with 8.0

* Removed old service

* Moved checkout stage above image

* Changed service name

* Override config options for Redis < 7

* Exported to github env

* Print major version output

* Added double quotes

* Test fixes

* Merge cluster and standalone infrastructure

* Removed separate cluster job and merge together with standalone

* Merge stack tests into main test job

* Fixed annotation condition

* tweaks

* Moved docker-compose.yml to root folder

* Added compose file to expected

* fixed in v0.10.1

* move docker file

* Added -all profile in docker-compose

* Removed redis official image, reduce test matrix, moved docker-compose.yml

* Revert docker-compose moving

* test php 8.0 and redis 4.0

* Revert changes related to official image

---------

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2025-02-20 17:47:05 +02:00
zxin ac933cc548 Fix eval_ro cluster support (#1449) 2025-02-13 09:40:23 -08:00
Stephan 355faa099f ClientInterface: update watch command accepting string and string[] (#1476) 2025-02-13 09:39:51 -08:00
Radu Neacsu 549889b198 Mark GEOSEARCH as read-only to ensure execution on replica instead of… (#1481) 2025-02-13 09:39:19 -08:00
Denny Septian Panggabean d1c657aac5 refactor: use parallel on PHP-CS-Fixer (#1489) 2025-02-13 09:06:51 -08:00
Jan Nedbal b196809d3a Prevent named arguments runtime failure (#1509) 2025-02-12 09:13:01 -08:00
Till Krüss 52489ea703 Update CHANGELOG.md 2025-01-22 09:26:10 -08:00
Till Krüss ba66e22c92 bump year to 2025 2025-01-22 09:24:26 -08:00
Nicolas Chapleau 37aa6fb515 PHP 8.4.0 compatibility with call to stream_context_set_option (#1503)
Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2025-01-22 09:08:12 -08:00
Till Krüss deed24c418 update year 2025-01-20 09:52:18 -08:00
Till Krüss 93895d02b6 Update composer.json 2025-01-16 08:48:12 -08:00
asafpamzn 275606843e Update composer.json 2025-01-16 08:48:12 -08:00
asafpamzn 976c9daa4f Update composer.json 2025-01-16 08:48:12 -08:00
Till Krüss 205ae75bd8 Update README.md 2025-01-16 08:48:12 -08:00
asafpamzn a5f46d0913 Update README.md to include that the client is compatible with Valkey
Added documentation clarifying that predis is compatible with Valkey. This information could be really helpful for developers using Valkey in their projects, saving them time and ensuring they are confident in their choice of predis.
2025-01-16 08:48:12 -08:00
Till Krüss b36c2f928f Update .editorconfig (#1494) 2024-11-25 09:58:29 -08:00
Vladyslav Vildanov bf6e97e7fb Fixed broken search test (#1492) 2024-11-22 07:54:01 -08:00
Till Krüss da40e1253c bump dev version [skip ci] 2024-11-21 12:14:32 -08:00
Till Krüss bac46bfdb7 Prepare v2.3.0 (#1491)
* mark as redis 7.4 compatible
* run more tests on 8.4
* add 2.3.0 changelog
* don't skip errors
2024-11-21 12:00:02 -08:00
Till Krüss 7631d317fd update year 2024-11-21 11:37:10 -08:00
Vladyslav Vildanov aaec13d074 Added support for INDEXMISSING and INDEXEMPTY arguments (#1464)
* Added support for INDEXMISSING and INDEXEMPTY arguments

* Added version restriction for test

* Codestyle fixes

* Updated test case to remove DIALECT 5

* Updated another test case

* Added correct versions restriction

---------

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2024-11-21 10:19:51 -08:00
Vladyslav Vildanov 52bdcf0c1f Added test case for enhanced exact matching (#1466)
* Added test case for enhanced exact matching

* Added version restriction for test

* Updated test case to use Tag Field instead

* Codestyle fix

* Added edge to stack matrix

* Updated test case to switch DIALECT

* Updated version restriction
2024-11-21 10:00:34 -08:00
Vladyslav Vildanov 1726db0f47 Codestyle updates (#1485) 2024-10-22 09:16:07 -07:00
Vladyslav Vildanov 8fbd34c6b3 Added support for hash field expiration commands (#1456)
* Added support for hash field expiration commands

* Added support for HSETF, HGETF commands

* Removed non-printable ASCII chars from docs

* Removed more non-printable ASCII

* Fixed code style issues

* Extended codespell ignore words list

* Added FIELDS argument, fixes related to comments

* Codestyle fixes

* Fixed typo

* Removed HSETF, HGETF commands

* Added 7.4-rc1 to test matrix

* Fixed test with new response types

* Updated tests against 7.4-rc2 image
2024-10-15 10:01:39 -07:00
Christian Flothmann 0a92618fa1 keep key and value when filtering SET arguments (#1471) 2024-07-11 09:46:52 +03:00
Vladyslav Vildanov d8bb9ac46e Added support for new IGNORE filter (#1458)
* Added support for new IGNORE filter

* Fixed arguments to be mandatory

* Added more test cases

* Codestyle fixes

* Added missing test case

* Updated test cases

* Added additional timeout after index creation

* Fixed broken test and removed non-related functionality

* Fixed tests version requirements

* Updated error message
2024-07-11 09:35:52 +03:00
Vladyslav Vildanov 274e0c17cd Fixed bug with null arguments in SET command (#1470) 2024-07-09 14:10:58 +03:00
Vladyslav Vildanov c27dafa40d [2.x] Added Redis 7.4 commands interface changes (#1459)
* [2.x] Added Redis 7.4 commands interface changes

* Removed RESP3 test case

* Added 7.4-rc1 to test matrix

* Added 7.4.0-rc1 to stack matrix

* Added version restriction for test

* Updated stack image to edge
2024-07-05 16:36:58 +03:00
Vladyslav Vildanov 8c2aac4f66 Added GEOSHAPE field and test polygon search (#1467)
* Added GEOSHAPE field and test polygon search

* Added version restriction for test

* Added edge to stack amtrix

* Added same values assertion

* Codestyle changes
2024-07-05 16:16:16 +03:00
Alexander Mohorev 5d22ed775a Fix prefix for SMISMEMBER (#1468) 2024-07-02 12:41:07 -07:00
Vladyslav Vildanov c5fdfc81ef Added tests case with FLOAT16 and BFLOAT16 vectors (#1465)
* Added tests case with FLOAT16 and BFLOAT16 vectors

* Added version restriction for test

* Updated version restrictions
2024-06-28 11:18:07 -07:00
Markus Reinhold cbef71090b Fix prefixes for LMOVE and BLMOVE (#1455)
Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2024-05-02 08:55:20 -07:00
mahshidhp 4dc72458e8 Fix prefix for GEOSEARCH (#1453) 2024-04-30 12:29:30 -07:00
Christian Flothmann e83b393e09 explicitly mark nullable parameters as nullable (#1448)
* explicitly mark nullable parameters as nullable
* add job to run tests with PHP 8.4
2024-04-30 12:14:13 -07:00
Till Krüss ed90750c1f fix prefixes for ZPOPMIN, ZPOPMAX and ZMSCORE (#1451) 2024-04-10 18:07:03 -07:00
René Højbjerg Larsen 45b18eb2e0 Filter out available slaves based on master-link-status flag (#1440) 2024-03-06 08:19:48 -08:00
Till Krüss d44f07339a Run tests under PHP 8.3 (#1396) 2023-10-25 10:08:55 -07:00
Till Krüss a9d18b182c tweak fixer rules 2023-10-24 09:17:43 -07:00
Tobias Bengtsson 5c8b19ebaa Fix operator precedence (#1405)
&& binds tighter than ?? so a parentheses is needed for desired result
2023-09-26 09:11:00 -07:00
Stephan 577bd39872 ClientInterface: using set with NX flag can return null (#1394)
Calling `$client->set('key', '1', 'EX', 7200, 'NX')` for a key that is already set will return null instead of Status
2023-09-14 09:44:52 -07:00
Jiří Bok 6372661dbf Make Relay work with Redis cluster (#1397) 2023-09-13 09:59:50 -07:00
Till Krüss 4846e2ab94 back to dev version 2023-09-13 09:55:14 -07:00
Sergei Predvoditelev 92b284967e Fix cmsincrby method annotation in ClientInterface (#1333) 2023-09-13 09:50:19 -07:00
Till Krüss 08d5298080 fix typos 2023-09-13 09:49:11 -07:00
Igor Malinovskiy d88153b63e Add 7.2 to supported Redis versions (#1367) 2023-09-13 09:47:35 -07:00
Till Krüss b1d3255ed9 tag v2.2.2 2023-09-13 09:42:03 -07:00
Till Krüss cbf394b882 Disable CLIENT SETINFO calls by default (#1399)
Add `client_info` parameter
2023-09-13 09:35:49 -07:00
Till Krüss c6bf644872 bump dev version 2023-09-13 09:34:52 -07:00
Vladyslav Vildanov 16bdd83d23 Added EXPIRETIME command to KeyPrefixProcessor (#1369)
* Added EXPIRETIME command to KeyPrefixProcessor

* Fixed test responses for Redis 7.2

* Marked test as relay-incompatible
2023-08-25 14:27:24 -07:00
Vladyslav Vildanov 912af82bfd Added support for CLUSTER container command (#1360)
* Added support for CLUSTER container command

* Codestyle fixes
2023-08-17 09:34:01 +03:00
Vladyslav Vildanov 2d74db1bde Changes related to Redis 7.2 image update (#1366)
* Added new assertion, fixed RESP3 JSON responses and versions

* Removed expectations for error messages

* Changed tests group for RESP3 not supported tests

* Removed 3.x test case

* Added missing test decorators

* Fixed typo

* Removed redisgraph module upload, as not a part of a redis-stack anymore
2023-08-16 08:18:45 -07:00
Till Krüss c5ee202179 bump version (#1365)
* bump version

* Update Client.php
2023-08-15 16:06:03 -07:00
Till Krüss 5f2b410a74 Update CHANGELOG.md (#1364)
* Update CHANGELOG.md

* Update CHANGELOG.md

* Update CHANGELOG.md
2023-08-15 16:01:46 -07:00
Vladyslav Vildanov f6cf2afe47 Updated CHANGELOG.md (#1363)
* Updated CHANGELOG.md

* Added quotes to CHANGELOG.md

* Codestyle fix
2023-08-15 08:43:46 -07:00
Vladyslav Vildanov 311cd2b79e Added support for WAITAOF command (#1357)
* Added support for WAITAOF command

* Added call to parent setUp method
2023-08-14 09:18:19 +03:00
Vladyslav Vildanov ffd31cfdef Added missing redis-stack commands to KeyPrefix processor (#1358) 2023-08-10 18:57:16 +03:00
Vladyslav Vildanov 1b2fd527ed Added support for Redis 7.0 arguments (#1359) 2023-08-10 18:57:00 +03:00
Vladyslav Vildanov 4172d2265f Client set name and version on connection (#1347)
* Added client metadata on server connection

* Added try...catch around server exception to supress CLIENT command errors

* Added exclusion for Relay connection
2023-08-03 09:04:04 +03:00
Vladyslav Vildanov a3311d6869 2.2.1 version changes (#1349) 2023-08-03 09:03:21 +03:00
Vladyslav Vildanov df14e11c3a Added support for tests running against redis cluster (#1236)
* Added support for tests running against redis cluster

* Test coverage

* Added comment about master nodes

* Codestyle fix

* Revert changes

* Revert DBNUM

* Added cluster endpoints to relay tests env configuration

* Exclude cluster tests from relay tests environment

* Removed TODO comment

* Changed cluster image version to unstable

* Updated configuration to match unstable cluster

* Fixed path

* Updated cluster CI configuration

* Removed redundant flag

* Removed backslash

* Updated file path

* Updated file path variable

* Added docker cluster initialization as additional step

* Run cluster tests as separate workflow

* Codestyle fixes

* Updated exported files

* Added additional timeout so cluster image could be settled

* Added support for different cluster image, use docker compose for cluster tests CI

* Remove unused flag

* Removed variable from volume path

* Added sleep timeout to allow docker setup after running

* Added timeout before tests run

* Updated linter settings

* Include indent changes for.sh files

* Added missing coverage

* Revert expected files and mark docker folder as exclusion

* Specify folder itself as excluded

* Moved cluster tests as separate job in tests.yml

* Updated name to contain cluster word

---------

Co-authored-by: Chayim <chayim@users.noreply.github.com>
2023-07-24 10:21:43 +03:00
Vladyslav Vildanov 7c2e8e01d8 Added support for FUNCTION KILL, FUNCTION LIST, FUNCTION STATS commands (#1334)
* Added support for FUNCTION KILL, FUNCTION LIST, FUNCTION STATS commands

* Marked tests as relay-incompatible
2023-07-12 09:58:00 +03:00
Vladyslav Vildanov 0b6ab4dea4 Added support for CLIENT NO-EVICT command (#1335) 2023-07-12 09:57:42 +03:00
Vladyslav Vildanov dd64569e06 Added support for FUNCTION DUMP, FUNCTION FLUSH, FUNCTION RESTORE commands (#1332) 2023-07-03 10:41:32 +03:00
Vladyslav Vildanov 90da582efc Fixed bug with incorrect multiple words processing (#1325)
* Fixed bug with incorrect multiple words processing

* Convert subcommand string to lower case

* Update SubcommandStrategyResolver.php

* Added test coverage

* Codestyle fixes

---------

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2023-06-21 12:00:58 +03:00
Till Krüss 732abc88a2 Update CHANGELOG.md 2023-06-14 13:42:52 +03:00
Till Krüss 33b70b971a Update CHANGELOG.md 2023-06-14 13:37:31 +03:00
Vladyslav Vildanov e46d56c45c Fixed subcommand test bug (#1313) 2023-06-08 11:33:25 -04:00
Vladyslav Vildanov c57a6744bb Added support for JSON.MSET command (#1307) 2023-06-08 17:35:04 +03:00
Vladyslav Vildanov df83c94bb3 Added support for JSON.MERGE command (#1304) 2023-06-08 12:16:14 +03:00
Vladyslav Vildanov a711ef96e2 Added GETDEL command to KeyPrefixProcessor (#1306)
* Added GETDEL command to KeyPrefixProcessor

* Added test coverage

* Codestyle fixes

* Added timeout after FT.CREATE call
2023-06-08 11:32:05 +03:00
Vladyslav Vildanov 3c322fc4e3 Codestyle changes related to php-cs-fixer update (#1311)
* Codestyle changes

* Added missing type-hints
2023-06-07 17:05:36 +03:00
1101 changed files with 8483 additions and 1668 deletions
+1 -1
View File
@@ -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
ignore-words-list=master,masters,slave,slaves,whitelist,cas,exat,smove,SUGGET,sugget,ro,DOF,dof
+1
View File
@@ -0,0 +1 @@
coverage_clover: build/logs/clover-*.xml
+4 -1
View File
@@ -14,9 +14,12 @@ block_comment_end = */
[*.php]
max_line_length = 150
[*.{md,yml,yaml,neon}]
[*.{md,yml,yaml,neon,sh}]
indent_size = 2
[VERSION]
insert_final_newline = false
[tests/**.php]
max_line_length = unset
+1
View File
@@ -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
+73
View File
@@ -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
-66
View File
@@ -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
+130 -27
View File
@@ -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-M04-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,21 +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' }}
REDIS_STACK_SERVER_PORT: 6479
- 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: 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: |
wget "https://github.com/php-coveralls/php-coveralls/releases/download/v2.5.3/php-coveralls.phar"
php ./php-coveralls.phar -v
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
View File
@@ -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;
+72 -4
View File
@@ -1,6 +1,70 @@
## Changelog
## v2.2.0-RC1 (2023-05-09)
## Unreleased
### Fixed
- 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)
- Fix eval_ro cluster support (#1449)
### Changed
- Use parallel on PHP-CS-Fixer (#1489)
- Update watch command accepting string and string[] (#1476)
- Optimize redis cluster slotmap with compact slot range object (#1493)
### Added
- Added testing with 8.0 (#1510)
- Added test coverage for compatibility with Redis 8.0 (#1513)
- Added missing FT._LIST and BITFIELD_RO commands (#1521)
- Added missing types for commands API (#1522)
## 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
- Added support for `WAITAOF` command (#1357)
- Added support for `SHUTDOWN` command (#1359)
- Added support for `FUNCTION` command (#1332)
- Added support for new optional `PEXPIRE`, `PEXPIREAT` and `COMMAND`
- Added missing Redis Stack commands to `KeyPrefixProcessor` (#1358)
### Changed
- Set client name and version when establishing a connection (#1347)
## v2.2.0 (2023-06-14)
Predis v2.2.0 introduces official support for [Redis Stack](https://redis.io/docs/stack/) as well as a [Relay](https://github.com/cachewerk/relay) integration for substantially [faster read performance](https://github.com/predis/predis/wiki/Using-Relay).
### Added
- Added support for [Relay](https://github.com/predis/predis/wiki/Using-Relay) (#1263)
@@ -8,11 +72,15 @@
- Added support for Redis `JSON`, `Bloom`, `Search` and `TimeSeries` module (#1253)
- Added support for `ACL SETUSER, GETUSER, DRYRUN` commands (#1193)
### Changed
- Minor code style and type-hint changes (#1311)
### Fixed
- Fixed prefixes for `XTRIM` and `XREVRANGE` commands (#1230)
- Fix `fclose()` being called on invalid stream resource (#1199)
- Fix `BitByte` and `ExpireOptions` traits skip processing on null values (#1169)
- Fix missing `@return` annotations (#1265)
- Fixed `fclose()` being called on invalid stream resource (#1199)
- Fixed `BitByte` and `ExpireOptions` traits skip processing on null values (#1169)
- Fixed missing `@return` annotations (#1265)
- Fixed `GETDEL` prefixing (#1306)
## v2.1.2 (2023-03-02)
+10 -58
View File
@@ -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 -1
View File
@@ -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
+2 -2
View File
@@ -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 __7.4__.
- 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).
+1 -1
View File
@@ -1 +1 @@
2.2.0-RC1
2.3.1-dev
+3 -2
View File
@@ -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 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
+41
View File
@@ -0,0 +1,41 @@
<?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.
*/
use Predis\Client;
require __DIR__ . '/../shared.php';
// Example of WAITAOF command usage:
// 1. Enable appendonly mode if it's not (command works only in appendonly mode)
$client = new Client($single_server);
$info = $client->info();
$enabled = false;
if ($info['Persistence']['aof_enabled'] === '0') {
$client->config('set', 'appendonly', 'yes');
$enabled = true;
}
// 2. Set key value pair
$response = $client->set('foo', 'bar');
echo "Key-value pair set status: {$response}\n";
// 3. Run WAITAOF command to make sure that all previous writes was fsynced
$response = $client->waitaof(1, 0, 0);
echo "Quantity of local instances that was fsynced - {$response[0]}, quantity of replicas - {$response[1]}";
// 4. Disable appendonly mode if it was enabled during script execution
if ($enabled) {
$client->config('set', 'appendonly', 'no');
}
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
+2 -2
View File
@@ -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) {
+7
View File
@@ -20,10 +20,12 @@
<groups>
<exclude>
<group>relay-incompatible</group>
<group>relay-resp3</group>
<group>realm-webdis</group>
<group>realm-stack</group>
<group>ext-curl</group>
<group>ext-phpiredis</group>
<group>cluster</group>
</exclude>
</groups>
@@ -38,5 +40,10 @@
<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 -->
<const name="REDIS_CLUSTER_ENDPOINTS" value="127.0.0.1:6372,127.0.0.1:6373,127.0.0.1:6374" />
</php>
</phpunit>
+6
View File
@@ -33,6 +33,7 @@
<group>ext-relay</group>
<group>ext-curl</group>
<group>ext-phpiredis</group>
<group>cluster</group>
<!-- <group>connected</group> -->
<!-- <group>disconnected</group> -->
<!-- <group>commands</group> -->
@@ -51,5 +52,10 @@
<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 -->
<const name="REDIS_CLUSTER_ENDPOINTS" value="127.0.0.1:6372,127.0.0.1:6373,127.0.0.1:6374" />
</php>
</phpunit>
+1 -1
View File
@@ -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.
+16 -16
View File
@@ -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.0-RC1';
public const VERSION = '2.3.1-dev';
/** @var OptionsInterface */
private $options;
@@ -346,29 +346,29 @@ class Client implements ClientInterface, IteratorAggregate
}
/**
* @param $name
* @param string $name
* @return ContainerInterface
*/
public function __get($name)
public function __get(string $name)
{
return ContainerFactory::create($this, $name);
}
/**
* @param $name
* @param $value
* @param string $name
* @param mixed $value
* @return mixed
*/
public function __set($name, $value)
public function __set(string $name, $value)
{
throw new RuntimeException('Not allowed');
}
/**
* @param $name
* @param string $name
* @return mixed
*/
public function __isset($name)
public function __isset(string $name)
{
throw new RuntimeException('Not allowed');
}
@@ -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);
+1 -1
View File
@@ -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.
+76 -59
View File
@@ -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,6 +39,7 @@ 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;
@@ -56,7 +57,7 @@ use Predis\Command\Redis\Container\Search\FTCURSOR;
* @method $this expiretime(string $key)
* @method $this keys($pattern)
* @method $this move($key, $db)
* @method $this object($subcommand, $key)
* @method $this object(string $subcommand, string $key)
* @method $this persist($key)
* @method $this pexpire($key, $milliseconds)
* @method $this pexpireat($key, $timestamp)
@@ -64,36 +65,37 @@ 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(int|string $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)
* @method $this append($key, $value)
* @method $this bfadd(string $key, $item)
* @method $this bfexists(string $key, $item)
* @method $this bfadd(string $key, string $item)
* @method $this bfexists(string $key, string $item)
* @method $this bfinfo(string $key, string $modifier = '')
* @method $this bfinsert(string $key, int $capacity = -1, float $error = -1, int $expansion = -1, bool $noCreate = false, bool $nonScaling = false, string ...$item)
* @method $this bfloadchunk(string $key, int $iterator, $data)
* @method $this bfmadd(string $key, ...$item)
* @method $this bfmexists(string $key, ...$item)
* @method $this bfmadd(string $key, string ...$item)
* @method $this bfmexists(string $key, string ...$item)
* @method $this bfreserve(string $key, float $errorRate, int $capacity, int $expansion = -1, bool $nonScaling = false)
* @method $this bfscandump(string $key, int $iterator)
* @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 bitpos($key, $bit, $start = null, $end = null, string $index = 'byte')
* @method $this bitop(string $operation, string $destkey, string $key)
* @method $this bitfield($key, string $subcommand, ...$subcommandArg)
* @method $this bitfield_ro(string $key, ?array $encodingOffsetMap = null)
* @method $this bitpos(string $key, int $bit, ?int $start = null, ?int $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)
* @method $this bzpopmin(array $keys, int $timeout)
* @method $this bzmpop(int $timeout, array $keys, string $modifier = 'min', int $count = 1)
* @method $this cfadd(string $key, $item)
* @method $this cfaddnx(string $key, $item)
* @method $this cfcount(string $key, $item)
* @method $this cfdel(string $key, $item)
* @method $this cfexists(string $key, $item)
* @method $this cfadd(string $key, string $item)
* @method $this cfaddnx(string $key, string $item)
* @method $this cfcount(string $key, string $item)
* @method $this cfdel(string $key, string $item)
* @method $this cfexists(string $key, string $item)
* @method $this cfloadchunk(string $key, int $iterator, $data)
* @method $this cfmexists(string $key, ...$item)
* @method $this cfmexists(string $key, string ...$item)
* @method $this cfinfo(string $key)
* @method $this cfinsert(string $key, int $capacity = -1, bool $noCreate = false, string ...$item)
* @method $this cfinsertnx(string $key, int $capacity = -1, bool $noCreate = false, string ...$item)
@@ -110,14 +112,15 @@ 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)
* @method $this ftaliasupdate(string $alias, string $index)
* @method $this ftalter(string $index, FieldInterface[] $schema, ?AlterArguments $arguments = null)
* @method $this ftcreate(string $index, FieldInterface[] $schema, ?CreateArguments $arguments = null)
* @method $this ftdictadd(string $dict, ...$term)
* @method $this ftdictdel(string $dict, ...$term)
* @method $this ftdictadd(string $dict, string ...$term)
* @method $this ftdictdel(string $dict, string ...$term)
* @method $this ftdictdump(string $dict)
* @method $this ftdropindex(string $index, ?DropArguments $arguments = null)
* @method $this ftexplain(string $index, string $query, ?ExplainArguments $arguments = null)
@@ -133,26 +136,33 @@ use Predis\Command\Redis\Container\Search\FTCURSOR;
* @method $this ftsynupdate(string $index, string $synonymGroupId, ?SynUpdateArguments $arguments = null, string ...$terms)
* @method $this fttagvals(string $index, string $fieldName)
* @method $this get($key)
* @method $this getbit($key, $offset)
* @method $this getex(string $key, $modifier = '', $value = false)
* @method $this getrange($key, $start, $end)
* @method $this getbit(string $key, int $offset)
* @method $this getex(string $key, string $modifier = '', string|int $value = false)
* @method $this getrange(string $key, int $start, int $end)
* @method $this getdel(string $key)
* @method $this getset($key, $value)
* @method $this getset(string $key, string|int|float $value)
* @method $this incr($key)
* @method $this incrby($key, $increment)
* @method $this incrbyfloat($key, $increment)
* @method $this mget(array $keys)
* @method $this mset(array $dictionary)
* @method $this msetnx(array $dictionary)
* @method $this psetex($key, $milliseconds, $value)
* @method $this set($key, $value, $expireResolution = null, $expireTTL = null, $flag = null)
* @method $this setbit($key, $offset, $value)
* @method $this setex($key, $seconds, $value)
* @method $this setnx($key, $value)
* @method $this setrange($key, $offset, $value)
* @method $this psetex(string $key, int $milliseconds, string|int|float $value)
* @method $this set(string $key, string|int|float $value, ?string $expireResolution = null, ?int $expireTTL = null, ?string $flag = null)
* @method $this setbit(string $key, int $offset, string|int|float $value)
* @method $this setex(string $key, int $seconds, string|int|float $value)
* @method $this setnx(string $key, string|int|float $value)
* @method $this setrange(string $key, int $offset, string|int|float $value)
* @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 hgetall($key)
* @method $this hincrby($key, $field, $increment)
@@ -162,12 +172,14 @@ 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(string $key, int|string $cursor, ?array $options = null)
* @method $this hset($key, $field, $value)
* @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)
* @method $this jsonarrappend(string $key, string $path = '$', string ...$value)
* @method $this jsonarrindex(string $key, string $path, string $value, int $start = 0, int $stop = 0)
* @method $this jsonarrinsert(string $key, string $path, int $index, string ...$value)
* @method $this jsonarrlen(string $key, string $path = '$')
@@ -178,7 +190,9 @@ use Predis\Command\Redis\Container\Search\FTCURSOR;
* @method $this jsonforget(string $key, string $path = '$')
* @method $this jsonget(string $key, string $indent = '', string $newline = '', string $space = '', string ...$paths)
* @method $this jsonnumincrby(string $key, string $path, int $value)
* @method $this jsonmerge(string $key, string $path, string $value)
* @method $this jsonmget(array $keys, string $path)
* @method $this jsonmset(string ...$keyPathValue)
* @method $this jsonobjkeys(string $key, string $path = '$')
* @method $this jsonobjlen(string $key, string $path = '$')
* @method $this jsonresp(string $key, string $path = '$')
@@ -193,7 +207,7 @@ use Predis\Command\Redis\Container\Search\FTCURSOR;
* @method $this brpoplpush($source, $destination, $timeout)
* @method $this lcs(string $key1, string $key2, bool $len = false, bool $idx = false, int $minMatchLen = 0, bool $withMatchLen = false)
* @method $this lindex($key, $index)
* @method $this linsert($key, $whence, $pivot, $value)
* @method $this linsert(string $key, string $whence, string|int|float $pivot, string|int|float $value)
* @method $this llen($key)
* @method $this lmove(string $source, string $destination, string $where, string $to)
* @method $this lmpop(array $keys, string $modifier = 'left', int $count = 1)
@@ -222,7 +236,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)
@@ -239,11 +253,11 @@ use Predis\Command\Redis\Container\Search\FTCURSOR;
* @method $this tdigestreset(string $key)
* @method $this tdigestrevrank(string $key, float ...$value)
* @method $this tdigesttrimmed_mean(string $key, float $lowCutQuantile, float $highCutQuantile)
* @method $this topkadd(string $key, ...$items)
* @method $this topkincrby(string $key, ...$itemIncrement)
* @method $this topkadd(string $key, string ...$items)
* @method $this topkincrby(string $key, string|int|float ...$itemIncrement)
* @method $this topkinfo(string $key)
* @method $this topklist(string $key, bool $withCount = false)
* @method $this topkquery(string $key, ...$items)
* @method $this topkquery(string $key, string ...$items)
* @method $this topkreserve(string $key, int $topK, int $width = 8, int $depth = 7, float $decay = 0.9)
* @method $this tsadd(string $key, int $timestamp, float $value, ?AddArguments $arguments = null)
* @method $this tsalter(string $key, ?TSAlterArguments $arguments = null)
@@ -252,16 +266,16 @@ 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)
* @method $this tsmget(MGetArguments $arguments, string ...$filterExpression)
* @method $this tsmrange($fromTimestamp, $toTimestamp, MRangeArguments $arguments)
* @method $this tsmrevrange($fromTimestamp, $toTimestamp, MRangeArguments $arguments)
* @method $this tsmrange(string|int|float $fromTimestamp, string|int|float $toTimestamp, MRangeArguments $arguments)
* @method $this tsmrevrange(string|int|float $fromTimestamp, string|int|float $toTimestamp, MRangeArguments $arguments)
* @method $this tsqueryindex(string ...$filterExpression)
* @method $this tsrange(string $key, $fromTimestamp, $toTimestamp, ?RangeArguments $arguments = null)
* @method $this tsrevrange(string $key, $fromTimestamp, $toTimestamp, ?RangeArguments $arguments = null)
* @method $this tsrange(string $key, string|int|float $fromTimestamp, string|int|float $toTimestamp, ?RangeArguments $arguments = null)
* @method $this tsrevrange(string $key, string|int|float $fromTimestamp, string|int|float $toTimestamp, ?RangeArguments $arguments = null)
* @method $this zadd($key, array $membersAndScoresDictionary)
* @method $this zcard($key)
* @method $this zcount($key, $min, $max)
@@ -274,68 +288,71 @@ 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)
* @method $this pfadd($key, array $elements)
* @method $this pfmerge($destinationKey, array|string $sourceKeys)
* @method $this pfcount(array|string $keys)
* @method $this pubsub($subcommand, $argument)
* @method $this publish($channel, $message)
* @method $this pubsub(string $subcommand, string|int|float $argument)
* @method $this publish(string $channel, string|int|float $message)
* @method $this discard()
* @method $this exec()
* @method $this multi()
* @method $this unwatch()
* @method $this waitaof(int $numLocal, int $numReplicas, int $timeout)
* @method $this watch($key)
* @method $this eval($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
* @method $this eval_ro(string $script, array $keys, ...$argument)
* @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 script(string $subcommand, $argument = null)
* @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)
* @method $this select($database)
* @method $this bgrewriteaof()
* @method $this bgsave()
* @method $this client($subcommand, $argument = null)
* @method $this config($subcommand, $argument = null)
* @method $this client(string $subcommand, $argument = null)
* @method $this config(string $subcommand, $argument = null)
* @method $this dbsize()
* @method $this flushall()
* @method $this flushdb()
* @method $this info($section = null)
* @method $this info(?string $section = null)
* @method $this lastsave()
* @method $this save()
* @method $this slaveof($host, $port)
* @method $this slowlog($subcommand, $argument = null)
* @method $this slowlog(string $subcommand, $argument = null)
* @method $this time()
* @method $this command()
* @method $this geoadd($key, $longitude, $latitude, $member)
* @method $this geoadd(string $key, string|float $longitude, string|float $latitude, string $member)
* @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 geodist(string $key, string $member1, string $member2, string $unit = null)
* @method $this georadius(string $key, string|float $longitude, string|float $latitude, int $radius, string $unit, ?array $options = null)
* @method $this georadiusbymember(string $key, string $member, int $radius, string $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
+1 -1
View File
@@ -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.
+86 -66
View File
@@ -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,6 +40,7 @@ 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;
@@ -65,7 +66,7 @@ use Predis\Response\Status;
* @method int expiretime(string $key)
* @method array keys(string $pattern)
* @method int move(string $key, int $db)
* @method mixed object($subcommand, string $key)
* @method mixed object(string $subcommand, string $key)
* @method int persist(string $key)
* @method int pexpire(string $key, int $milliseconds)
* @method int pexpireat(string $key, int $timestamp)
@@ -73,42 +74,43 @@ 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(int|string $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)
* @method int append(string $key, $value)
* @method int bfadd(string $key, $item)
* @method int bfexists(string $key, $item)
* @method int bfadd(string $key, string $item)
* @method int bfexists(string $key, string $item)
* @method array bfinfo(string $key, string $modifier = '')
* @method array bfinsert(string $key, int $capacity = -1, float $error = -1, int $expansion = -1, bool $noCreate = false, bool $nonScaling = false, string ...$item)
* @method Status bfloadchunk(string $key, int $iterator, $data)
* @method array bfmadd(string $key, ...$item)
* @method array bfmexists(string $key, ...$item)
* @method array bfmadd(string $key, string ...$item)
* @method array bfmexists(string $key, string ...$item)
* @method Status bfreserve(string $key, float $errorRate, int $capacity, int $expansion = -1, bool $nonScaling = false)
* @method array bfscandump(string $key, int $iterator)
* @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 int bitpos(string $key, $bit, $start = null, $end = null, string $index = 'byte')
* @method int bitop(string $operation, string $destkey, string $key)
* @method array|null bitfield(string $key, string $subcommand, ...$subcommandArg)
* @method array|null bitfield_ro(string $key, ?array $encodingOffsetMap = null)
* @method int bitpos(string $key, int $bit, ?int $start = null, ?int $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)
* @method array bzpopmin(array $keys, int $timeout)
* @method array bzmpop(int $timeout, array $keys, string $modifier = 'min', int $count = 1)
* @method int cfadd(string $key, $item)
* @method int cfaddnx(string $key, $item)
* @method int cfcount(string $key, $item)
* @method int cfdel(string $key, $item)
* @method int cfexists(string $key, $item)
* @method int cfadd(string $key, string $item)
* @method int cfaddnx(string $key, string $item)
* @method int cfcount(string $key, string $item)
* @method int cfdel(string $key, string $item)
* @method int cfexists(string $key, string $item)
* @method Status cfloadchunk(string $key, int $iterator, $data)
* @method int cfmexists(string $key, ...$item)
* @method int cfmexists(string $key, string ...$item)
* @method array cfinfo(string $key)
* @method array cfinsert(string $key, int $capacity = -1, bool $noCreate = false, string ...$item)
* @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,14 +121,15 @@ 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)
* @method Status ftaliasupdate(string $alias, string $index)
* @method Status ftalter(string $index, FieldInterface[] $schema, ?AlterArguments $arguments = null)
* @method Status ftcreate(string $index, FieldInterface[] $schema, ?CreateArguments $arguments = null)
* @method int ftdictadd(string $dict, ...$term)
* @method int ftdictdel(string $dict, ...$term)
* @method int ftdictadd(string $dict, string ...$term)
* @method int ftdictdel(string $dict, string ...$term)
* @method array ftdictdump(string $dict)
* @method Status ftdropindex(string $index, ?DropArguments $arguments = null)
* @method string ftexplain(string $index, string $query, ?ExplainArguments $arguments = null)
@@ -142,26 +145,33 @@ use Predis\Response\Status;
* @method Status ftsynupdate(string $index, string $synonymGroupId, ?SynUpdateArguments $arguments = null, string ...$terms)
* @method array fttagvals(string $index, string $fieldName)
* @method string|null get(string $key)
* @method int getbit(string $key, $offset)
* @method int|null getex(string $key, $modifier = '', $value = false)
* @method string getrange(string $key, $start, $end)
* @method int getbit(string $key, int $offset)
* @method int|null getex(string $key, string $modifier = '', int|string $value = false)
* @method string getrange(string $key, int $start, int $end)
* @method string getdel(string $key)
* @method string|null getset(string $key, $value)
* @method string|null getset(string $key, string|int|float $value)
* @method int incr(string $key)
* @method int incrby(string $key, int $increment)
* @method string incrbyfloat(string $key, int|float $increment)
* @method array mget(string[]|string $keyOrKeys, string ...$keys = null)
* @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 int setbit(string $key, $offset, $value)
* @method Status setex(string $key, $seconds, $value)
* @method int setnx(string $key, $value)
* @method int setrange(string $key, $offset, $value)
* @method Status psetex(string $key, int $milliseconds, string|int|float $value)
* @method Status|null set(string $key, string|int|float $value, ?string $expireResolution = null, ?int $expireTTL = null, ?string $flag = null)
* @method int setbit(string $key, int $offset, string|int|float $value)
* @method Status setex(string $key, int $seconds, string|int|float $value)
* @method int setnx(string $key, string|int|float $value)
* @method int setrange(string $key, int $offset, string|int|float $value)
* @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 hgetall(string $key)
* @method int hincrby(string $key, string $field, int $increment)
@@ -171,12 +181,14 @@ 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, int|string $cursor, ?array $options = null)
* @method int hset(string $key, string $field, string $value)
* @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)
* @method array jsonarrappend(string $key, string $path = '$', string ...$value)
* @method array jsonarrindex(string $key, string $path, string $value, int $start = 0, int $stop = 0)
* @method array jsonarrinsert(string $key, string $path, int $index, string ...$value)
* @method array jsonarrlen(string $key, string $path = '$')
@@ -187,7 +199,9 @@ use Predis\Response\Status;
* @method int jsonforget(string $key, string $path = '$')
* @method string jsonget(string $key, string $indent = '', string $newline = '', string $space = '', string ...$paths)
* @method string jsonnumincrby(string $key, string $path, int $value)
* @method Status jsonmerge(string $key, string $path, string $value)
* @method array jsonmget(array $keys, string $path)
* @method Status jsonmset(string ...$keyPathValue)
* @method array jsonobjkeys(string $key, string $path = '$')
* @method array jsonobjlen(string $key, string $path = '$')
* @method array jsonresp(string $key, string $path = '$')
@@ -202,7 +216,7 @@ use Predis\Response\Status;
* @method string|null brpoplpush(string $source, string $destination, int|float $timeout)
* @method mixed lcs(string $key1, string $key2, bool $len = false, bool $idx = false, int $minMatchLen = 0, bool $withMatchLen = false)
* @method string|null lindex(string $key, int $index)
* @method int linsert(string $key, $whence, $pivot, $value)
* @method int linsert(string $key, string $whence, string|int|float $pivot, string|int|float $value)
* @method int llen(string $key)
* @method string lmove(string $source, string $destination, string $where, string $to)
* @method array|null lmpop(array $keys, string $modifier = 'left', int $count = 1)
@@ -228,10 +242,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)
@@ -249,11 +263,11 @@ use Predis\Response\Status;
* @method Status tdigestreset(string $key)
* @method array tdigestrevrank(string $key, float ...$value)
* @method string tdigesttrimmed_mean(string $key, float $lowCutQuantile, float $highCutQuantile)
* @method array topkadd(string $key, ...$items)
* @method array topkincrby(string $key, ...$itemIncrement)
* @method array topkadd(string $key, string ...$items)
* @method array topkincrby(string $key, string|int|float ...$itemIncrement)
* @method array topkinfo(string $key)
* @method array topklist(string $key, bool $withCount = false)
* @method array topkquery(string $key, ...$items)
* @method array topkquery(string $key, string|int|float ...$items)
* @method Status topkreserve(string $key, int $topK, int $width = 8, int $depth = 7, float $decay = 0.9)
* @method int tsadd(string $key, int $timestamp, float $value, ?AddArguments $arguments = null)
* @method Status tsalter(string $key, ?TSAlterArguments $arguments = null)
@@ -262,22 +276,23 @@ 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)
* @method array tsmget(MGetArguments $arguments, string ...$filterExpression)
* @method array tsmrange($fromTimestamp, $toTimestamp, MRangeArguments $arguments)
* @method array tsmrevrange($fromTimestamp, $toTimestamp, MRangeArguments $arguments)
* @method array tsmrange(string|int|float $fromTimestamp, string|int|float $toTimestamp, MRangeArguments $arguments)
* @method array tsmrevrange(string|int|float $fromTimestamp, string|int|float $toTimestamp, MRangeArguments $arguments)
* @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 array tsrange(string $key, string|int|float $fromTimestamp, string|int|float $toTimestamp, ?RangeArguments $arguments = null)
* @method array tsrevrange(string $key, string|int|float $fromTimestamp, string|int|float $toTimestamp, ?RangeArguments $arguments = 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)
@@ -292,73 +307,78 @@ 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)
* @method int pfadd(string $key, array $elements)
* @method mixed pfmerge(string $destinationKey, array|string $sourceKeys)
* @method int pfcount(string[]|string $keyOrKeys, string ...$keys = null)
* @method mixed pubsub($subcommand, $argument)
* @method int publish($channel, $message)
* @method mixed pubsub(string $subcommand, string|int|float $argument)
* @method int publish(string $channel, string|int|float $message)
* @method mixed discard()
* @method array|null exec()
* @method mixed multi()
* @method mixed unwatch()
* @method mixed watch(string $key)
* @method array waitaof(int $numLocal, int $numReplicas, int $timeout)
* @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 mixed script(string $subcommand, $argument = null)
* @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()
* @method mixed client($subcommand, $argument = null)
* @method mixed config($subcommand, $argument = null)
* @method mixed client(string $subcommand, $argument = null)
* @method mixed config(string $subcommand, $argument = null)
* @method int dbsize()
* @method mixed flushall()
* @method mixed flushdb()
* @method array info($section = null)
* @method array info(?string $section = null)
* @method int lastsave()
* @method mixed save()
* @method mixed slaveof(string $host, int $port)
* @method mixed slowlog($subcommand, $argument = null)
* @method mixed slowlog(string $subcommand, $argument = null)
* @method array time()
* @method array command()
* @method int geoadd(string $key, $longitude, $latitude, $member)
* @method int geoadd(string $key, string|float $longitude, string|float $latitude, string $member)
* @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 string|null geodist(string $key, string $member1, string $member2, string $unit = null)
* @method array georadius(string $key, string|float $longitude, string|float $latitude, int $radius, string $unit, ?array $options = null)
* @method array georadiusbymember(string $key, string $member, int $radius, string $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
{
+20 -1
View File
@@ -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,6 +53,7 @@ abstract class ClusterStrategy implements StrategyInterface
'SORT' => [$this, 'getKeyFromSortCommand'],
'DUMP' => $getKeyFromFirstArgument,
'RESTORE' => $getKeyFromFirstArgument,
'FLUSHDB' => [$this, 'getFakeKey'],
/* commands operating on string values */
'APPEND' => $getKeyFromFirstArgument,
@@ -162,6 +163,11 @@ abstract class ClusterStrategy implements StrategyInterface
/* scripting */
'EVAL' => [$this, 'getKeyFromScriptingCommands'],
'EVALSHA' => [$this, 'getKeyFromScriptingCommands'],
'EVAL_RO' => [$this, 'getKeyFromScriptingCommands'],
'EVALSHA_RO' => [$this, 'getKeyFromScriptingCommands'],
/* server */
'INFO' => [$this, 'getFakeKey'],
/* commands performing geospatial operations */
'GEOADD' => $getKeyFromFirstArgument,
@@ -170,6 +176,9 @@ abstract class ClusterStrategy implements StrategyInterface
'GEODIST' => $getKeyFromFirstArgument,
'GEORADIUS' => [$this, 'getKeyFromGeoradiusCommands'],
'GEORADIUSBYMEMBER' => [$this, 'getKeyFromGeoradiusCommands'],
/* cluster */
'CLUSTER' => [$this, 'getFakeKey'],
];
}
@@ -216,6 +225,16 @@ abstract class ClusterStrategy implements StrategyInterface
$this->commands[$commandID] = $callback;
}
/**
* Get fake key for commands with no key argument.
*
* @return string
*/
protected function getFakeKey(): string
{
return 'key';
}
/**
* Extracts the key from the first argument of a command instance.
*
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
}
+3 -3
View File
@@ -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();
+3 -3
View File
@@ -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();
+209
View File
@@ -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
View File
@@ -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);
}
}
+145
View File
@@ -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();
}
}
+1 -1
View File
@@ -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;
}
}
/**
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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