mirror of
https://github.com/predis/predis.git
synced 2026-08-20 06:12:02 +00:00
Compare commits
71 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1183f5732e | |||
| 83dbdbeb43 | |||
| 5d85628a11 | |||
| 8b9f882a43 | |||
| e851ed6ceb | |||
| 861bde010a | |||
| 53504469d7 | |||
| d8a99ef674 | |||
| a24a7be9b4 | |||
| 95e802430d | |||
| 0703c3cae6 | |||
| 7c7cf90152 | |||
| b211afd755 | |||
| 980326d5d8 | |||
| 0ae180c942 | |||
| 98c853a689 | |||
| 153097374b | |||
| 6ef87493ca | |||
| 80430b4cde | |||
| d0f37f0bac | |||
| f11e855047 | |||
| ce853ecec2 | |||
| f4dcf6ce57 | |||
| 72a95b3d75 | |||
| 62f4ebcc37 | |||
| f26a13c8f4 | |||
| 44e4546ccd | |||
| da7b1cedb7 | |||
| fd1a0fc278 | |||
| 7a15da293b | |||
| d9dfefd247 | |||
| 8a0c70baa5 | |||
| 053cb4b6ac | |||
| 0f4bc7653c | |||
| 9e9deec4df | |||
| c1845d96cc | |||
| 8f18de1c12 | |||
| 6d37dc45b0 | |||
| 1c96f704fc | |||
| b10cf7c96a | |||
| 202e0c5322 | |||
| 6387da61d4 | |||
| 97bce0062d | |||
| fe1ea1b8f9 | |||
| 302b63b742 | |||
| 8e7afbe679 | |||
| c60003a717 | |||
| 4dcc66f47e | |||
| e0a03c6590 | |||
| 5e59123f0a | |||
| 7509e5f42d | |||
| efc2c3798c | |||
| ec375afa4a | |||
| 9992595711 | |||
| 33e1174a4f | |||
| 1e390b1814 | |||
| 0a8fe54b44 | |||
| b5b486a254 | |||
| 5e18e91ffc | |||
| c2b95dfd2a | |||
| 30e48f566e | |||
| d7f60099a6 | |||
| 6021daf9cd | |||
| 2372b5c767 | |||
| 87e08a3709 | |||
| 421827625e | |||
| afa8b55aa3 | |||
| 34fb0a7da0 | |||
| 06c904af37 | |||
| 9b1c6d2c8f | |||
| 3cc35471e6 |
+2
-14
@@ -1,14 +1,2 @@
|
||||
# Default
|
||||
* @tillkruss
|
||||
|
||||
# Redis commands
|
||||
src/Command/Redis/* @predis/team @tillkruss
|
||||
|
||||
# Redis Stack
|
||||
src/Command/Redis/Json/* @predis/team
|
||||
src/Command/Redis/Search/* @predis/team
|
||||
src/Command/Redis/TopK/* @predis/team
|
||||
src/Command/Redis/TDigest/* @predis/team
|
||||
src/Command/Redis/BloomFilter/* @predis/team
|
||||
src/Command/Redis/CuckooFilter/* @predis/team
|
||||
src/Command/Redis/CountMinSketch/* @predis/team
|
||||
* @predis/maintainers
|
||||
src/Relay* @tillkruss
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
services:
|
||||
|
||||
redis-official:
|
||||
image: ${REDIS_IMAGE_NAME:-redis:7.4}
|
||||
image: ${REDIS_IMAGE_NAME:-redis:8.0}
|
||||
container_name: redis-official
|
||||
healthcheck:
|
||||
test: [ "CMD", "redis-cli", "PING" ]
|
||||
@@ -12,20 +12,24 @@ services:
|
||||
retries: 3
|
||||
ports:
|
||||
- "6379:6379"
|
||||
command:
|
||||
- --requirepass "foobar"
|
||||
profiles:
|
||||
- all
|
||||
- official
|
||||
- standalone
|
||||
|
||||
redis-clients:
|
||||
image: ${REDIS_IMAGE_NAME:-redislabs/client-libs-test:7.4.2}
|
||||
image: ${REDIS_IMAGE_NAME:-redislabs/client-libs-test:8.0.2}
|
||||
container_name: redis-standalone
|
||||
environment:
|
||||
- TLS_ENABLED=yes
|
||||
- TLS_CLIENT_CNS=test_user
|
||||
- REDIS_CLUSTER=no
|
||||
- REDIS_PASSWORD=foobar
|
||||
- PORT=6379
|
||||
- TLS_PORT=6666
|
||||
command: ${REDIS_EXTRA_ARGS:---enable-debug-command yes --enable-module-command yes --tls-auth-clients optional --save ""}
|
||||
command: ${REDIS_EXTRA_ARGS:---enable-debug-command yes --enable-module-command yes --tls-auth-clients optional --save "" --requirepass "foobar"}
|
||||
ports:
|
||||
- 6379:6379
|
||||
- 6666:6666 # TLS port
|
||||
@@ -36,19 +40,40 @@ services:
|
||||
- clients
|
||||
- standalone
|
||||
|
||||
redis-unprotected:
|
||||
image: ${REDIS_IMAGE_NAME:-redislabs/client-libs-test:8.0.2}
|
||||
container_name: redis-unprotected
|
||||
environment:
|
||||
- TLS_ENABLED=no
|
||||
- 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:
|
||||
- 6380:6379
|
||||
volumes:
|
||||
- "./dockers/unprotected:/redis/work"
|
||||
profiles:
|
||||
- all
|
||||
- clients
|
||||
- unprotected
|
||||
|
||||
redis-cluster:
|
||||
image: ${REDIS_IMAGE_NAME:-redislabs/client-libs-test:7.4.2}
|
||||
image: ${REDIS_IMAGE_NAME:-redislabs/client-libs-test:8.0.2}
|
||||
container_name: redis-cluster
|
||||
environment:
|
||||
- REDIS_CLUSTER=yes
|
||||
- REDIS_PASSWORD=foobar
|
||||
- NODES=6
|
||||
- REPLICAS=1
|
||||
- TLS_ENABLED=yes
|
||||
- PORT=16379
|
||||
- TLS_CLIENT_CNS=test_user
|
||||
- PORT=6372
|
||||
- TLS_PORT=27379
|
||||
command: ${REDIS_EXTRA_ARGS:---enable-debug-command yes --enable-module-command yes --tls-auth-clients optional --save ""}
|
||||
command: ${REDIS_EXTRA_ARGS:---enable-debug-command yes --enable-module-command yes --tls-auth-clients optional --save "" --requirepass "foobar"}
|
||||
ports:
|
||||
- "6372-6377:16379-16384"
|
||||
- "6372-6377:6372-6377"
|
||||
- "27379-27384:27379-27384"
|
||||
volumes:
|
||||
- "./dockers/cluster:/redis/work"
|
||||
profiles:
|
||||
@@ -63,8 +88,9 @@ services:
|
||||
- "6479:6379"
|
||||
environment:
|
||||
- REDIS_CLUSTER=no
|
||||
- REDIS_PASSWORD=foobar
|
||||
- PORT=6379
|
||||
command: ${REDIS_EXTRA_ARGS:---enable-debug-command yes --enable-module-command yes --save ""}
|
||||
command: ${REDIS_EXTRA_ARGS:---enable-debug-command yes --enable-module-command yes --save "" --requirepass "foobar"}
|
||||
volumes:
|
||||
- "./dockers/redis-stack:/redis/work"
|
||||
profiles:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name-template: 'v$NEXT_MINOR_VERSION'
|
||||
tag-template: 'v$NEXT_MINOR_VERSION'
|
||||
change-template: '- $TITLE (#$NUMBER)'
|
||||
filter-by-comitish: true
|
||||
filter-by-commitish: true
|
||||
commitish: v3.x
|
||||
|
||||
autolabeler:
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
ACLs
|
||||
AUTH
|
||||
Autoloading
|
||||
cafile
|
||||
CAS
|
||||
CN
|
||||
Customizable
|
||||
ElastiCache
|
||||
FPM
|
||||
GC
|
||||
IANA
|
||||
mTLS
|
||||
Lua
|
||||
PSR
|
||||
Packagist
|
||||
|
||||
+40
-21
@@ -31,6 +31,9 @@ jobs:
|
||||
- '7.2'
|
||||
- '7.4'
|
||||
- '8.0'
|
||||
- '8.2'
|
||||
- '8.4'
|
||||
- '8.6'
|
||||
|
||||
steps:
|
||||
|
||||
@@ -38,7 +41,10 @@ jobs:
|
||||
run: |
|
||||
# Mapping of original redis versions to client test containers
|
||||
declare -A redis_clients_version_mapping=(
|
||||
["8.0"]="8.0-RC2-pre"
|
||||
["8.6"]="8.6.0"
|
||||
["8.4"]="8.4.0"
|
||||
["8.2"]="8.2.2"
|
||||
["8.0"]="8.0.2"
|
||||
["7.4"]="7.4.2"
|
||||
["7.2"]="7.2.7"
|
||||
)
|
||||
@@ -78,6 +84,13 @@ jobs:
|
||||
compose-file: .github/docker-compose.yml
|
||||
services: ${{ env.DOCKER_SERVICE }}
|
||||
|
||||
- name: Start Redis unprotected image
|
||||
uses: hoverkraft-tech/compose-action@v2.0.1
|
||||
if: ${{ matrix.redis > '4.0' }}
|
||||
with:
|
||||
compose-file: .github/docker-compose.yml
|
||||
services: redis-unprotected
|
||||
|
||||
- name: Start Redis stack image
|
||||
id: stack_infra
|
||||
uses: hoverkraft-tech/compose-action@v2.0.1
|
||||
@@ -98,8 +111,8 @@ jobs:
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
extensions: relay
|
||||
coverage: ${{ (matrix.php == '8.4' && matrix.redis == '7.4') && 'xdebug' || 'none' }}
|
||||
extensions: relay-nightly
|
||||
coverage: ${{ (matrix.php == '8.4' && matrix.redis == '8.0') && 'xdebug' || 'none' }}
|
||||
|
||||
- name: Install Composer dependencies
|
||||
uses: ramsey/composer-install@v2
|
||||
@@ -108,68 +121,74 @@ jobs:
|
||||
composer-options: ${{ matrix.php == '8.0' && '--ignore-platform-reqs' || '' }}
|
||||
|
||||
- name: Run tests
|
||||
if: ${{ matrix.php != '8.4' || matrix.redis != '7.4' }}
|
||||
if: ${{ matrix.php != '8.4' || matrix.redis != '8.0' }}
|
||||
run: vendor/bin/phpunit
|
||||
|
||||
- name: Run tests with coverage
|
||||
if: ${{ matrix.php == '8.4' && matrix.redis == '7.4' }}
|
||||
if: ${{ matrix.php == '8.4' && matrix.redis == '8.0' }}
|
||||
run: vendor/bin/phpunit --coverage-php build/cov/coverage-predis.cov --coverage-filter ./src
|
||||
|
||||
- name: Run tests using Relay
|
||||
if: ${{ matrix.php != '8.4' && matrix.redis >= '7.2' }}
|
||||
if: ${{ matrix.php != '8.4' && matrix.redis >= '8.0' }}
|
||||
run: vendor/bin/phpunit -c phpunit.relay.xml
|
||||
|
||||
- name: Run tests using Relay with coverage
|
||||
if: ${{ matrix.php == '8.4' && matrix.redis == '7.4' }}
|
||||
if: ${{ matrix.php == '8.4' && matrix.redis == '8.0' }}
|
||||
run: vendor/bin/phpunit -c phpunit.relay.xml --coverage-php build/cov/coverage-relay.cov --coverage-filter ./src
|
||||
|
||||
- name: Run tests against unprotected Redis
|
||||
if: ${{ (matrix.php != '8.4' || matrix.redis != '8.0') && matrix.redis > '4.0'}}
|
||||
run: vendor/bin/phpunit --group unprotected
|
||||
|
||||
- name: Run tests against unprotected Redis with coverage
|
||||
if: ${{ matrix.php == '8.4' && matrix.redis == '8.0' }}
|
||||
run: vendor/bin/phpunit --group unprotected --coverage-php build/cov/coverage-unprotected.cov --coverage-filter ./src
|
||||
|
||||
- name: Run stack tests
|
||||
if: ${{ (matrix.php != '8.4' || matrix.redis != '7.4') && matrix.redis >= '7.2' }}
|
||||
if: ${{ (matrix.php != '8.4' || matrix.redis != '8.0') && matrix.redis >= '7.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' }}
|
||||
if: ${{ matrix.php == '8.4' && matrix.redis == '8.0' }}
|
||||
run: vendor/bin/phpunit --group realm-stack --coverage-php build/cov/coverage-stack.cov --coverage-filter ./src
|
||||
env:
|
||||
REDIS_STACK_SERVER_PORT: 6479
|
||||
|
||||
- name: Run stack tests using Relay
|
||||
if: ${{ matrix.php != '8.4' && matrix.redis == '7.4' }}
|
||||
if: ${{ (matrix.php != '8.4' || matrix.redis != '8.0') && matrix.redis >= '7.2' }}
|
||||
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' }}
|
||||
if: ${{ matrix.php == '8.4' && matrix.redis == '8.0' }}
|
||||
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' }}
|
||||
if: ${{ (matrix.php != '8.4' || matrix.redis != '8.0') && steps.cluster_infra.conclusion == 'success' }}
|
||||
run: |
|
||||
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' }}
|
||||
if: ${{ matrix.php == '8.4' && matrix.redis == '8.0' && 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' }}
|
||||
if: ${{ matrix.php != '8.4' && matrix.redis == '8.0' }}
|
||||
run: |
|
||||
sleep 5
|
||||
vendor/bin/phpunit -c phpunit.relay.xml --group cluster
|
||||
|
||||
- name: Run tests against cluster using Relay with coverage
|
||||
if: ${{ matrix.php == '8.4' && matrix.redis == '7.4' }}
|
||||
if: ${{ matrix.php == '8.4' && matrix.redis == '8.0' }}
|
||||
run: |
|
||||
sleep 5
|
||||
vendor/bin/phpunit -c phpunit.relay.xml --group cluster --coverage-php build/cov/coverage-cluster-relay.cov --coverage-filter ./src
|
||||
|
||||
- name: Merge coverage reports
|
||||
if: ${{ matrix.php == '8.4' && matrix.redis == '7.4' }}
|
||||
if: ${{ matrix.php == '8.4' && matrix.redis == '8.0' }}
|
||||
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' }}
|
||||
if: ${{ matrix.php == '8.4' && matrix.redis == '8.0' }}
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
parallel: true
|
||||
|
||||
@@ -1,5 +1,70 @@
|
||||
## Changelog
|
||||
|
||||
## v3.4.0 (2026-02-11)
|
||||
### Added
|
||||
- Added optional retry support (#1616)
|
||||
- Added support for `VRANGE` command (#1623)
|
||||
- Added support for idempotent stream API (#1632)
|
||||
- Added support for `HOTKEYS` container command (#1630)
|
||||
|
||||
### Fixed
|
||||
- Fixed `[L|R]PUSHX` variadic arguments normalization (#1633)
|
||||
- Fixed wrong `@param` annotation in `Parameters` (#1614)
|
||||
- Made `ZRANDMEMBER` prefixable (#1621)
|
||||
- Improve connection handshake by pipelining commands (#1622)
|
||||
|
||||
## v3.3.0 (2025-11-24)
|
||||
### Added
|
||||
- Added cluster support for `XADD`, `XDEL` and `XRANGE` (#1587)
|
||||
- Added prefixable interface for `HEXPIRE` and `HEXPIRETIME` (#1592)
|
||||
- Added new experimental CAS/CAD functionality (#1609)
|
||||
- Added temporary `XREADGROUP_CLAIM` command (#1608)
|
||||
- Added support for `MSET` command (#1610)
|
||||
- Added experimental support for `FT.HYBRID` (#1607)
|
||||
|
||||
### Changed
|
||||
- Improved compatiblity with Relay (#1597)
|
||||
- Refactor pipeline data writing depends on connection type (#1586)
|
||||
|
||||
## v3.2.0 (2025-08-05)
|
||||
### Added
|
||||
- Added support for `XDELEX` and `XACKDEL` (#1580)
|
||||
- Added missing VSIM argument (#1582)
|
||||
|
||||
### Changed
|
||||
- Extended `XTRIM` and `XADD` commands with new parameters (#1580)
|
||||
|
||||
### Maintenance
|
||||
- Updated Redis 8.2 test image (#1583)
|
||||
- Added test coverage for updated Vamana (#1584)
|
||||
|
||||
## v3.1.0 (2025-07-22)
|
||||
### Added
|
||||
- Add experimental support for vector sets commands (#1550)
|
||||
- Added support for `XACK` command (#1555)
|
||||
- Added support for `XCLAIM` command (#1557)
|
||||
- Added support for `XPENDING` command (#1558)
|
||||
- Added support for `XSETID` command (#1559)
|
||||
- Added validation and support for the new `BITOP` command operations (#1566)
|
||||
|
||||
### Changed
|
||||
- Handle and retry `LOADING` errors from Sentinel replicas (#1536)
|
||||
- Retry all exceptions from Sentinel replicas (#1577)
|
||||
|
||||
### Fixed
|
||||
- Fixed PHP 8.4 deprecated call to `stream_context_set_option()` (#1545)
|
||||
- Fixed return type for `ZCOUNT` to be `int` (#1547)
|
||||
- Fixed throwing `CommunicationException` when stream is EOF (#1548)
|
||||
- Removed automatic `conn_uid` parameter assignment (#1552)
|
||||
- Fixed wrong command API call on prefix processing (#1554)
|
||||
- Fixed `XREAD` response parsing while read null (#1563)
|
||||
- Fixed `XINFO` command responses parsing (#1560)
|
||||
- Marked missing commands as Prefixable (#1576)
|
||||
|
||||
## v3.0.1 (2025-05-16)
|
||||
### Fixed
|
||||
- Send `default` user if only password is used for authentication (#1535)
|
||||
|
||||
## v3.0.0 (2025-05-02)
|
||||
### Added
|
||||
- ⚠️ Added support for transactions for clustered connections (#1497)
|
||||
@@ -24,6 +89,9 @@
|
||||
### Fixed
|
||||
- Fixed single persistent connection using the same resource (#1512)
|
||||
|
||||
### Maintenance
|
||||
- Revisit incompatible tests against Relay (#1537)
|
||||
|
||||
## v2.4.0 (2025-04-30)
|
||||
### Added
|
||||
- Added new hash-field expiration commands (#1520)
|
||||
|
||||
@@ -114,6 +114,40 @@ The connection schemes [`redis`](http://www.iana.org/assignments/uri-schemes/pro
|
||||
also supported, with the difference that URI strings containing these schemes are parsed following
|
||||
the rules described on their respective IANA provisional registration documents.
|
||||
|
||||
Since Redis 8.6, you can authenticate a client using the Subject CN from its TLS client certificate (mTLS).
|
||||
When this is enabled on the server, the client is authenticated during the TLS handshake, so you don’t need
|
||||
to send an AUTH command.
|
||||
|
||||
To use this, configure:
|
||||
|
||||
- a CA certificate used to verify the server certificate (cafile),
|
||||
- a client certificate (local_cert) signed by a CA trusted by the Redis server for client authentication,
|
||||
- the corresponding private key (local_pk).
|
||||
|
||||
Make sure:
|
||||
|
||||
- the Redis server certificate is signed by a CA trusted by the client, and
|
||||
- the client certificate is signed by a CA trusted by the Redis server (mTLS).
|
||||
|
||||
```php
|
||||
// Named array of connection parameters:
|
||||
$client = new Predis\Client([
|
||||
'scheme' => 'tls',
|
||||
'ssl' => [
|
||||
'cafile' => 'ca.pem', // CA used to verify the server certificate
|
||||
'local_cert' => 'client.crt', // client certificate (Subject CN maps to ACL user)
|
||||
'local_pk' => 'client.key', // client private key
|
||||
'verify_peer' => true,
|
||||
],
|
||||
]);
|
||||
|
||||
// ACL user must exist and match the certificate Subject CN (example: CN=CN_NAME).
|
||||
// Enable the user and grant permissions as needed:
|
||||
$client->acl->setUser('CN_NAME', 'on', '>clientpass', 'allcommands', 'allkeys')
|
||||
|
||||
echo $client->acl->whoami() // CN_NAME
|
||||
```
|
||||
|
||||
The actual list of supported connection parameters can vary depending on each connection backend so
|
||||
it is recommended to refer to their specific documentation or implementation for details.
|
||||
|
||||
@@ -138,6 +172,50 @@ it is still desired to have control of when the connection is opened or closed:
|
||||
achieved by invoking `$client->connect()` and `$client->disconnect()`. Please note that the effect
|
||||
of these methods on aggregate connections may differ depending on each specific implementation.
|
||||
|
||||
#### Persistent connections ####
|
||||
|
||||
To increase a performance of your application you may set up a client to use persistent TCP connection, this way
|
||||
client saves a time on socket creation and connection handshake. By default, connection is created on first-command
|
||||
execution and will be automatically closed by GC before the process is being killed.
|
||||
However, if your application is backed by PHP-FPM the processes are idle, and you may set up it to be persistent and
|
||||
reusable across multiple script execution within the same process.
|
||||
|
||||
To enable the persistent connection mode you should provide following configuration:
|
||||
|
||||
```php
|
||||
// Standalone
|
||||
$client = new Predis\Client(['persistent' => true]);
|
||||
|
||||
// Cluster
|
||||
$client = new Predis\Client(
|
||||
['tcp://host:port', 'tcp://host:port', 'tcp://host:port'],
|
||||
['cluster' => 'redis', 'parameters' => ['persistent' => true]]
|
||||
);
|
||||
```
|
||||
|
||||
**Important**
|
||||
|
||||
If you operate on multiple clients within the same application, and they communicate with the same resource, by default
|
||||
they will share the same socket (that's the default behaviour of persistent sockets). So in this case you would need
|
||||
to additionally provide a `conn_uid` identifier for each client, this way each client will create its own socket so
|
||||
the connection context won't be shared across clients. This socket behaviour explained
|
||||
[here](https://www.php.net/manual/en/function.stream-socket-client.php#105393)
|
||||
|
||||
```php
|
||||
// Standalone
|
||||
$client1 = new Predis\Client(['persistent' => true, 'conn_uid' => 'id_1']);
|
||||
$client2 = new Predis\Client(['persistent' => true, 'conn_uid' => 'id_2']);
|
||||
|
||||
// Cluster
|
||||
$client1 = new Predis\Client(
|
||||
['tcp://host:port', 'tcp://host:port', 'tcp://host:port'],
|
||||
['cluster' => 'redis', 'parameters' => ['persistent' => true, 'conn_uid' => 'id_1']]
|
||||
);
|
||||
$client2 = new Predis\Client(
|
||||
['tcp://host:port', 'tcp://host:port', 'tcp://host:port'],
|
||||
['cluster' => 'redis', 'parameters' => ['persistent' => true, 'conn_uid' => 'id_2']]
|
||||
);
|
||||
```
|
||||
|
||||
### Client configuration ###
|
||||
|
||||
@@ -465,6 +543,43 @@ $client = new Predis\Client('tcp://127.0.0.1', [
|
||||
For a more in-depth insight on how to create new connection backends you can refer to the actual
|
||||
implementation of the standard connection classes available in the `Predis\Connection` namespace.
|
||||
|
||||
### Retry exceptions
|
||||
|
||||
You can enable automatic retry that is disabled by default, to be able to reduce the amount of
|
||||
false-positives in case of network issues. By default, we're retrying on any connection,
|
||||
timeout or socket initialization exception, but you can update the list of retry
|
||||
exceptions. For now `EqualBackoff` and `ExponentialBackoff` strategies are available,
|
||||
but you may provide your custom one. Retry may be configured with any type of communication
|
||||
(standalone node, cluster, pipeline, transaction, replication). Here's an example of
|
||||
configuration:
|
||||
|
||||
```php
|
||||
// Standalone client
|
||||
$client = new Predis\Client([
|
||||
'retry' => new \Predis\Retry\Retry(
|
||||
new \Predis\Retry\Strategy\ExponentialBackoff(1000, 10000), // Base and cap configuration in microseconds
|
||||
3 // Number of retries
|
||||
),
|
||||
]);
|
||||
|
||||
// Cluster configuration
|
||||
$options = [
|
||||
'parameters' => [
|
||||
'retry' => new \Predis\Retry\Retry(new \Predis\Retry\Strategy\ExponentialBackoff(1000, 10000), 3),
|
||||
],
|
||||
];
|
||||
|
||||
$client = new Predis\Client(['tcp://host:port', 'tcp://host:port', 'tcp://host:port'], $options);
|
||||
|
||||
$retry = new \Predis\Retry\Retry(
|
||||
new \Predis\Retry\Strategy\ExponentialBackoff(1000, 10000),
|
||||
3
|
||||
);
|
||||
|
||||
// Update a list of exceptions to catch
|
||||
$retry->updateCatchableExceptions([Exception::class]);
|
||||
```
|
||||
|
||||
## RESP3 ##
|
||||
|
||||
### Connection ###
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// For example, to generate a test case for SET (which is represented by the
|
||||
// Predis\Command\Redis\StringSet class):
|
||||
//
|
||||
// $ ./bin/generate-command-test --class=StringSet
|
||||
// $ ./bin/create-command-test --class=StringSet
|
||||
//
|
||||
// Here is a list of optional arguments:
|
||||
//
|
||||
|
||||
+7
-1
@@ -46,7 +46,13 @@
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true,
|
||||
"preferred-install": "dist"
|
||||
"preferred-install": "dist",
|
||||
"audit": {
|
||||
"ignore": [
|
||||
"GHSA-vvj3-c3rp-c85p",
|
||||
"PKSA-z3gr-8qht-p93v"
|
||||
]
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true
|
||||
|
||||
@@ -34,11 +34,11 @@ class SimpleDebuggableConnection extends StreamConnection
|
||||
|
||||
private function storeDebug(CommandInterface $command, $direction)
|
||||
{
|
||||
$firtsArg = $command->getArgument(0);
|
||||
$firstArg = $command->getArgument(0);
|
||||
$timestamp = round(microtime(true) - $this->tstart, 4);
|
||||
|
||||
$debug = $command->getId();
|
||||
$debug .= isset($firtsArg) ? " $firtsArg " : ' ';
|
||||
$debug .= isset($firstArg) ? " $firstArg " : ' ';
|
||||
$debug .= "$direction $this";
|
||||
$debug .= " [{$timestamp}s]";
|
||||
|
||||
|
||||
+2
-2
@@ -22,9 +22,9 @@ function redis_version($info)
|
||||
return $info['Server']['redis_version'];
|
||||
} elseif (isset($info['redis_version'])) {
|
||||
return $info['redis_version'];
|
||||
} else {
|
||||
return 'unknown version';
|
||||
}
|
||||
|
||||
return 'unknown version';
|
||||
}
|
||||
|
||||
$single_server = [
|
||||
|
||||
@@ -29,9 +29,6 @@ parameters:
|
||||
- message: "#^Access to an undefined property Predis\\\\Connection\\\\ParametersInterface\\:\\:\\$weight\\.$#"
|
||||
count: 1
|
||||
path: src/Connection/Cluster/PredisCluster.php
|
||||
- message: "#^Variable \\$response might not be defined\\.$#"
|
||||
count: 2
|
||||
path: src/Connection/Cluster/RedisCluster.php
|
||||
- message: "#^Access to an undefined property Predis\\\\Connection\\\\ParametersInterface\\:\\:\\$role\\.$#"
|
||||
count: 1
|
||||
path: src/Connection/Replication/MasterSlaveReplication.php
|
||||
@@ -45,6 +42,3 @@ parameters:
|
||||
- message: "#^Variable \\$response might not be defined\\.$#"
|
||||
count: 1
|
||||
path: src/Connection/Replication/MasterSlaveReplication.php
|
||||
- message: "#^Variable \\$response might not be defined\\.$#"
|
||||
count: 1
|
||||
path: src/Connection/Replication/SentinelReplication.php
|
||||
|
||||
+7
-1
@@ -29,6 +29,7 @@
|
||||
<group>ext-curl</group>
|
||||
<group>cluster</group>
|
||||
<group>gears</group>
|
||||
<group>unprotected</group>
|
||||
</exclude>
|
||||
</groups>
|
||||
|
||||
@@ -41,12 +42,17 @@
|
||||
<php>
|
||||
<const name="REDIS_SERVER_HOST" value="127.0.0.1" />
|
||||
<const name="REDIS_SERVER_PORT" value="6379" />
|
||||
<const name="REDIS_UNPROTECTED_SERVER_PORT" value="6380" />
|
||||
<const name="REDIS_SERVER_DBNUM" value="0" />
|
||||
<const name="REDIS_PASSWORD" value="foobar" />
|
||||
<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" />
|
||||
<const
|
||||
name="REDIS_CLUSTER_ENDPOINTS"
|
||||
value="127.0.0.1:6372?password=foobar,127.0.0.1:6373?password=foobar,127.0.0.1:6374?password=foobar"
|
||||
/>
|
||||
</php>
|
||||
</phpunit>
|
||||
|
||||
+24
-1
@@ -10,6 +10,9 @@
|
||||
stopOnFailure="false"
|
||||
beStrictAboutTestsThatDoNotTestAnything="true"
|
||||
>
|
||||
<php>
|
||||
<ini name="error_reporting" value="E_ALL & ~E_DEPRECATED"/>
|
||||
</php>
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="Predis Test Suite">
|
||||
@@ -29,6 +32,7 @@
|
||||
<group>cluster</group>
|
||||
<group>gears</group>
|
||||
<group>gears-cluster</group>
|
||||
<group>unprotected</group>
|
||||
<!-- <group>connected</group> -->
|
||||
<!-- <group>disconnected</group> -->
|
||||
<!-- <group>commands</group> -->
|
||||
@@ -45,12 +49,31 @@
|
||||
<php>
|
||||
<const name="REDIS_SERVER_HOST" value="127.0.0.1" />
|
||||
<const name="REDIS_SERVER_PORT" value="6379" />
|
||||
<const name="REDIS_UNPROTECTED_SERVER_PORT" value="6380" />
|
||||
<const name="REDIS_SERVER_DBNUM" value="0" />
|
||||
<const name="REDIS_PASSWORD" value="foobar" />
|
||||
<env name="USE_RELAY" value="false" />
|
||||
<env name="REDIS_STACK_SERVER_PORT" value="6479" />
|
||||
|
||||
<!-- SSL -->
|
||||
<env name="STANDALONE_CA_CERT_PATH" value=".github/dockers/standalone/tls/ca.crt" />
|
||||
<env name="STANDALONE_LOCAL_CERT_PATH" value=".github/dockers/standalone/tls/test_user.crt" />
|
||||
<env name="STANDALONE_LOCAL_PK_PATH" value=".github/dockers/standalone/tls/test_user.key" />
|
||||
<env name="CN_USER_NAME" value="test_user" />
|
||||
<env name="REDIS_SSL_PORT" value="6666" />
|
||||
<env name="CLUSTER_CA_CERT_PATH" value=".github/dockers/cluster/tls/ca.crt" />
|
||||
<env name="CLUSTER_LOCAL_CERT_PATH" value=".github/dockers/cluster/tls/test_user.crt" />
|
||||
<env name="CLUSTER_LOCAL_PK_PATH" value=".github/dockers/cluster/tls/test_user.key" />
|
||||
<const
|
||||
name="SSL_REDIS_CLUSTER_ENDPOINTS"
|
||||
value="127.0.0.1:27379?password=foobar,127.0.0.1:27380?password=foobar,127.0.0.1:27381?password=foobar"
|
||||
/>
|
||||
|
||||
<!-- 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" />
|
||||
<const
|
||||
name="REDIS_CLUSTER_ENDPOINTS"
|
||||
value="127.0.0.1:6372?password=foobar,127.0.0.1:6373?password=foobar,127.0.0.1:6374?password=foobar"
|
||||
/>
|
||||
</php>
|
||||
</phpunit>
|
||||
|
||||
+21
-8
@@ -22,6 +22,7 @@ use Predis\Command\RawCommand;
|
||||
use Predis\Command\ScriptCommand;
|
||||
use Predis\Configuration\Options;
|
||||
use Predis\Configuration\OptionsInterface;
|
||||
use Predis\Connection\AggregateConnectionInterface;
|
||||
use Predis\Connection\ConnectionInterface;
|
||||
use Predis\Connection\Parameters;
|
||||
use Predis\Connection\ParametersInterface;
|
||||
@@ -41,6 +42,7 @@ use Predis\Response\ServerException;
|
||||
use Predis\Transaction\MultiExec as MultiExecTransaction;
|
||||
use ReturnTypeWillChange;
|
||||
use RuntimeException;
|
||||
use Throwable;
|
||||
use Traversable;
|
||||
|
||||
/**
|
||||
@@ -54,7 +56,7 @@ use Traversable;
|
||||
*/
|
||||
class Client implements ClientInterface, IteratorAggregate
|
||||
{
|
||||
public const VERSION = '3.0.0';
|
||||
public const VERSION = '3.4.0';
|
||||
|
||||
/** @var OptionsInterface */
|
||||
private $options;
|
||||
@@ -90,9 +92,8 @@ class Client implements ClientInterface, IteratorAggregate
|
||||
return new Options($options);
|
||||
} elseif ($options instanceof OptionsInterface) {
|
||||
return $options;
|
||||
} else {
|
||||
throw new InvalidArgumentException('Invalid type for client options');
|
||||
}
|
||||
throw new InvalidArgumentException('Invalid type for client options');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -138,11 +139,10 @@ class Client implements ClientInterface, IteratorAggregate
|
||||
return $initializer($parameters, true);
|
||||
} elseif ($options->defined('aggregate') && $initializer = $options->aggregate) {
|
||||
return $initializer($parameters, false);
|
||||
} else {
|
||||
throw new InvalidArgumentException(
|
||||
'Array of connection parameters requires `cluster`, `replication` or `aggregate` client option'
|
||||
);
|
||||
}
|
||||
throw new InvalidArgumentException(
|
||||
'Array of connection parameters requires `cluster`, `replication` or `aggregate` client option'
|
||||
);
|
||||
}
|
||||
|
||||
if (is_callable($parameters)) {
|
||||
@@ -376,12 +376,25 @@ class Client implements ClientInterface, IteratorAggregate
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function executeCommand(CommandInterface $command)
|
||||
{
|
||||
$response = $this->connection->executeCommand($command);
|
||||
$parameters = $this->connection->getParameters();
|
||||
|
||||
if ($this->connection instanceof AggregateConnectionInterface || $this->connection instanceof RelayConnection) {
|
||||
$response = $this->connection->executeCommand($command);
|
||||
} else {
|
||||
$response = $parameters->retry->callWithRetry(
|
||||
function () use ($command) {
|
||||
return $this->connection->executeCommand($command);
|
||||
},
|
||||
function () {
|
||||
$this->connection->disconnect();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if ($response instanceof ResponseInterface) {
|
||||
if ($response instanceof ErrorResponseInterface) {
|
||||
$response = $this->onErrorResponse($command, $response);
|
||||
|
||||
@@ -19,6 +19,7 @@ use Predis\Command\Argument\Search\AlterArguments;
|
||||
use Predis\Command\Argument\Search\CreateArguments;
|
||||
use Predis\Command\Argument\Search\DropArguments;
|
||||
use Predis\Command\Argument\Search\ExplainArguments;
|
||||
use Predis\Command\Argument\Search\HybridSearch\HybridSearchQuery;
|
||||
use Predis\Command\Argument\Search\ProfileArguments;
|
||||
use Predis\Command\Argument\Search\SchemaFields\FieldInterface;
|
||||
use Predis\Command\Argument\Search\SearchArguments;
|
||||
@@ -41,16 +42,20 @@ use Predis\Command\CommandInterface;
|
||||
use Predis\Command\Container\ACL;
|
||||
use Predis\Command\Container\CLIENT;
|
||||
use Predis\Command\Container\FUNCTIONS;
|
||||
use Predis\Command\Container\HOTKEYS;
|
||||
use Predis\Command\Container\Json\JSONDEBUG;
|
||||
use Predis\Command\Container\Search\FTCONFIG;
|
||||
use Predis\Command\Container\Search\FTCURSOR;
|
||||
use Predis\Command\Container\XGROUP;
|
||||
use Predis\Command\Redis\VADD;
|
||||
|
||||
/**
|
||||
* Interface defining a client-side context such as a pipeline or transaction.
|
||||
*
|
||||
* @method $this copy(string $source, string $destination, int $db = -1, bool $replace = false)
|
||||
* @method $this del(array|string $keys)
|
||||
* @method $this delex(string $key, string $flag, $flagValue)
|
||||
* @method $this digest(string $key)
|
||||
* @method $this dump($key)
|
||||
* @method $this exists($key)
|
||||
* @method $this expire($key, $seconds, string $expireOption = '')
|
||||
@@ -125,6 +130,7 @@ use Predis\Command\Container\XGROUP;
|
||||
* @method $this ftdictdump(string $dict)
|
||||
* @method $this ftdropindex(string $index, ?DropArguments $arguments = null)
|
||||
* @method $this ftexplain(string $index, string $query, ?ExplainArguments $arguments = null)
|
||||
* @method $this fthybrid(string $index, HybridSearchQuery $query)
|
||||
* @method $this ftinfo(string $index)
|
||||
* @method $this ftprofile(string $index, ProfileArguments $arguments)
|
||||
* @method $this ftsearch(string $index, string $query, ?SearchArguments $arguments = null)
|
||||
@@ -147,9 +153,10 @@ use Predis\Command\Container\XGROUP;
|
||||
* @method $this incrbyfloat($key, $increment)
|
||||
* @method $this mget(array $keys)
|
||||
* @method $this mset(array $dictionary)
|
||||
* @method $this msetex(array $dictionary, ?string $existModifier = null, ?string $expireResolution = null, ?int $expireTTL = null)
|
||||
* @method $this msetnx(array $dictionary)
|
||||
* @method $this psetex($key, $milliseconds, $value)
|
||||
* @method $this set($key, $value, $expireResolution = null, $expireTTL = null, $flag = null)
|
||||
* @method $this set($key, $value, $expireResolution = null, $expireTTL = null, $flag = null, $flagValue = null)
|
||||
* @method $this setbit($key, $offset, $value)
|
||||
* @method $this setex($key, $seconds, $value)
|
||||
* @method $this setnx($key, $value)
|
||||
@@ -266,7 +273,7 @@ use Predis\Command\Container\XGROUP;
|
||||
* @method $this topklist(string $key, bool $withCount = false)
|
||||
* @method $this topkquery(string $key, ...$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 tsadd(string $key, int $timestamp, string|float $value, ?AddArguments $arguments = null)
|
||||
* @method $this tsalter(string $key, ?TSAlterArguments $arguments = null)
|
||||
* @method $this tscreate(string $key, ?TSCreateArguments $arguments = null)
|
||||
* @method $this tscreaterule(string $sourceKey, string $destKey, string $aggregator, int $bucketDuration, int $alignTimestamp = 0)
|
||||
@@ -283,6 +290,23 @@ use Predis\Command\Container\XGROUP;
|
||||
* @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 xack(string $key, string $group, string ...$id)
|
||||
* @method $this xackdel(string $key, string $group, string $mode, array $ids)
|
||||
* @method $this xadd(string $key, array $dictionary, string $id = '*', array $options = null)
|
||||
* @method $this xautoclaim(string $key, string $group, string $consumer, int $minIdleTime, string $start, ?int $count = null, bool $justId = false)
|
||||
* @method $this xclaim(string $key, string $group, string $consumer, int $minIdleTime, string|array $ids, ?int $idle = null, ?int $time = null, ?int $retryCount = null, bool $force = false, bool $justId = false, ?string $lastId = null)
|
||||
* @method $this xcfgset(string $key, ?int $duration = null, ?int $maxsize = null)
|
||||
* @method $this xdel(string $key, string ...$id)
|
||||
* @method $this xdelex(string $key, string $mode, array $ids)
|
||||
* @method $this xlen(string $key)
|
||||
* @method $this xpending(string $key, string $group, ?int $minIdleTime = null, ?string $start = null, ?string $end = null, ?int $count = null, ?string $consumer = null)
|
||||
* @method $this xrevrange(string $key, string $end, string $start, ?int $count = null)
|
||||
* @method $this xrange(string $key, string $start, string $end, ?int $count = null)
|
||||
* @method $this xread(int $count = null, int $block = null, array $streams = null, string ...$id)
|
||||
* @method $this xreadgroup(string $group, string $consumer, ?int $count = null, ?int $blockMs = null, bool $noAck = false, string ...$keyOrId)
|
||||
* @method $this xreadgroup_claim(string $group, string $consumer, array $keyIdDict, ?int $count = null, ?int $blockMs = null, bool $noAck = false, ?int $claim = null)
|
||||
* @method $this xsetid(string $key, string $lastId, ?int $entriesAdded = null, ?string $maxDeleteId = null)
|
||||
* @method $this xtrim(string $key, array|string $strategy, string $threshold, array $options = null)
|
||||
* @method $this zadd($key, array $membersAndScoresDictionary)
|
||||
* @method $this zcard($key)
|
||||
* @method $this zcount($key, $min, $max)
|
||||
@@ -325,6 +349,18 @@ use Predis\Command\Container\XGROUP;
|
||||
* @method $this unwatch()
|
||||
* @method $this waitaof(int $numLocal, int $numReplicas, int $timeout)
|
||||
* @method $this unsubscribe(string ...$channels)
|
||||
* @method $this vadd(string $key, string|array $vector, string $elem, int $dim = null, bool $cas = false, string $quant = VADD::QUANT_DEFAULT, ?int $BEF = null, string|array $attributes = null, int $numlinks = null)
|
||||
* @method $this vcard(string $key)
|
||||
* @method $this vdim(int $key)
|
||||
* @method $this vemb(string $key, string $elem, bool $raw = false)
|
||||
* @method $this vgetattr(string $key, string $elem, bool $asJson = false)
|
||||
* @method $this vinfo(string $key)
|
||||
* @method $this vlinks(string $key, string $elem, bool $withScores = false)
|
||||
* @method $this vrandmember(string $key, int $count = null)
|
||||
* @method $this vrange(string $key, string $start, string $end, int $count = null)
|
||||
* @method $this vrem(string $key, string $elem)
|
||||
* @method $this vsetattr(string $key, string $elem, string|array $attributes)
|
||||
* @method $this vsim(string $key, string|array $vectorOrElem, bool $isElem = false, bool $withScores = false, int $count = null, float $epsilon = null, int $ef = null, string $filter = null, int $filterEf = null, bool $truth = false, bool $noThread = false)
|
||||
* @method $this watch($key)
|
||||
* @method $this eval($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
|
||||
* @method $this eval_ro(string $script, array $keys, ...$argument)
|
||||
@@ -361,6 +397,7 @@ use Predis\Command\Container\XGROUP;
|
||||
*
|
||||
* Container commands
|
||||
* @property CLIENT $client
|
||||
* @property HOTKEYS $hotkeys
|
||||
* @property FUNCTIONS $function
|
||||
* @property FTCONFIG $ftconfig
|
||||
* @property FTCURSOR $ftcursor
|
||||
|
||||
+31
-3
@@ -19,6 +19,7 @@ use Predis\Command\Argument\Search\AlterArguments;
|
||||
use Predis\Command\Argument\Search\CreateArguments;
|
||||
use Predis\Command\Argument\Search\DropArguments;
|
||||
use Predis\Command\Argument\Search\ExplainArguments;
|
||||
use Predis\Command\Argument\Search\HybridSearch\HybridSearchQuery;
|
||||
use Predis\Command\Argument\Search\ProfileArguments;
|
||||
use Predis\Command\Argument\Search\SchemaFields\FieldInterface;
|
||||
use Predis\Command\Argument\Search\SearchArguments;
|
||||
@@ -41,12 +42,14 @@ use Predis\Command\CommandInterface;
|
||||
use Predis\Command\Container\ACL;
|
||||
use Predis\Command\Container\CLIENT;
|
||||
use Predis\Command\Container\FUNCTIONS;
|
||||
use Predis\Command\Container\HOTKEYS;
|
||||
use Predis\Command\Container\Json\JSONDEBUG;
|
||||
use Predis\Command\Container\Search\FTCONFIG;
|
||||
use Predis\Command\Container\Search\FTCURSOR;
|
||||
use Predis\Command\Container\XGROUP;
|
||||
use Predis\Command\Container\XINFO;
|
||||
use Predis\Command\FactoryInterface;
|
||||
use Predis\Command\Redis\VADD;
|
||||
use Predis\Configuration\OptionsInterface;
|
||||
use Predis\Connection\ConnectionInterface;
|
||||
use Predis\Response\Status;
|
||||
@@ -61,6 +64,8 @@ use Predis\Response\Status;
|
||||
*
|
||||
* @method int copy(string $source, string $destination, int $db = -1, bool $replace = false)
|
||||
* @method int del(string[]|string $keyOrKeys, string ...$keys = null)
|
||||
* @method int delex(string $key, string $flag, $flagValue)
|
||||
* @method string digest(string $key)
|
||||
* @method string|null dump(string $key)
|
||||
* @method int exists(string $key)
|
||||
* @method int expire(string $key, int $seconds, string $expireOption = '')
|
||||
@@ -135,6 +140,7 @@ use Predis\Response\Status;
|
||||
* @method array ftdictdump(string $dict)
|
||||
* @method Status ftdropindex(string $index, ?DropArguments $arguments = null)
|
||||
* @method string ftexplain(string $index, string $query, ?ExplainArguments $arguments = null)
|
||||
* @method array fthybrid(string $index, HybridSearchQuery $query)
|
||||
* @method array ftinfo(string $index)
|
||||
* @method array ftprofile(string $index, ProfileArguments $arguments)
|
||||
* @method array ftsearch(string $index, string $query, ?SearchArguments $arguments = null)
|
||||
@@ -157,9 +163,10 @@ use Predis\Response\Status;
|
||||
* @method string incrbyfloat(string $key, int|float $increment)
|
||||
* @method array mget(string[]|string $keyOrKeys, string ...$keys = null)
|
||||
* @method mixed mset(array $dictionary)
|
||||
* @method array msetex(array $dictionary, ?string $existModifier = null, ?string $expireResolution = null, ?int $expireTTL = null)
|
||||
* @method int msetnx(array $dictionary)
|
||||
* @method Status psetex(string $key, $milliseconds, $value)
|
||||
* @method Status|null set(string $key, $value, $expireResolution = null, $expireTTL = null, $flag = null)
|
||||
* @method Status|null set(string $key, $value, $expireResolution = null, $expireTTL = null, $flag = null, $flagValue = null)
|
||||
* @method int setbit(string $key, $offset, $value)
|
||||
* @method Status setex(string $key, $seconds, $value)
|
||||
* @method int setnx(string $key, $value)
|
||||
@@ -277,7 +284,7 @@ use Predis\Response\Status;
|
||||
* @method array topklist(string $key, bool $withCount = false)
|
||||
* @method array topkquery(string $key, ...$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 int tsadd(string $key, int $timestamp, string|float $value, ?AddArguments $arguments = null)
|
||||
* @method Status tsalter(string $key, ?TSAlterArguments $arguments = null)
|
||||
* @method Status tscreate(string $key, ?TSCreateArguments $arguments = null)
|
||||
* @method Status tscreaterule(string $sourceKey, string $destKey, string $aggregator, int $bucketDuration, int $alignTimestamp = 0)
|
||||
@@ -294,18 +301,26 @@ use Predis\Response\Status;
|
||||
* @method array tsqueryindex(string ...$filterExpression)
|
||||
* @method array tsrange(string $key, $fromTimestamp, $toTimestamp, ?RangeArguments $arguments = null)
|
||||
* @method array tsrevrange(string $key, $fromTimestamp, $toTimestamp, ?RangeArguments $arguments = null)
|
||||
* @method int xack(string $key, string $group, string ...$id)
|
||||
* @method array xackdel(string $key, string $group, string $mode, array $ids)
|
||||
* @method string xadd(string $key, array $dictionary, string $id = '*', array $options = null)
|
||||
* @method array xautoclaim(string $key, string $group, string $consumer, int $minIdleTime, string $start, ?int $count = null, bool $justId = false)
|
||||
* @method array xclaim(string $key, string $group, string $consumer, int $minIdleTime, string|array $ids, ?int $idle = null, ?int $time = null, ?int $retryCount = null, bool $force = false, bool $justId = false, ?string $lastId = null)
|
||||
* @method Status xcfgset(string $key, ?int $duration = null, ?int $maxsize = null)
|
||||
* @method int xdel(string $key, string ...$id)
|
||||
* @method array xdelex(string $key, string $mode, array $ids)
|
||||
* @method int xlen(string $key)
|
||||
* @method array xpending(string $key, string $group, ?int $minIdleTime = null, ?string $start = null, ?string $end = null, ?int $count = null, ?string $consumer = null)
|
||||
* @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 array|null xread(int $count = null, int $block = null, array $streams = null, string ...$id)
|
||||
* @method array xreadgroup(string $group, string $consumer, ?int $count = null, ?int $blockMs = null, bool $noAck = false, string ...$keyOrId)
|
||||
* @method array xreadgroup_claim(string $group, string $consumer, array $keyIdDict, ?int $count = null, ?int $blockMs = null, bool $noAck = false, ?int $claim = null)
|
||||
* @method Status xsetid(string $key, string $lastId, ?int $entriesAdded = null, ?string $maxDeleteId = null)
|
||||
* @method string xtrim(string $key, array|string $strategy, string $threshold, array $options = null)
|
||||
* @method int zadd(string $key, array $membersAndScoresDictionary)
|
||||
* @method int zcard(string $key)
|
||||
* @method string zcount(string $key, int|string $min, int|string $max)
|
||||
* @method int zcount(string $key, int|string $min, int|string $max)
|
||||
* @method array zdiff(array $keys, bool $withScores = false)
|
||||
* @method int zdiffstore(string $destination, array $keys)
|
||||
* @method string zincrby(string $key, int $increment, string $member)
|
||||
@@ -346,6 +361,18 @@ use Predis\Response\Status;
|
||||
* @method mixed multi()
|
||||
* @method mixed unwatch()
|
||||
* @method array unsubscribe(string ...$channels)
|
||||
* @method bool vadd(string $key, string|array $vector, string $elem, int $dim = null, bool $cas = false, string $quant = VADD::QUANT_DEFAULT, int $bef = null, string|array $attributes = null, int $numlinks = null)
|
||||
* @method int vcard(string $key)
|
||||
* @method int vdim(string $key)
|
||||
* @method array vemb(string $key, string $elem, bool $raw = false)
|
||||
* @method string|array|null vgetattr(string $key, string $elem, bool $asJson = false)
|
||||
* @method array|null vinfo(string $key)
|
||||
* @method array|null vlinks(string $key, string $elem, bool $withScores = false)
|
||||
* @method string|array|null vrandmember(string $key, int $count = null)
|
||||
* @method array vrange(string $key, string $start, string $end, int $count = null)
|
||||
* @method bool vrem(string $key, string $elem)
|
||||
* @method array vsim(string $key, string|array $vectorOrElem, bool $isElem = false, bool $withScores = false, int $count = null, float $epsilon = null, int $ef = null, string $filter = null, int $filterEf = null, bool $truth = false, bool $noThread = false)
|
||||
* @method bool vsetattr(string $key, string $elem, string|array $attributes)
|
||||
* @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)
|
||||
@@ -383,6 +410,7 @@ use Predis\Response\Status;
|
||||
*
|
||||
* Container commands
|
||||
* @property CLIENT $client
|
||||
* @property HOTKEYS $hotkeys
|
||||
* @property FUNCTIONS $function
|
||||
* @property FTCONFIG $ftconfig
|
||||
* @property FTCURSOR $ftcursor
|
||||
|
||||
@@ -155,6 +155,11 @@ abstract class ClusterStrategy implements StrategyInterface
|
||||
'HSCAN' => $getKeyFromFirstArgument,
|
||||
'HSTRLEN' => $getKeyFromFirstArgument,
|
||||
|
||||
/* commands operating on streams */
|
||||
'XADD' => $getKeyFromFirstArgument,
|
||||
'XDEL' => $getKeyFromFirstArgument,
|
||||
'XRANGE' => $getKeyFromFirstArgument,
|
||||
|
||||
/* commands operating on HyperLogLog */
|
||||
'PFADD' => $getKeyFromFirstArgument,
|
||||
'PFCOUNT' => $getKeyFromAllArguments,
|
||||
@@ -184,6 +189,9 @@ abstract class ClusterStrategy implements StrategyInterface
|
||||
|
||||
/* cluster */
|
||||
'CLUSTER' => [$this, 'getFakeKey'],
|
||||
|
||||
/* control */
|
||||
'ACL' => [$this, 'getFakeKey'],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<?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\Command\Argument\Search\HybridSearch\Combine;
|
||||
|
||||
use Predis\Command\Argument\ArrayableArgument;
|
||||
|
||||
abstract class BaseCombine implements ArrayableArgument
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $arguments = ['COMBINE'];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $as = [];
|
||||
|
||||
/**
|
||||
* @param string $alias
|
||||
* @return $this
|
||||
*/
|
||||
public function as(string $alias): self
|
||||
{
|
||||
array_push($this->as, 'YIELD_SCORE_AS', $alias);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
abstract public function toArray(): array;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?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\Command\Argument\Search\HybridSearch\Combine;
|
||||
|
||||
class LinearCombineConfig extends BaseCombine
|
||||
{
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
protected $alpha;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
protected $beta;
|
||||
|
||||
/**
|
||||
* The weight for the text score (a value between 0 and 1).
|
||||
*
|
||||
* @param float $alpha
|
||||
* @return $this
|
||||
*/
|
||||
public function alpha(float $alpha): self
|
||||
{
|
||||
$this->alpha = $alpha;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The weight for the vector score (a value between 0 and 1).
|
||||
*
|
||||
* @param float $beta
|
||||
* @return $this
|
||||
*/
|
||||
public function beta(float $beta): self
|
||||
{
|
||||
$this->beta = $beta;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
$this->arguments[] = 'LINEAR';
|
||||
$tokens = [];
|
||||
|
||||
if ($this->alpha !== null) {
|
||||
array_push($tokens, 'ALPHA', $this->alpha);
|
||||
}
|
||||
|
||||
if ($this->beta !== null) {
|
||||
array_push($tokens, 'BETA', $this->beta);
|
||||
}
|
||||
|
||||
if ($this->as) {
|
||||
array_push($tokens, ...$this->as);
|
||||
}
|
||||
|
||||
if (!empty($tokens)) {
|
||||
array_push($this->arguments, count($tokens), ...$tokens);
|
||||
}
|
||||
|
||||
return $this->arguments;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?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\Command\Argument\Search\HybridSearch\Combine;
|
||||
|
||||
class RRFCombineConfig extends BaseCombine
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $window;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $rrfConstant;
|
||||
|
||||
/**
|
||||
* The number of top results from each search type to consider for fusion. Defaults to 50.
|
||||
*
|
||||
* @param int $window
|
||||
* @return $this
|
||||
*/
|
||||
public function window(int $window): self
|
||||
{
|
||||
$this->window = $window;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The RRF ranking constant. A smaller value gives more weight to top-ranked items. Defaults to 60.
|
||||
*
|
||||
* @param int $constant
|
||||
* @return $this
|
||||
*/
|
||||
public function rrfConstant(int $constant): self
|
||||
{
|
||||
$this->rrfConstant = $constant;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
$this->arguments[] = 'RRF';
|
||||
$tokens = [];
|
||||
|
||||
if ($this->window !== null) {
|
||||
array_push($tokens, 'WINDOW', $this->window);
|
||||
}
|
||||
|
||||
if ($this->rrfConstant !== null) {
|
||||
array_push($tokens, 'CONSTANT', $this->rrfConstant);
|
||||
}
|
||||
|
||||
if ($this->as) {
|
||||
array_push($tokens, ...$this->as);
|
||||
}
|
||||
|
||||
if (!empty($tokens)) {
|
||||
array_push($this->arguments, count($tokens), ...$tokens);
|
||||
}
|
||||
|
||||
return $this->arguments;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,352 @@
|
||||
<?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\Command\Argument\Search\HybridSearch;
|
||||
|
||||
use Predis\Command\Argument\ArrayableArgument;
|
||||
use Predis\Command\Argument\Search\HybridSearch\Combine\LinearCombineConfig;
|
||||
use Predis\Command\Argument\Search\HybridSearch\Combine\RRFCombineConfig;
|
||||
use Predis\Command\Argument\Search\HybridSearch\VectorSearch\KNNVectorSearchConfig;
|
||||
use Predis\Command\Argument\Search\HybridSearch\VectorSearch\RangeVectorSearchConfig;
|
||||
use Predis\Command\Redis\Utils\CommandUtility;
|
||||
use ValueError;
|
||||
|
||||
class HybridSearchQuery implements ArrayableArgument
|
||||
{
|
||||
public const SORT_ASC = 'ASC';
|
||||
public const SORT_DESC = 'DESC';
|
||||
|
||||
/**
|
||||
* @var SearchConfig
|
||||
*/
|
||||
protected $searchConfig;
|
||||
|
||||
/**
|
||||
* The vector search portion of the query.
|
||||
*
|
||||
* @var KNNVectorSearchConfig|RangeVectorSearchConfig
|
||||
*/
|
||||
protected $vectorSearchConfig;
|
||||
|
||||
/**
|
||||
* Configuration for the score fusion method (optional).
|
||||
* If not provided, Reciprocal Rank Fusion (RRF) is used with server-side default parameters.
|
||||
*
|
||||
* @var RRFCombineConfig|LinearCombineConfig
|
||||
*/
|
||||
protected $combineConfig;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $load = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $groupBy = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $apply = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $sortBy = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $filter;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $limit = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $params = [];
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $explainScore = false;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $timeout = false;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $withCursor = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $arguments = [];
|
||||
|
||||
/**
|
||||
* @param string $vectorSearchMethod Class type of desired vector search method
|
||||
* @param string $combineMethod Class type of desired combine method
|
||||
*/
|
||||
public function __construct(
|
||||
string $vectorSearchMethod = KNNVectorSearchConfig::class,
|
||||
string $combineMethod = RRFCombineConfig::class
|
||||
) {
|
||||
$this->searchConfig = new SearchConfig();
|
||||
$this->vectorSearchConfig = new $vectorSearchMethod();
|
||||
$this->combineConfig = new $combineMethod();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable(SearchConfig): void $callable
|
||||
* @return $this
|
||||
*/
|
||||
public function buildSearchConfig(callable $callable): self
|
||||
{
|
||||
$callable($this->searchConfig);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable(KNNVectorSearchConfig|RangeVectorSearchConfig): void $callable
|
||||
* @return $this
|
||||
*/
|
||||
public function buildVectorSearchConfig(callable $callable): self
|
||||
{
|
||||
$callable($this->vectorSearchConfig);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable(RRFCombineConfig|LinearCombineConfig): void $callable
|
||||
* @return $this
|
||||
*/
|
||||
public function buildCombineConfig(callable $callable): self
|
||||
{
|
||||
$callable($this->combineConfig);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The list of fields to return in the results.
|
||||
*
|
||||
* @param array $fields
|
||||
* @return $this
|
||||
*/
|
||||
public function load(array $fields): self
|
||||
{
|
||||
array_push($this->load, 'LOAD', count($fields), ...$fields);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $fields
|
||||
* @param Reducer[] $reducers
|
||||
* @return $this
|
||||
*/
|
||||
public function groupBy(array $fields, array $reducers): self
|
||||
{
|
||||
array_push($this->groupBy, 'GROUPBY', count($fields), ...$fields);
|
||||
|
||||
foreach ($reducers as $reducer) {
|
||||
array_push($this->groupBy, 'REDUCE', ...$reducer->toArray());
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $expressionFieldDict field => function dictionary
|
||||
* @return $this
|
||||
*/
|
||||
public function apply(array $expressionFieldDict): self
|
||||
{
|
||||
foreach ($expressionFieldDict as $field => $function) {
|
||||
array_push($this->apply, 'APPLY', $function, 'AS', $field);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the final results by a specific field.
|
||||
*
|
||||
* @param array<string, string> $fields Dictionary with fields and sort direction. Check class constants.
|
||||
* @return $this
|
||||
*/
|
||||
public function sortBy(array $fields): self
|
||||
{
|
||||
$fieldsArray = [];
|
||||
foreach ($fields as $field => $direction) {
|
||||
if (!in_array(strtoupper($direction), [self::SORT_ASC, self::SORT_DESC])) {
|
||||
throw new ValueError('Sort direction must be one of "ASC" or "DESC".');
|
||||
}
|
||||
|
||||
array_push($fieldsArray, $field, $direction);
|
||||
}
|
||||
|
||||
array_push($this->sortBy, 'SORTBY', count($fieldsArray), ...$fieldsArray);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Final result filtering.
|
||||
*
|
||||
* @param string $expression
|
||||
* @return $this
|
||||
*/
|
||||
public function filter(string $expression): self
|
||||
{
|
||||
$this->filter = $expression;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $offset
|
||||
* @param int $num
|
||||
* @return $this
|
||||
*/
|
||||
public function limit(int $offset, int $num): self
|
||||
{
|
||||
array_push($this->limit, 'LIMIT', $offset, $num);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds values to named parameters in the query string.
|
||||
*
|
||||
* @param array $params
|
||||
* @return $this
|
||||
*/
|
||||
public function params(array $params): self
|
||||
{
|
||||
$arrayParams = CommandUtility::dictionaryToArray($params);
|
||||
array_push($this->params, 'PARAMS', count($arrayParams), ...$arrayParams);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function explainScore(): self
|
||||
{
|
||||
$this->explainScore = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function timeout(): self
|
||||
{
|
||||
$this->timeout = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $readSize
|
||||
* @param int|null $idleTime
|
||||
* @return $this
|
||||
*/
|
||||
public function withCursor(?int $readSize = null, ?int $idleTime = null): self
|
||||
{
|
||||
$this->withCursor[] = 'WITHCURSOR';
|
||||
|
||||
if ($readSize) {
|
||||
array_push($this->withCursor, 'COUNT', $readSize);
|
||||
}
|
||||
|
||||
if ($idleTime) {
|
||||
array_push($this->withCursor, 'MAXIDLE', $idleTime);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
$this->arguments = array_merge(
|
||||
$this->arguments,
|
||||
$this->searchConfig->toArray(),
|
||||
$this->vectorSearchConfig->toArray()
|
||||
);
|
||||
|
||||
$combineConfig = $this->combineConfig->toArray();
|
||||
|
||||
// Only add if any configuration was applied
|
||||
if (count($combineConfig) > 2) {
|
||||
$this->arguments = array_merge($this->arguments, $combineConfig);
|
||||
}
|
||||
|
||||
if ($this->load) {
|
||||
$this->arguments = array_merge($this->arguments, $this->load);
|
||||
}
|
||||
|
||||
if ($this->groupBy) {
|
||||
$this->arguments = array_merge($this->arguments, $this->groupBy);
|
||||
}
|
||||
|
||||
if ($this->apply) {
|
||||
$this->arguments = array_merge($this->arguments, $this->apply);
|
||||
}
|
||||
|
||||
if ($this->sortBy) {
|
||||
$this->arguments = array_merge($this->arguments, $this->sortBy);
|
||||
}
|
||||
|
||||
if ($this->filter) {
|
||||
array_push($this->arguments, 'FILTER', $this->filter);
|
||||
}
|
||||
|
||||
if ($this->limit) {
|
||||
$this->arguments = array_merge($this->arguments, $this->limit);
|
||||
}
|
||||
|
||||
if ($this->params) {
|
||||
$this->arguments = array_merge($this->arguments, $this->params);
|
||||
}
|
||||
|
||||
if ($this->explainScore) {
|
||||
$this->arguments[] = 'EXPLAINSCORE';
|
||||
}
|
||||
|
||||
if ($this->timeout) {
|
||||
$this->arguments[] = 'TIMEOUT';
|
||||
}
|
||||
|
||||
if ($this->withCursor) {
|
||||
$this->arguments = array_merge($this->arguments, $this->withCursor);
|
||||
}
|
||||
|
||||
return $this->arguments;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?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\Command\Argument\Search\HybridSearch;
|
||||
|
||||
use Predis\Command\Argument\ArrayableArgument;
|
||||
|
||||
class Reducer implements ArrayableArgument
|
||||
{
|
||||
public const REDUCE_COUNT = 'COUNT';
|
||||
public const REDUCE_COUNT_DISTINCT = 'COUNT_DISTINCT';
|
||||
public const REDUCE_COUNT_DISTINCTISH = 'COUNT_DISTINCTISH';
|
||||
public const REDUCE_SUM = 'SUM';
|
||||
public const REDUCE_MIN = 'MIN';
|
||||
public const REDUCE_MAX = 'MAX';
|
||||
public const REDUCE_AVG = 'AVG';
|
||||
public const REDUCE_STDDEV = 'STDDEV';
|
||||
public const REDUCE_QUANTILE = 'QUANTILE';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $arguments = [];
|
||||
|
||||
/**
|
||||
* @param string $function One of the available functions. Check class constants.
|
||||
* @param array $arguments List of properties
|
||||
*/
|
||||
public function __construct(string $function = self::REDUCE_COUNT, array $arguments = [], ?string $alias = null)
|
||||
{
|
||||
array_push($this->arguments, $function, count($arguments), ...$arguments);
|
||||
|
||||
if ($alias) {
|
||||
array_push($this->arguments, 'AS', $alias);
|
||||
}
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
return $this->arguments;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?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\Command\Argument\Search\HybridSearch;
|
||||
|
||||
use Predis\Command\Argument\ArrayableArgument;
|
||||
|
||||
class ScorerConfig implements ArrayableArgument
|
||||
{
|
||||
public const TYPE_BM25 = 'BM25';
|
||||
public const TYPE_TFIDF = 'TFIDF';
|
||||
public const TYPE_DISMAX = 'DISMAX';
|
||||
public const TYPE_DOCSCORE = 'DOCSCORE';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $arguments = [];
|
||||
|
||||
/**
|
||||
* The text scoring algorithm. Defaults to BM25.
|
||||
*
|
||||
* @param string $type
|
||||
* @return $this
|
||||
*/
|
||||
public function type(string $type = self::TYPE_BM25): self
|
||||
{
|
||||
$this->arguments[] = $type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* An alias for the text score field in the results.
|
||||
* The aliased field will be included in the `value` object of each returned document.
|
||||
*
|
||||
* @param string $alias
|
||||
* @return $this
|
||||
*/
|
||||
public function as(string $alias): self
|
||||
{
|
||||
array_push($this->arguments, 'YIELD_SCORE_AS', $alias);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
return $this->arguments;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<?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\Command\Argument\Search\HybridSearch;
|
||||
|
||||
use Predis\Command\Argument\ArrayableArgument;
|
||||
|
||||
class SearchConfig implements ArrayableArgument
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $arguments = ['SEARCH'];
|
||||
|
||||
/**
|
||||
* @var ScorerConfig
|
||||
*/
|
||||
protected $scorerConfig;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->scorerConfig = new ScorerConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Search query.
|
||||
*
|
||||
* @param string $query
|
||||
* @return $this
|
||||
*/
|
||||
public function query(string $query): self
|
||||
{
|
||||
$this->arguments[] = $query;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $alias
|
||||
* @return $this
|
||||
*/
|
||||
public function as(string $alias): self
|
||||
{
|
||||
array_push($this->arguments, 'YIELD_SCORE_AS', $alias);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable(ScorerConfig): void $callable
|
||||
* @return $this
|
||||
*/
|
||||
public function buildScorerConfig(callable $callable): self
|
||||
{
|
||||
$callable($this->scorerConfig);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
$scorerConfig = $this->scorerConfig->toArray();
|
||||
|
||||
if (!empty($scorerConfig)) {
|
||||
$this->arguments[] = 'SCORER';
|
||||
$this->arguments = array_merge($this->arguments, $scorerConfig);
|
||||
}
|
||||
|
||||
return $this->arguments;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<?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\Command\Argument\Search\HybridSearch\VectorSearch;
|
||||
|
||||
use Predis\Command\Argument\ArrayableArgument;
|
||||
|
||||
abstract class BaseVectorSearchConfig implements ArrayableArgument
|
||||
{
|
||||
public const POLICY_ADHOC = 'ADHOC';
|
||||
public const POLICY_BATCHES = 'BATCHES';
|
||||
public const POLICY_ACORN = 'ACORN';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $vector = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $filter = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $as = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $arguments = ['VSIM'];
|
||||
|
||||
/**
|
||||
* Vector to perform search against.
|
||||
*
|
||||
* @param string $field The vector field name to search against. Must start with "@".
|
||||
* @param string $value Name of the parameter to use in the query. Must start with "$".
|
||||
* @return self
|
||||
*/
|
||||
public function vector(string $field, string $value): self
|
||||
{
|
||||
array_push($this->vector, $field, $value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $expression
|
||||
* @return $this
|
||||
*/
|
||||
public function filter(string $expression): self
|
||||
{
|
||||
array_push($this->filter, 'FILTER', $expression);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $alias
|
||||
* @return $this
|
||||
*/
|
||||
public function as(string $alias): self
|
||||
{
|
||||
array_push($this->as, 'YIELD_SCORE_AS', $alias);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
abstract public function toArray(): array;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?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\Command\Argument\Search\HybridSearch\VectorSearch;
|
||||
|
||||
use ValueError;
|
||||
|
||||
class KNNVectorSearchConfig extends BaseVectorSearchConfig
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $k;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $ef;
|
||||
|
||||
/**
|
||||
* The number of nearest neighbors to find. Defaults to 10 on server side.
|
||||
*
|
||||
* @param int $k
|
||||
* @return self
|
||||
*/
|
||||
public function k(int $k): self
|
||||
{
|
||||
$this->k = $k;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The HNSW `ef_runtime` parameter for tuning the accuracy/speed trade-off.
|
||||
*
|
||||
* @param int $ef
|
||||
* @return $this
|
||||
*/
|
||||
public function ef(int $ef): self
|
||||
{
|
||||
$this->ef = $ef;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
if (!$this->vector) {
|
||||
throw new ValueError('Vector configuration not specified.');
|
||||
}
|
||||
|
||||
$this->arguments = array_merge($this->arguments, $this->vector);
|
||||
|
||||
if ($this->k || $this->ef) {
|
||||
$this->arguments[] = 'KNN';
|
||||
}
|
||||
|
||||
$tokens = [];
|
||||
|
||||
if ($this->k !== null) {
|
||||
array_push($tokens, 'K', $this->k);
|
||||
}
|
||||
|
||||
if ($this->ef !== null) {
|
||||
array_push($tokens, 'EF_RUNTIME', $this->ef);
|
||||
}
|
||||
|
||||
if (!empty($tokens)) {
|
||||
array_push($this->arguments, count($tokens), ...$tokens);
|
||||
}
|
||||
|
||||
if ($this->filter) {
|
||||
$this->arguments = array_merge($this->arguments, $this->filter);
|
||||
}
|
||||
|
||||
if ($this->as) {
|
||||
array_push($this->arguments, ...$this->as);
|
||||
}
|
||||
|
||||
return $this->arguments;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?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\Command\Argument\Search\HybridSearch\VectorSearch;
|
||||
|
||||
use ValueError;
|
||||
|
||||
class RangeVectorSearchConfig extends BaseVectorSearchConfig
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $radius;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
protected $epsilon;
|
||||
|
||||
/**
|
||||
* The search radius/threshold. Finds all vectors within this distance.
|
||||
*
|
||||
* @param int $radius
|
||||
* @return $this
|
||||
*/
|
||||
public function radius(int $radius): self
|
||||
{
|
||||
$this->radius = $radius;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $epsilon
|
||||
* @return $this
|
||||
*/
|
||||
public function epsilon(float $epsilon): self
|
||||
{
|
||||
$this->epsilon = $epsilon;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
if (!$this->vector) {
|
||||
throw new ValueError('Vector configuration not specified.');
|
||||
}
|
||||
|
||||
$this->arguments = array_merge($this->arguments, $this->vector);
|
||||
|
||||
if ($this->radius || $this->epsilon) {
|
||||
$this->arguments[] = 'RANGE';
|
||||
}
|
||||
|
||||
$tokens = [];
|
||||
|
||||
if ($this->radius !== null) {
|
||||
array_push($tokens, 'RADIUS', $this->radius);
|
||||
}
|
||||
|
||||
if ($this->epsilon !== null) {
|
||||
array_push($tokens, 'EPSILON', $this->epsilon);
|
||||
}
|
||||
|
||||
if (!empty($tokens)) {
|
||||
array_push($this->arguments, count($tokens), ...$tokens);
|
||||
}
|
||||
|
||||
if ($this->filter) {
|
||||
$this->arguments = array_merge($this->arguments, $this->filter);
|
||||
}
|
||||
|
||||
if ($this->as) {
|
||||
array_push($this->arguments, ...$this->as);
|
||||
}
|
||||
|
||||
return $this->arguments;
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,13 @@ namespace Predis\Command\Argument\TimeSeries;
|
||||
|
||||
class RangeArguments extends CommonArguments
|
||||
{
|
||||
public const AGG_SUM = 'sum';
|
||||
public const AGG_MIN = 'min';
|
||||
public const AGG_MAX = 'max';
|
||||
public const AGG_COUNT = 'count';
|
||||
public const AGG_COUNT_NAN = 'countNan';
|
||||
public const AGG_COUNT_ALL = 'countAll';
|
||||
|
||||
/**
|
||||
* Filters samples by a list of specific timestamps.
|
||||
*
|
||||
@@ -57,7 +64,7 @@ class RangeArguments extends CommonArguments
|
||||
/**
|
||||
* Aggregates samples into time buckets.
|
||||
*
|
||||
* @param string $aggregator
|
||||
* @param string $aggregator Aggregation type. Check class constants.
|
||||
* @param int $bucketDuration Is duration of each bucket, in milliseconds.
|
||||
* @param int $align It controls the time bucket timestamps by changing the reference timestamp on which a bucket is defined.
|
||||
* @param int $bucketTimestamp Controls how bucket timestamps are reported.
|
||||
|
||||
@@ -17,8 +17,10 @@ use Predis\Response\Status;
|
||||
/**
|
||||
* @method array cat(string $category = null)
|
||||
* @method Status dryRun(string $username, string $command, ...$arguments)
|
||||
* @method int delUser(string ...$username)
|
||||
* @method array getUser(string $username)
|
||||
* @method Status setUser(string $username, string ...$rules)
|
||||
* @method string whoami()
|
||||
*/
|
||||
class ACL extends AbstractContainer
|
||||
{
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
<?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\Command\Container;
|
||||
|
||||
use Predis\Response\Status;
|
||||
|
||||
/**
|
||||
* @method Status stop()
|
||||
* @method Status reset()
|
||||
* @method array get()
|
||||
*/
|
||||
class HOTKEYS extends AbstractContainer
|
||||
{
|
||||
public const CPU = 'CPU';
|
||||
public const NET = 'NET';
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getContainerCommandId(): string
|
||||
{
|
||||
return 'HOTKEYS';
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a hotkeys tracking on server side.
|
||||
*
|
||||
* @param array<self::CPU|self::NET> $metrics One of the available metric types. Check class constants.
|
||||
* @param int|null $count Number of top keys to report. Default: 10, Min: 10, Max: 64
|
||||
* @param int|null $duration Auto-stop tracking after this many seconds. Default: 0 (no auto-stop)
|
||||
* @param int|null $sample Sample ratio - track keys with probability 1/sample. Default: 1 (track every key), Min: 1
|
||||
* @param array<int>|null $slots All specified slots must be hosted by the receiving node! If not specified, all slots are tracked.
|
||||
* @return string|Status
|
||||
*/
|
||||
public function start(array $metrics, ?int $count = null, ?int $duration = null, ?int $sample = null, ?array $slots = null)
|
||||
{
|
||||
return $this->__call('START', func_get_args());
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ abstract class PrefixableCommand extends Command implements PrefixableCommandInt
|
||||
*/
|
||||
public function applyPrefixForAllArguments(string $prefix): void
|
||||
{
|
||||
$this->setArguments(
|
||||
$this->setRawArguments(
|
||||
array_map(static function ($key) use ($prefix) {
|
||||
return $prefix . $key;
|
||||
}, $this->getArguments())
|
||||
@@ -49,7 +49,7 @@ abstract class PrefixableCommand extends Command implements PrefixableCommandInt
|
||||
{
|
||||
$arguments = $this->getArguments();
|
||||
$arguments[0] = $prefix . $arguments[0];
|
||||
$this->setArguments($arguments);
|
||||
$this->setRawArguments($arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
@@ -19,6 +20,8 @@ use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
*/
|
||||
class BITOP extends RedisCommand
|
||||
{
|
||||
private const VALID_OPERATIONS = ['AND', 'OR', 'XOR', 'NOT', 'DIFF', 'DIFF1', 'ANDOR', 'ONE'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -38,6 +41,13 @@ class BITOP extends RedisCommand
|
||||
array_unshift($arguments, $operation, $destination);
|
||||
}
|
||||
|
||||
if (!empty($arguments)) {
|
||||
$operation = strtoupper($arguments[0]);
|
||||
if (!in_array($operation, self::VALID_OPERATIONS, false)) {
|
||||
throw new InvalidArgumentException('BITOP operation must be one of: AND, OR, XOR, NOT, DIFF, DIFF1, ANDOR, ONE');
|
||||
}
|
||||
}
|
||||
|
||||
parent::setArguments($arguments);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\BloomFilter;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/bf.add/
|
||||
@@ -26,4 +26,9 @@ class BFADD extends RedisCommand
|
||||
{
|
||||
return 'BF.ADD';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\BloomFilter;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/bf.exists/
|
||||
@@ -25,4 +25,9 @@ class BFEXISTS extends RedisCommand
|
||||
{
|
||||
return 'BF.EXISTS';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\BloomFilter;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
use UnexpectedValueException;
|
||||
|
||||
/**
|
||||
@@ -76,4 +76,9 @@ class BFINFO extends RedisCommand
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\BloomFilter;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
use Predis\Command\Traits\BloomFilters\Capacity;
|
||||
use Predis\Command\Traits\BloomFilters\Error;
|
||||
use Predis\Command\Traits\BloomFilters\Expansion;
|
||||
@@ -48,6 +48,11 @@ class BFINSERT extends RedisCommand
|
||||
return 'BF.INSERT';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
$this->setNoCreate($arguments);
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\BloomFilter;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/bf.loadchunk/
|
||||
@@ -25,4 +25,9 @@ class BFLOADCHUNK extends RedisCommand
|
||||
{
|
||||
return 'BF.LOADCHUNK';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\BloomFilter;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/bf.madd/
|
||||
@@ -26,4 +26,9 @@ class BFMADD extends RedisCommand
|
||||
{
|
||||
return 'BF.MADD';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\BloomFilter;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/bf.mexists/
|
||||
@@ -25,4 +25,9 @@ class BFMEXISTS extends RedisCommand
|
||||
{
|
||||
return 'BF.MEXISTS';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\BloomFilter;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
use Predis\Command\Traits\BloomFilters\Expansion;
|
||||
|
||||
/**
|
||||
@@ -46,4 +46,9 @@ class BFRESERVE extends RedisCommand
|
||||
$this->setExpansion($arguments);
|
||||
$this->filterArguments();
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\BloomFilter;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/bf.scandump/
|
||||
@@ -26,4 +26,9 @@ class BFSCANDUMP extends RedisCommand
|
||||
{
|
||||
return 'BF.SCANDUMP';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,9 +32,23 @@ class COMMAND extends BaseCommand
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
// Relay (RESP3) uses maps and it might be good
|
||||
// to make the return value a breaking change
|
||||
if (!is_array($data)) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
return $data;
|
||||
if ($data === array_values($data)) {
|
||||
return array_map(function ($item) {
|
||||
return $this->parseResponse($item);
|
||||
}, $data);
|
||||
}
|
||||
|
||||
// Relay
|
||||
$result = [];
|
||||
foreach ($data as $key => $value) {
|
||||
$result[] = $key;
|
||||
$result[] = $this->parseResponse($value);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\CountMinSketch;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/cms.incrby/
|
||||
@@ -26,4 +26,9 @@ class CMSINCRBY extends RedisCommand
|
||||
{
|
||||
return 'CMS.INCRBY';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\CountMinSketch;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/cms.info/
|
||||
@@ -42,4 +42,9 @@ class CMSINFO extends RedisCommand
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\CountMinSketch;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/cms.initbydim/
|
||||
@@ -25,4 +25,9 @@ class CMSINITBYDIM extends RedisCommand
|
||||
{
|
||||
return 'CMS.INITBYDIM';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\CountMinSketch;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/cms.initbyprob/
|
||||
@@ -25,4 +25,9 @@ class CMSINITBYPROB extends RedisCommand
|
||||
{
|
||||
return 'CMS.INITBYPROB';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\CountMinSketch;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/cms.merge/
|
||||
@@ -39,4 +39,17 @@ class CMSMERGE extends RedisCommand
|
||||
|
||||
parent::setArguments($processedArguments);
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
if ($arguments = $this->getArguments()) {
|
||||
$arguments[0] = $prefix . $arguments[0];
|
||||
|
||||
for ($i = 2, $iMax = (int) $arguments[1] + 2; $i < $iMax; $i++) {
|
||||
$arguments[$i] = $prefix . $arguments[$i];
|
||||
}
|
||||
|
||||
$this->setRawArguments($arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\CountMinSketch;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/cms.query/
|
||||
@@ -25,4 +25,9 @@ class CMSQUERY extends RedisCommand
|
||||
{
|
||||
return 'CMS.QUERY';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\CuckooFilter;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/cf.add/
|
||||
@@ -25,4 +25,9 @@ class CFADD extends RedisCommand
|
||||
{
|
||||
return 'CF.ADD';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\CuckooFilter;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/cf.addnx/
|
||||
@@ -25,4 +25,9 @@ class CFADDNX extends RedisCommand
|
||||
{
|
||||
return 'CF.ADDNX';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\CuckooFilter;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/cf.count/
|
||||
@@ -26,4 +26,9 @@ class CFCOUNT extends RedisCommand
|
||||
{
|
||||
return 'CF.COUNT';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\CuckooFilter;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/cf.del/
|
||||
@@ -27,4 +27,9 @@ class CFDEL extends RedisCommand
|
||||
{
|
||||
return 'CF.DEL';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\CuckooFilter;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/cf.exists/
|
||||
@@ -25,4 +25,9 @@ class CFEXISTS extends RedisCommand
|
||||
{
|
||||
return 'CF.EXISTS';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\CuckooFilter;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/cf.info/
|
||||
@@ -42,4 +42,9 @@ class CFINFO extends RedisCommand
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\CuckooFilter;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
use Predis\Command\Traits\BloomFilters\Capacity;
|
||||
use Predis\Command\Traits\BloomFilters\Items;
|
||||
use Predis\Command\Traits\BloomFilters\NoCreate;
|
||||
@@ -49,4 +49,9 @@ class CFINSERT extends RedisCommand
|
||||
$this->setCapacity($arguments);
|
||||
$this->filterArguments();
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\CuckooFilter;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/cf.loadchunk/
|
||||
@@ -26,4 +26,9 @@ class CFLOADCHUNK extends RedisCommand
|
||||
{
|
||||
return 'CF.LOADCHUNK';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\CuckooFilter;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/cf.mexists/
|
||||
@@ -25,4 +25,9 @@ class CFMEXISTS extends RedisCommand
|
||||
{
|
||||
return 'CF.MEXISTS';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\CuckooFilter;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
use Predis\Command\Traits\BloomFilters\BucketSize;
|
||||
use Predis\Command\Traits\BloomFilters\Expansion;
|
||||
use Predis\Command\Traits\BloomFilters\MaxIterations;
|
||||
@@ -49,4 +49,9 @@ class CFRESERVE extends RedisCommand
|
||||
$this->setBucketSize($arguments);
|
||||
$this->filterArguments();
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\CuckooFilter;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/cf.scandump/
|
||||
@@ -26,4 +26,9 @@ class CFSCANDUMP extends RedisCommand
|
||||
{
|
||||
return 'CF.SCANDUMP';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<?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\Command\Redis;
|
||||
|
||||
use Predis\Command\PrefixableCommand;
|
||||
|
||||
class DELEX extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'DELEX';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?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\Command\Redis;
|
||||
|
||||
use Predis\Command\PrefixableCommand;
|
||||
|
||||
class DIGEST extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'DIGEST';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/expiretime/
|
||||
@@ -26,4 +26,9 @@ class EXPIRETIME extends RedisCommand
|
||||
{
|
||||
return 'EXPIRETIME';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,4 +127,26 @@ class FUNCTIONS extends RedisCommand
|
||||
|
||||
parent::setArguments($processedArguments);
|
||||
}
|
||||
|
||||
public function parseResponse($data)
|
||||
{
|
||||
if (!is_array($data)) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
if ($data === array_values($data)) {
|
||||
return array_map(function ($item) {
|
||||
return $this->parseResponse($item);
|
||||
}, $data);
|
||||
}
|
||||
|
||||
// Relay
|
||||
$result = [];
|
||||
foreach ($data as $key => $value) {
|
||||
$result[] = $key;
|
||||
$result[] = $this->parseResponse($value);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
use Predis\Command\Traits\By\GeoBy;
|
||||
use Predis\Command\Traits\Count;
|
||||
use Predis\Command\Traits\From\GeoFrom;
|
||||
@@ -119,4 +119,9 @@ class GEOSEARCH extends RedisCommand
|
||||
|
||||
return $parsedData;
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
class GETDEL extends RedisCommand
|
||||
{
|
||||
@@ -20,4 +20,9 @@ class GETDEL extends RedisCommand
|
||||
{
|
||||
return 'GETDEL';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
use UnexpectedValueException;
|
||||
|
||||
class HEXPIRE extends RedisCommand
|
||||
@@ -48,4 +48,9 @@ class HEXPIRE extends RedisCommand
|
||||
|
||||
parent::setArguments($processedArguments);
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
class HEXPIRETIME extends RedisCommand
|
||||
{
|
||||
@@ -28,4 +28,9 @@ class HEXPIRETIME extends RedisCommand
|
||||
|
||||
parent::setArguments($processedArguments);
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
<?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\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\Redis\Utils\CommandUtility;
|
||||
use ValueError;
|
||||
|
||||
class HOTKEYS extends RedisCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HOTKEYS';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $arguments
|
||||
* @return void
|
||||
*/
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
switch ($arguments[0]) {
|
||||
case 'START':
|
||||
$this->setStartArguments($arguments);
|
||||
break;
|
||||
|
||||
default:
|
||||
parent::setArguments($arguments);
|
||||
}
|
||||
}
|
||||
|
||||
public function parseResponse($data)
|
||||
{
|
||||
if (is_array($data)) {
|
||||
foreach ($data as $key => $item) {
|
||||
$dict = CommandUtility::arrayToDictionary($item, null, false);
|
||||
$data[$key] = $dict;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $arguments
|
||||
* @return void
|
||||
*/
|
||||
private function setStartArguments(array $arguments)
|
||||
{
|
||||
$processedArguments = [$arguments[0]];
|
||||
|
||||
array_push($processedArguments, 'METRICS', count($arguments[1]), ...$arguments[1]);
|
||||
|
||||
if (isset($arguments[2])) {
|
||||
if ($arguments[2] > 9 && $arguments[2] < 65) {
|
||||
array_push($processedArguments, 'COUNT', $arguments[2]);
|
||||
} else {
|
||||
throw new ValueError('Count value should be between 10 and 64');
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($arguments[3])) {
|
||||
array_push($processedArguments, 'DURATION', $arguments[3]);
|
||||
}
|
||||
|
||||
if (isset($arguments[4])) {
|
||||
if ($arguments[4] > 0) {
|
||||
array_push($processedArguments, 'SAMPLE', $arguments[4]);
|
||||
} else {
|
||||
throw new ValueError('Sample value should be greater than 0');
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($arguments[5])) {
|
||||
array_push($processedArguments, 'SLOTS', count($arguments[5]), ...$arguments[5]);
|
||||
}
|
||||
|
||||
parent::setArguments($processedArguments);
|
||||
}
|
||||
}
|
||||
@@ -38,9 +38,9 @@ class INFO extends RedisCommand
|
||||
|
||||
if (strpos($lines[0], '#') === 0) {
|
||||
return $this->parseNewResponseFormat($lines);
|
||||
} else {
|
||||
return $this->parseOldResponseFormat($lines);
|
||||
}
|
||||
|
||||
return $this->parseOldResponseFormat($lines);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/json.arrappend/
|
||||
@@ -25,4 +25,9 @@ class JSONARRAPPEND extends RedisCommand
|
||||
{
|
||||
return 'JSON.ARRAPPEND';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/json.arrindex/
|
||||
@@ -25,4 +25,9 @@ class JSONARRINDEX extends RedisCommand
|
||||
{
|
||||
return 'JSON.ARRINDEX';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/json.arrinsert/
|
||||
@@ -25,4 +25,9 @@ class JSONARRINSERT extends RedisCommand
|
||||
{
|
||||
return 'JSON.ARRINSERT';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/json.arrlen/
|
||||
@@ -25,4 +25,9 @@ class JSONARRLEN extends RedisCommand
|
||||
{
|
||||
return 'JSON.ARRLEN';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/json.arrpop/
|
||||
@@ -25,4 +25,9 @@ class JSONARRPOP extends RedisCommand
|
||||
{
|
||||
return 'JSON.ARRPOP';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/json.arrtrim/
|
||||
@@ -25,4 +25,9 @@ class JSONARRTRIM extends RedisCommand
|
||||
{
|
||||
return 'JSON.ARRTRIM';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/json.clear/
|
||||
@@ -25,4 +25,9 @@ class JSONCLEAR extends RedisCommand
|
||||
{
|
||||
return 'JSON.CLEAR';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/json.del/
|
||||
@@ -25,4 +25,9 @@ class JSONDEL extends RedisCommand
|
||||
{
|
||||
return 'JSON.DEL';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/json.forget/
|
||||
@@ -25,4 +25,9 @@ class JSONFORGET extends RedisCommand
|
||||
{
|
||||
return 'JSON.FORGET';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
use Predis\Command\Traits\Json\Indent;
|
||||
use Predis\Command\Traits\Json\Newline;
|
||||
use Predis\Command\Traits\Json\Space;
|
||||
@@ -54,4 +54,9 @@ class JSONGET extends RedisCommand
|
||||
$this->setIndent($arguments);
|
||||
$this->filterArguments();
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/json.merge/
|
||||
@@ -26,4 +26,9 @@ class JSONMERGE extends RedisCommand
|
||||
{
|
||||
return 'JSON.MERGE';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
class JSONMGET extends RedisCommand
|
||||
{
|
||||
@@ -33,4 +33,9 @@ class JSONMGET extends RedisCommand
|
||||
|
||||
parent::setArguments($unpackedArguments);
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixSkippingLastArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/json.mset/
|
||||
@@ -25,4 +25,15 @@ class JSONMSET extends RedisCommand
|
||||
{
|
||||
return 'JSON.MSET';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
if ($arguments = $this->getArguments()) {
|
||||
for ($i = 0, $l = count($arguments); $i < $l; $i += 3) {
|
||||
$arguments[$i] = $prefix . $arguments[$i];
|
||||
}
|
||||
|
||||
$this->setArguments($arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/json.numincrby/
|
||||
@@ -25,4 +25,9 @@ class JSONNUMINCRBY extends RedisCommand
|
||||
{
|
||||
return 'JSON.NUMINCRBY';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/json.objkeys/
|
||||
@@ -25,4 +25,9 @@ class JSONOBJKEYS extends RedisCommand
|
||||
{
|
||||
return 'JSON.OBJKEYS';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/json.objlen/
|
||||
@@ -25,4 +25,9 @@ class JSONOBJLEN extends RedisCommand
|
||||
{
|
||||
return 'JSON.OBJLEN';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/json.resp/
|
||||
@@ -25,4 +25,9 @@ class JSONRESP extends RedisCommand
|
||||
{
|
||||
return 'JSON.RESP';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
use Predis\Command\Traits\Json\NxXxArgument;
|
||||
|
||||
/**
|
||||
@@ -38,4 +38,9 @@ class JSONSET extends RedisCommand
|
||||
$this->setSubcommand($arguments);
|
||||
$this->filterArguments();
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/json.strappend/
|
||||
@@ -25,4 +25,9 @@ class JSONSTRAPPEND extends RedisCommand
|
||||
{
|
||||
return 'JSON.STRAPPEND';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/json.strlen/
|
||||
@@ -25,4 +25,9 @@ class JSONSTRLEN extends RedisCommand
|
||||
{
|
||||
return 'JSON.STRLEN';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/json.toggle/
|
||||
@@ -25,4 +25,9 @@ class JSONTOGGLE extends RedisCommand
|
||||
{
|
||||
return 'JSON.TOGGLE';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\Json;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/json.type/
|
||||
@@ -25,4 +25,9 @@ class JSONTYPE extends RedisCommand
|
||||
{
|
||||
return 'JSON.TYPE';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
class LMOVE extends RedisCommand
|
||||
{
|
||||
@@ -20,4 +20,14 @@ class LMOVE extends RedisCommand
|
||||
{
|
||||
return 'LMOVE';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
if ($arguments = $this->getArguments()) {
|
||||
$arguments[0] = $prefix . $arguments[0];
|
||||
$arguments[1] = $prefix . $arguments[1];
|
||||
|
||||
$this->setRawArguments($arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,16 @@ class LPUSHX extends RedisCommand
|
||||
return 'LPUSHX';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
$arguments = self::normalizeVariadic($arguments);
|
||||
|
||||
parent::setArguments($arguments);
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
<?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\Command\Redis;
|
||||
|
||||
use Predis\Command\PrefixableCommand;
|
||||
use ValueError;
|
||||
|
||||
class MSETEX extends PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'MSETEX';
|
||||
}
|
||||
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
$processedArguments = [count(array_keys($arguments[0]))];
|
||||
|
||||
array_walk($arguments[0], function ($value, $key) use (&$processedArguments) {
|
||||
array_push($processedArguments, $key, $value);
|
||||
});
|
||||
|
||||
if (isset($arguments[1])) {
|
||||
if (!in_array(strtoupper($arguments[1]), ['NX', 'XX'])) {
|
||||
throw new ValueError('Incorrect exist modifier. Should be one of: NX, XX.');
|
||||
}
|
||||
|
||||
$processedArguments[] = strtoupper($arguments[1]);
|
||||
}
|
||||
|
||||
if (isset($arguments[2])) {
|
||||
if (!isset($arguments[3]) && strtoupper($arguments[2]) !== 'KEEPTTL') {
|
||||
throw new ValueError('TTL should be specified along with expire resolution parameter');
|
||||
}
|
||||
|
||||
if (!in_array(strtoupper($arguments[2]), ['EX', 'PX', 'EXAT', 'PXAT', 'KEEPTTL'])) {
|
||||
throw new ValueError('Incorrect expire modifier. Should be one of: EX, PX, EXAT, PXAT, KEEPTTL');
|
||||
}
|
||||
|
||||
if (strtoupper($arguments[2]) !== 'KEEPTTL') {
|
||||
array_push($processedArguments, strtoupper($arguments[2]), $arguments[3]);
|
||||
} else {
|
||||
$processedArguments[] = strtoupper($arguments[2]);
|
||||
}
|
||||
}
|
||||
|
||||
parent::setArguments($processedArguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$arguments = $this->getArguments();
|
||||
$keysCount = $arguments[0];
|
||||
$currentKeyIndex = 1;
|
||||
|
||||
while ($keysCount > 0) {
|
||||
$arguments[$currentKeyIndex] = $prefix . $arguments[$currentKeyIndex];
|
||||
$keysCount--;
|
||||
$currentKeyIndex += 2;
|
||||
}
|
||||
|
||||
parent::setRawArguments($arguments);
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,16 @@ class RPUSHX extends RedisCommand
|
||||
return 'RPUSHX';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
$arguments = self::normalizeVariadic($arguments);
|
||||
|
||||
parent::setArguments($arguments);
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/smismember/
|
||||
@@ -25,4 +25,9 @@ class SMISMEMBER extends RedisCommand
|
||||
{
|
||||
return 'SMISMEMBER';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\Search;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/ft.aggregate/
|
||||
@@ -50,4 +50,9 @@ class FTAGGREGATE extends RedisCommand
|
||||
$commandArguments
|
||||
));
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForFirstArgument($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Predis\Command\Redis\Search;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\PrefixableCommand as RedisCommand;
|
||||
|
||||
/**
|
||||
* @see https://redis.io/commands/ft.aliasadd/
|
||||
@@ -25,4 +25,9 @@ class FTALIASADD extends RedisCommand
|
||||
{
|
||||
return 'FT.ALIASADD';
|
||||
}
|
||||
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
$this->applyPrefixForAllArguments($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user