Compare commits

..

26 Commits

Author SHA1 Message Date
Till Krüss b1d3255ed9 tag v2.2.2 2023-09-13 09:42:03 -07:00
Till Krüss cbf394b882 Disable CLIENT SETINFO calls by default (#1399)
Add `client_info` parameter
2023-09-13 09:35:49 -07:00
Till Krüss c6bf644872 bump dev version 2023-09-13 09:34:52 -07:00
Vladyslav Vildanov 16bdd83d23 Added EXPIRETIME command to KeyPrefixProcessor (#1369)
* Added EXPIRETIME command to KeyPrefixProcessor

* Fixed test responses for Redis 7.2

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

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

* Removed expectations for error messages

* Changed tests group for RESP3 not supported tests

* Removed 3.x test case

* Added missing test decorators

* Fixed typo

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

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

* Update CHANGELOG.md

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

* Added quotes to CHANGELOG.md

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

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

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

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

* Test coverage

* Added comment about master nodes

* Codestyle fix

* Revert changes

* Revert DBNUM

* Added cluster endpoints to relay tests env configuration

* Exclude cluster tests from relay tests environment

* Removed TODO comment

* Changed cluster image version to unstable

* Updated configuration to match unstable cluster

* Fixed path

* Updated cluster CI configuration

* Removed redundant flag

* Removed backslash

* Updated file path

* Updated file path variable

* Added docker cluster initialization as additional step

* Run cluster tests as separate workflow

* Codestyle fixes

* Updated exported files

* Added additional timeout so cluster image could be settled

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

* Remove unused flag

* Removed variable from volume path

* Added sleep timeout to allow docker setup after running

* Added timeout before tests run

* Updated linter settings

* Include indent changes for.sh files

* Added missing coverage

* Revert expected files and mark docker folder as exclusion

* Specify folder itself as excluded

* Moved cluster tests as separate job in tests.yml

* Updated name to contain cluster word

---------

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

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

* Convert subcommand string to lower case

* Update SubcommandStrategyResolver.php

* Added test coverage

* Codestyle fixes

---------

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

* Added test coverage

* Codestyle fixes

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

* Added missing type-hints
2023-06-07 17:05:36 +03:00
623 changed files with 5688 additions and 16662 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
[codespell]
skip=./.git,./src/Command/Redis/Search/FTSUGGET.php,./examples/Commands/Search/ft_sug_add_get_del_len.php
skip=./.git
check-hidden=
check-filenames=
builtin=clear,rare,informal,usage,code,names
-2
View File
@@ -1,8 +1,6 @@
name-template: 'v$NEXT_MINOR_VERSION'
tag-template: 'v$NEXT_MINOR_VERSION'
change-template: '- $TITLE (#$NUMBER)'
filter-by-comitish: true
commitish: v3.x
autolabeler:
- label: 'maintenance'
-29
View File
@@ -1,29 +0,0 @@
matrix:
- name: Markdown
expect_match: false
apsell:
lang: en
d: en_US
ignore-case: true
dictionary:
wordlists:
- .github/wordlist.txt
output: wordlist.dic
pipeline:
- pyspelling.filters.markdown:
markdown_extensions:
- markdown.extensions.extra:
- pyspelling.filters.html:
comments: false
attributes:
- alt
ignores:
- ':matches(code, pre)'
- code
- pre
- blockquote
- img
sources:
- 'README.md'
- 'FAQ.md'
- 'docs/**'
-52
View File
@@ -1,52 +0,0 @@
ACLs
Autoloading
CAS
Customizable
ElastiCache
FPM
IANA
Lua
PSR
Packagist
PhpRedis
Predis
README
Redis
SHA
SSL
TCP
OSS
CLI
TLS
URI
autoload
autoloader
autoloading
backend
backends
behaviour
customizable
dataset
de
DevOPS
extensibility
keyspace
keyspaces
localhost
namespace
pipelining
pluggable
rebalanced
rebalancing
redis
runtime
sharding
stunnel
variadic
commitish
Kubernetes
programmatically
unhandled
invalidations
Sharded
sharded
+23 -1
View File
@@ -7,7 +7,6 @@ on:
branches:
- main
- v2.**
- v3.**
pull_request: null
permissions: {}
@@ -143,3 +142,26 @@ jobs:
echo "CURRENT =${CURRENT}"
echo "EXPECTED=${EXPECTED}"
test "${CURRENT}" = "${EXPECTED}"
spelling:
name: Spelling
needs:
- byte_level
- syntax_errors
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Cache pip
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-codespell
- name: Install codespell
run: pip install --user 'codespell>=2.2'
- name: Search for misspellings
run: $(python -m site --user-base)/bin/codespell
-9
View File
@@ -4,24 +4,15 @@ on:
push:
branches:
- main
- v2.**
- v3.**
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
update_release_draft:
permissions:
contents: write
pull-requests: write
name: Update release draft
runs-on: ubuntu-latest
-14
View File
@@ -1,14 +0,0 @@
name: spellcheck
on:
pull_request:
jobs:
check-spelling:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Check Spelling
uses: rojopolis/spellcheck-github-actions@0.33.1
with:
config_path: .github/spellcheck-settings.yml
task_name: Markdown
+66
View File
@@ -0,0 +1,66 @@
name: Stack
on:
push:
branches:
- main
- v2.**
pull_request:
jobs:
predis:
name: PHP ${{ matrix.php }} (Redis Stack ${{ matrix.redis }})
runs-on: ubuntu-latest
services:
redis:
image: redis/redis-stack-server:${{ matrix.redis }}
options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3
ports:
- 6379:6379
strategy:
fail-fast: false
matrix:
php:
- '7.2'
- '7.3'
- '7.4'
- '8.0'
- '8.1'
- '8.2'
redis:
- latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup PHP with Composer and extensions
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: relay
- name: Get Composer cache directory
id: composer-cache
run: echo "directory=$(composer config cache-dir)" >> $GITHUB_OUTPUT
- name: Cache Composer dependencies
uses: actions/cache@v3
with:
path: ${{ steps.composer-cache.outputs.directory }}
key: tests-php-${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: tests-php-${{ matrix.php }}-composer
- name: Install Composer dependencies
env:
PHP_VERSION: ${{ matrix.php }}
run: composer install --ansi --no-progress --prefer-dist
- name: Run tests
run: vendor/bin/phpunit --group realm-stack
- name: Run tests using Relay
run: vendor/bin/phpunit --group realm-stack -c phpunit.relay.xml
+9 -115
View File
@@ -5,7 +5,6 @@ on:
branches:
- main
- v2.**
- v3.**
pull_request:
concurrency:
@@ -66,26 +65,19 @@ jobs:
- name: Run tests with coverage
if: ${{ matrix.php == '8.1' && matrix.redis == '7' }}
run: vendor/bin/phpunit --coverage-php build/cov/coverage-predis.cov --coverage-filter ./src
run: vendor/bin/phpunit --coverage-clover build/logs/clover.xml --coverage-filter ./src
- name: Run tests using Relay
if: ${{ matrix.redis >= '6' && (matrix.php != '8.1' || matrix.redis != '7')}}
if: ${{ matrix.redis >= '6' }}
run: vendor/bin/phpunit -c phpunit.relay.xml
- name: Run tests using Relay with coverage
if: ${{ matrix.php == '8.1' && matrix.redis == '7' }}
run: vendor/bin/phpunit -c phpunit.relay.xml --coverage-php build/cov/coverage-relay.cov --coverage-filter ./src
- name: Merge coverage reports
if: ${{ matrix.php == '8.1' && matrix.redis == '7' }}
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.1' && matrix.redis == '7' }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel: true
env:
COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
if: ${{ env.COVERALLS_REPO_TOKEN && matrix.php == '8.1' && matrix.redis == '7' }}
run: |
wget "https://github.com/php-coveralls/php-coveralls/releases/download/v2.5.3/php-coveralls.phar"
php ./php-coveralls.phar -v
predis-cluster:
@@ -128,102 +120,4 @@ jobs:
- name: Run tests against cluster
run: |
sleep 5 # Timeout to make sure that docker image is setup
vendor/bin/phpunit --group cluster,gears-cluster
predis-stack:
name: PHP ${{ matrix.php }} (Redis Stack ${{ matrix.redis }})
needs: predis
runs-on: ubuntu-latest
services:
redis:
image: redis/redis-stack-server:${{ matrix.redis }}
options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3
ports:
- 6379:6379
strategy:
fail-fast: false
matrix:
php:
- '7.2'
- '7.3'
- '7.4'
- '8.0'
- '8.1'
- '8.2'
redis:
- edge
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup PHP with Composer and extensions
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: relay
- name: Get Composer cache directory
id: composer-cache
run: echo "directory=$(composer config cache-dir)" >> $GITHUB_OUTPUT
- name: Cache Composer dependencies
uses: actions/cache@v3
with:
path: ${{ steps.composer-cache.outputs.directory }}
key: tests-php-${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: tests-php-${{ matrix.php }}-composer
- name: Install Composer dependencies
env:
PHP_VERSION: ${{ matrix.php }}
run: composer install --ansi --no-progress --prefer-dist
- name: Run tests
if: ${{ matrix.php != '8.1' }}
run: vendor/bin/phpunit --group realm-stack
- name: Run tests with coverage
if: ${{ matrix.php == '8.1' }}
run: vendor/bin/phpunit --group realm-stack --coverage-php build/cov/coverage-stack.cov --coverage-filter ./src
- name: Run redis gears tests
if: ${{ matrix.php != '8.1' }}
run: vendor/bin/phpunit --group gears
- name: Run redis gears tests with coverage
if: ${{ matrix.php == '8.1' }}
run: vendor/bin/phpunit --group gears --coverage-php build/cov/coverage-gears.cov --coverage-filter ./src
- name: Run tests using Relay
if: ${{ matrix.php != '8.1' }}
run: vendor/bin/phpunit --group realm-stack -c phpunit.relay.xml
- name: Run tests using Relay with coverage
if: ${{ matrix.php == '8.1' }}
run: vendor/bin/phpunit --group realm-stack --coverage-php build/cov/coverage-relay-stack.cov --coverage-filter ./src -c phpunit.relay.xml
- name: Merge coverage reports
if: ${{ matrix.php == '8.1' }}
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.1' }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel: true
finish:
name: Finish Coverall
needs: predis-stack
if: ${{ always() }}
runs-on: ubuntu-latest
steps:
- name: Coveralls Finished
uses: coverallsapp/github-action@v2
with:
parallel-finished: true
vendor/bin/phpunit --group cluster
-1
View File
@@ -19,7 +19,6 @@ return (new PhpCsFixer\Config)
'phpdoc_annotation_without_dot' => false,
'no_superfluous_phpdoc_tags' => false,
'no_unneeded_curly_braces' => false,
'no_unneeded_braces' => false,
'global_namespace_import' => true,
'yoda_style' => false,
'single_line_throw' => false,
+19 -18
View File
@@ -1,30 +1,31 @@
## Changelog
## v3.0.0-alpha1 (2024-01-19)
Predis v3.0 introduces support for new communication protocol [RESP3](https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md) and [new features](README.md#resp3) based on it.
### Breaking Changes
- Refactored Relay integration (#1423)
- Changed interface of `CLIENT` command (#1337)
- Changed interfaces for commands to support Redis 6.2—7.0 arguments (#1330)
## v2.2.2 (2023-09-13)
### Added
- Added support for RESP3 communication protocol (#1047)
- Added support for [Push notifications](https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md#push-type) (#1316)
- Added support for Sharded Pub/Sub (#1303)
- Added support for `XGROUP` commands (#1324)
- Added support for `XREADGROUP` command (#1327)
- Added support for `XAUTOCLAIM` command (#1328)
- Added support for `XINFO` commands (#1331)
- Added support for Redis Gears triggered functions API (#1348)
- Added `client_info` client parameter
- Added support for `CLUSTER` container command
### Fixed
- Fixed `EXPIRETIME` not using `prefix`
- Disabled `CLIENT SETINFO` calls by default
## v2.2.1 (2023-08-15)
### Added
- Added support for `WAITAOF` command (#1357)
- Added support for `SHUTDOWN` command (#1359)
- Added support for `FUNCTION` command (#1332)
- Added support for new optional `PEXPIRE`, `PEXPIREAT` and `COMMAND`
- Added missing Redis Stack commands to `KeyPrefixProcessor` (#1358)
### Changed
- Set client name and version when establishing a connection (#1347)
## v2.2.0 (2023-06-14)
Predis v2.2.0 introduces official support for [Redis Stack](https://redis.io/docs/stack/) as well as a [Relay](https://github.com/cachewerk/relay) integration for substantially [faster read performance](https://github.com/predis/predis/wiki/Using-Relay).
## v2.2.0-RC1 (2023-05-09)
### Added
- Added support for [Relay](https://github.com/predis/predis/wiki/Using-Relay) (#1263)
- Added support for `FCALL_RO` command (#1191)
+2 -2
View File
@@ -33,7 +33,7 @@ but significantly reduces bytes sent over the network and Redis memory usage.
Without Relay, Predis will not serialize data and will never do that by default. The reason
behind this decision is that serialization is usually something that developers prefer to
customize depending on their needs and can not be easily generalized when using Redis because
customize depending on their needs and can not be easilygeneralized when using Redis because
of the many possible access patterns for your data. This does not mean that it is impossible
to have such a feature since you can leverage the extensibility of this library to define
your own serialization-aware commands. You can find more details about how to do that
@@ -90,7 +90,7 @@ Predis is fast enough when Redis is located on the same machine as PHP, more on
[PhpRedis](https://github.com/phpredis/phpredis) (and Relay) perform significantly better when
network I/O is involved, due to their ability to compress data by ~75%. Fewer bytes and received
sent over the network [means faster operations](https://akalongman.medium.com/phpredis-vs-predis-comparison-on-real-production-data-a819b48cbadb),
and potentially cost savings when network traffic isn't free (e.g. AWS ElastiCache Inter-AZ transfer costs).
and potentially cost savings when network traffic isn't free (e.g. AWS Elasticache Inter-AZ transfer costs).
## Predis is a pure-PHP implementation: it can not be fast enough! ##
-161
View File
@@ -159,7 +159,6 @@ when needed. The client options supported by default in Predis are:
- `aggregate`: configures the client with a custom aggregate connection (callable).
- `parameters`: list of default connection parameters for aggregate connections.
- `commands`: specifies a command factory instance to use through the library.
- `readTimeout`: (cluster only) Timeout between read operations while loop over connections.
Users can also provide custom options with values or callable objects (for lazy initialization) that
are stored in the options container for later use through the library.
@@ -201,26 +200,6 @@ $options = ['cluster' => 'redis'];
$client = new Predis\Client($parameters, $options);
```
#### Redis Gears with cluster ####
Since Redis v7.2, Redis Gears module is a part of Redis Stack bundle. Client supports a variety of
Redis Gears commands that can be used with OSS cluster API. Currently, before using any Redis
Gears commands against OSS cluster Redis server needs to be aware of cluster topology.
`REDISGEARS_2.REFRESHCLUSTER` command should be called against **each master node** (read replicas
should be ignored) **on cluster creation and each time cluster topology changes**.
In most cases this actions should be performed from the CLI interface by the administrator, DevOPS
or even Kubernetes, depends on your infrastructure managing process. However, client provides an API
to do this programmatically.
```php
/** @var \Predis\Connection\Cluster\ClusterInterface $connection */
$connection->executeCommandOnEachNode(
new \Predis\Command\RawCommand('REDISGEARS_2.REFRESHCLUSTER')
);
```
#### Replication ####
The client can be configured to operate in a single master / multiple slaves setup to provide better
@@ -446,147 +425,7 @@ $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.
## RESP3 ##
### Connection ###
To establish the connection using RESP3 protocol, you need to set parameter `protocol => 3`. Default protocol is still RESP2.
You can pass parameter as configuration option in array or as a query parameter in `redis_url`
```php
// Configuration option
$client = new \Predis\Client(['protocol' => 3]);
// Redis URL
$client = new \Predis\Client('redis://localhost:6379?protocol=3');
// ["proto" => "3"]
$client->executeRaw(['HELLO']);
```
### Command responses ###
RESP3 protocol introduce a variety of new [response types](https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md#resp3-types),
so on the client-side we have more explicit understanding on data types we retrieve from server. Here's some examples to show the difference
between RESP2 and RESP3 responses.
#### Float responses ####
``` php
// RESP2 connection
$client = new \Predis\Client();
$client->geoadd('my_geo', 11.111, 22.222, 'member1');
// [[0 => string(20) "11.11099988222122192", 1 => string(20) "22.22200052541037252"]]
// RESP2 returns float values as simple strings.
var_dump($client->geopos('my_geo', ['member1']));
// RESP3 connection
$client = new \Predis\Client(['protocol' => 3]);
// [[0 => float(11.110999882221222), 1 => float(22.222000525410373)]]
// RESP3 introduces new double type, that corresponds to PHP float.
var_dump($client->geopos('my_geo', ['member1']));
```
#### Aggregate types ####
In RESP3 new aggregate type [Map](https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md#map-type)
was introduced, that represents the sequence of field-value pairs. So it simplifies parsing, since we don't need to specify
parsing strategy per command (RESP2) and instead relies on the type defined by protocol (RESP3).
In most cases RESP2 responses shouldn't differ from RESP3, since we added additional parsing for those
command that return field-value pairs. However, since RESP2 requires additional parsing, it could be that some commands
had lack of it and return unhandled responses. In this case there would be difference like this:
```php
$client = new \Predis\Client();
// RESP2: ['field', 'value]
$client->commandThatReturnsFieldValuePair('key');
$client = new \Predis\Client(['protocol' => 3]);
// RESP3: ['field' => 'value]
$client->commandThatReturnsFieldValuePair('key');
```
Feel free to open PR or GitHub issue if you face those protocol mismatching.
### Push notifications ###
RESP3 introduce a concept of [push connection](https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md#push-type),
is the one where server could send asynchronous data to client which was not explicitly requested. Predis 3.0 provides
an API to establish this kind of connection as separate blocking process (worker) and invoke callbacks depends on push
notification message type.
#### Consumer ####
First of all, you need to set up a consumer connection and provide an optional callback that will be executed before
event loop will be started. It allows you to subscribe on channels, enable keys invalidations tracking or enable monitor
connection, any Redis command to let server know that you want to receive push notification within this connection.
```php
// Make sure that RESP3 protocol enabled and read_write_timeout set 0,
// so connection won't be killed by timeout.
$client = new Predis\Client(['read_write_timeout' => 0, 'protocol' => 3]);
// Create push notifications consumer.
// Provides callback where current consumer subscribes to few channels before
// enter the loop.
$push = $client->push(static function (ClientInterface $client) {
$response = $client->subscribe('channel', 'control');
$status = ($response[2] === 1) ? 'OK' : 'FAILED';
echo "Channel subscription status: {$status}\n";
});
```
#### Dispatcher loop ####
Dispatcher object allows you to attach a callback to given push notification type and run the actual worker process that
listen for incoming push notifications. To be able to stop blocking process in runtime you can specify a condition and
call `$dispatcher->stop()` method from given callback. In this example we're waiting for specific message `terminate`
within `control` channel that we subscribed to before entering the loop.
```php
// Storage for incoming notifications.
$messages = [];
// Create dispatcher for push notifications.
$dispatcher = new Predis\Consumer\Push\DispatcherLoop($push);
$dispatcher->attachCallback(
PushResponseInterface::MESSAGE_DATA_TYPE,
static function (array $payload, DispatcherLoopInterface $dispatcher) {
global $messages;
[$channel, $message] = $payload;
if ($channel === 'control' && $message === 'terminate') {
echo "Terminating notification consumer.\n";
$dispatcher->stop();
return;
}
$messages[] = $message;
echo "Received message: {$message}\n";
}
);
// Run consumer loop with attached callbacks.
$dispatcher->run();
// Count all messages that were received during consumer loop.
$messagesCount = count($messages);
echo "We received: {$messagesCount} messages\n";
```
This example shows a simple script to count all incoming messages from push notifications that we receive from
subscribed channels until stop condition will be met. Examples available in `examples/` folder.
### Sharded pub/sub ###
From Redis 7.0, sharded Pub/Sub is introduced in which shard channels are assigned to slots by the same algorithm used
to assign keys to slots.
Predis 3.0 provides an API that allows to use pub/sub for Cluster connections using sharded pub/sub from Redis.
You don't need to specify any additional configuration to enable sharded pub/sub, it will be automatically enabled if
Cluster connection is using.
Implementation looks pretty much the same as Push notification, so you need to set up consumer
and run it over Dispatcher loop object. All examples available in `examples/` folder.
## Development ##
+1 -1
View File
@@ -1 +1 @@
3.0.0-alpha1
2.2.2
+1 -2
View File
@@ -27,8 +27,7 @@
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.3",
"phpstan/phpstan": "^1.9",
"phpunit/phpunit": "^8.0 || ~9.4.4",
"phpunit/phpcov": "^6.0 || ^8.0"
"phpunit/phpunit": "^8.0 || ~9.4.4"
},
"suggest": {
"ext-relay": "Faster connection with in-memory caching (>=0.6.2)"
+1 -1
View File
@@ -1,4 +1,4 @@
FROM redis/redis-stack-server:edge as rss
FROM redis/redis-stack-server:latest as rss
COPY create_cluster.sh /create_cluster.sh
RUN ls -R /opt/redis-stack
+1 -1
View File
@@ -11,7 +11,7 @@ services:
- "6374:6374"
- "6375:6375"
- "6376:6376"
- "6377:6377"
- "6377:6378"
volumes:
- "./redis.conf:/redis.conf:ro"
-2
View File
@@ -3,8 +3,6 @@
# port, cluster-enabled, daemonize, logfile, dir
protected-mode no
loadmodule /opt/redis-stack/lib/redisearch.so
loadmodule /opt/redis-stack/lib/redisgraph.so
loadmodule /opt/redis-stack/lib/redisgears.so v8-plugin-path /opt/redis-stack/lib/libredisgears_v8_plugin.so
loadmodule /opt/redis-stack/lib/redistimeseries.so
loadmodule /opt/redis-stack/lib/rejson.so
loadmodule /opt/redis-stack/lib/redisbloom.so
+41
View File
@@ -0,0 +1,41 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
require __DIR__ . '/../shared.php';
// Example of WAITAOF command usage:
// 1. Enable appendonly mode if it's not (command works only in appendonly mode)
$client = new Client($single_server);
$info = $client->info();
$enabled = false;
if ($info['Persistence']['aof_enabled'] === '0') {
$client->config('set', 'appendonly', 'yes');
$enabled = true;
}
// 2. Set key value pair
$response = $client->set('foo', 'bar');
echo "Key-value pair set status: {$response}\n";
// 3. Run WAITAOF command to make sure that all previous writes was fsynced
$response = $client->waitaof(1, 0, 0);
echo "Quantity of local instances that was fsynced - {$response[0]}, quantity of replicas - {$response[1]}";
// 4. Disable appendonly mode if it was enabled during script execution
if ($enabled) {
$client->config('set', 'appendonly', 'no');
}
+1 -1
View File
@@ -30,7 +30,7 @@ $client = new Predis\Client($single_server + ['read_write_timeout' => 0]);
$pubsub = $client->pubSubLoop();
// Create a dispatcher loop instance and attach a bunch of callbacks.
$dispatcher = new Predis\Consumer\PubSub\DispatcherLoop($pubsub);
$dispatcher = new Predis\PubSub\DispatcherLoop($pubsub);
// Demonstrate how to use a callable class as a callback for the dispatcher loop.
class EventsListener implements Countable
-49
View File
@@ -1,49 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\ClientInterface;
use Predis\Consumer\Push\PushResponseInterface;
require __DIR__ . '/shared.php';
// 1. Create client with RESP3 protocol specified. Push notifications allowed only in RESP3 mode.
$client = new Predis\Client($single_server + ['read_write_timeout' => 0, 'protocol' => 3]);
// 2. Create push notifications consumer. Provides callback where current consumer subscribes to few channels before enter the loop.
$push = $client->push(static function (ClientInterface $client) {
$response = $client->subscribe('channel', 'control');
$status = ($response[2] === 1) ? 'OK' : 'FAILED';
echo "Channel subscription status: {$status}\n";
});
// 3. Run consumer that will handle message data type push notifications. And stops if certain message will be sent to control channel.
// Send following commands via redis-cli to test:
//
// PUBLISH channel message1
// PUBLISH channel message2
// PUBLISH channel message3
// PUBLISH control terminate
// Data types should be changed in near future. Instead of Message data type it should be one of kind data types.
foreach ($push as $notification) {
if ((null !== $notification) && $notification->getDataType() === PushResponseInterface::MESSAGE_DATA_TYPE) {
if ($notification[1] === 'control' && $notification[2] === 'terminate') {
echo "Terminating notification consumer.\n";
$push->stop();
break;
}
$message = $notification[2];
echo "Received message: {$message}\n";
}
}
@@ -1,68 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\ClientInterface;
use Predis\Consumer\DispatcherLoopInterface;
use Predis\Consumer\Push\DispatcherLoop;
use Predis\Consumer\Push\PushResponseInterface;
require __DIR__ . '/shared.php';
// 1. Create client with RESP3 protocol specified. Push notifications allowed only in RESP3 mode.
$client = new Predis\Client($single_server + ['read_write_timeout' => 0, 'protocol' => 3]);
// 2. Create push notifications consumer. Provides callback where current consumer subscribes to few channels before enter the loop.
$push = $client->push(static function (ClientInterface $client) {
$response = $client->subscribe('channel', 'control');
$status = ($response[2] === 1) ? 'OK' : 'FAILED';
echo "Channel subscription status: {$status}\n";
});
// 3. Storage for upcoming notifications.
$messages = [];
// 4. Create dispatcher for push notifications.
$dispatcher = new DispatcherLoop($push);
// 5. Attach callback for message data type. Print every message and store them in storage.
// Send following commands via redis-cli to test:
//
// PUBLISH channel message1
// PUBLISH channel message2
// PUBLISH channel message3
// PUBLISH control terminate
// Data types should be changed in near future. Instead of Message data type it should be one of kind data types.
$dispatcher->attachCallback(
PushResponseInterface::MESSAGE_DATA_TYPE,
static function (array $payload, DispatcherLoopInterface $dispatcher) {
global $messages;
[$channel, $message] = $payload;
if ($channel === 'control' && $message === 'terminate') {
echo "Terminating notification consumer.\n";
$dispatcher->stop();
return;
}
$messages[] = $message;
echo "Received message: {$message}\n";
}
);
// 6. Run consumer loop with attached callbacks.
$dispatcher->run();
// 7. Count all messages that were received during consumer loop.
$messagesCount = count($messages);
echo "We received: {$messagesCount} messages\n";
-91
View File
@@ -1,91 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
require __DIR__ . '/shared.php';
// This is a basic example on how to use the Predis\DispatcherLoop class in sharded pub/sub mode.
//
// Both channels belong to different shards. So in sharded mode we can subscribe
// and receive messages from different shard channels.
//
// To see this example in action you can just use redis-cli and publish some
// messages to the '{channels}_events' and 'control' channel, e.g.:
// ./redis-cli
// SPUBLISH {channels}_events first
// SPUBLISH {channels}_events second
// SPUBLISH {channels}_events third
// SPUBLISH control terminate_dispatcher
// 1. Create client and setup RW timeout to 0.
$client = new Client(
[
'tcp://127.0.0.1:6372?read_write_timeout=0',
'tcp://127.0.0.1:6373?read_write_timeout=0',
'tcp://127.0.0.1:6374?read_write_timeout=0',
], [
'cluster' => 'redis',
]);
// 2. Run pub/sub loop.
$pubSub = $client->pubSubLoop();
// 3. Create a dispatcher loop instance and attach a bunch of callbacks.
$dispatcher = new Predis\Consumer\PubSub\DispatcherLoop($pubSub);
// 4. Demonstrate how to use a callable class as a callback for the dispatcher loop.
class EventsListener implements Countable
{
private $events;
public function __construct()
{
$this->events = [];
}
public function count()
{
return count($this->events);
}
public function getEvents()
{
return $this->events;
}
public function __invoke($payload, $dispatcher)
{
$this->events[] = $payload;
}
}
// 5. Attach our callable class to the dispatcher.
$dispatcher->attachCallback('{channels}_events', $events = new EventsListener());
// 6. Attach a function to control the dispatcher loop termination with a message.
$dispatcher->attachCallback('control', function ($payload, $dispatcher) {
if ($payload === 'terminate_dispatcher') {
$dispatcher->stop();
}
});
// 7. Run the dispatcher loop until the callback attached to the 'control' channel
// receives 'terminate_dispatcher' as a message.
$dispatcher->run();
// Display our achievements!
echo "We received {$events->count()} messages!", PHP_EOL;
// Say goodbye :-)
echo 'Goodbye from Redis!', PHP_EOL;
-64
View File
@@ -1,64 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Predis\Client;
require __DIR__ . '/shared.php';
// 1. Create client and setup RW timeout to 0.
$client = new Client(
[
'tcp://127.0.0.1:6372?read_write_timeout=0',
'tcp://127.0.0.1:6373?read_write_timeout=0',
'tcp://127.0.0.1:6374?read_write_timeout=0',
], [
'cluster' => 'redis',
]);
// 2. Run pub/sub loop. Sharded channels belongs to different shards.
$pubSub = $client->pubSubLoop();
$pubSub->ssubscribe('{channels}_notifications');
$pubSub->ssubscribe('control_channel');
// Start processing the pubsup messages. Open a terminal and use redis-cli
// to push messages to the channels. Examples:
// ./redis-cli SPUBLISH {channels}_notifications "this is a test"
// ./redis-cli SPUBLISH control_channel quit_loop
foreach ($pubSub as $message) {
switch ($message->kind) {
case 'ssubscribe':
echo "Subscribed to {$message->channel}", PHP_EOL;
break;
case 'message':
if ($message->channel == 'control_channel') {
if ($message->payload == 'quit_loop') {
echo 'Aborting pubsub loop...', PHP_EOL;
$pubSub->sunsubscribe();
} else {
echo "Received an unrecognized command: {$message->payload}.", PHP_EOL;
}
} else {
echo "Received the following message from {$message->channel}:",
PHP_EOL, " {$message->payload}", PHP_EOL, PHP_EOL;
}
break;
}
}
// Always unset the pubsub consumer instance when you are done! The
// class destructor will take care of cleanups and prevent protocol
// desynchronizations between the client and the server.
unset($pubsub);
// Say goodbye :-)
echo 'Goodbye from Redis!', PHP_EOL;
+6
View File
@@ -12,6 +12,9 @@ parameters:
- message: "#^Cannot cast Predis\\\\Connection\\\\ConnectionInterface to string\\.$#"
count: 1
path: src/Client.php
# phpiredis extension is not installed
- "#^Function phpiredis_\\w+ not found\\.$#"
- "#^Constant PHPIREDIS_#"
# "new static" in non-final classes
- message: "#^Unsafe usage of new static\\(\\)\\.$#"
count: 3
@@ -26,6 +29,9 @@ parameters:
- message: "#^Call to an undefined method Predis\\\\Command\\\\FactoryInterface\\:\\:undefine\\(\\)\\.$#"
count: 1
path: src/Configuration/Option/Commands.php
- message: "#^Access to an undefined property Predis\\\\Configuration\\\\OptionsInterface\\:\\:\\$parameters\\.$#"
count: 1
path: src/Configuration/Option/Connections.php
- message: "#^Access to an undefined property Predis\\\\Connection\\\\ParametersInterface\\:\\:\\$weight\\.$#"
count: 1
path: src/Connection/Cluster/PredisCluster.php
+2 -5
View File
@@ -17,18 +17,15 @@
</testsuite>
</testsuites>
<logging>
<log type="coverage-php" target="build/cov/coverage.cov"/>
</logging>
<groups>
<exclude>
<group>relay-incompatible</group>
<group>relay-resp3</group>
<group>realm-webdis</group>
<group>realm-stack</group>
<group>ext-curl</group>
<group>ext-phpiredis</group>
<group>cluster</group>
<group>gears</group>
</exclude>
</groups>
+10 -5
View File
@@ -17,18 +17,23 @@
</testsuite>
</testsuites>
<logging>
<log type="coverage-php" target="build/cov/coverage.cov"/>
</logging>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./src</directory>
</include>
<report>
<clover outputFile="build/logs/clover.xml"/>
</report>
</coverage>
<groups>
<exclude>
<group>realm-webdis</group>
<group>realm-stack</group>
<group>ext-relay</group>
<group>ext-curl</group>
<group>ext-phpiredis</group>
<group>cluster</group>
<group>gears</group>
<group>gears-cluster</group>
<!-- <group>connected</group> -->
<!-- <group>disconnected</group> -->
<!-- <group>commands</group> -->
+6 -23
View File
@@ -16,9 +16,9 @@ use ArrayIterator;
use InvalidArgumentException;
use IteratorAggregate;
use Predis\Command\CommandInterface;
use Predis\Command\Container\ContainerFactory;
use Predis\Command\Container\ContainerInterface;
use Predis\Command\RawCommand;
use Predis\Command\Redis\Container\ContainerFactory;
use Predis\Command\Redis\Container\ContainerInterface;
use Predis\Command\ScriptCommand;
use Predis\Configuration\Options;
use Predis\Configuration\OptionsInterface;
@@ -26,15 +26,14 @@ use Predis\Connection\ConnectionInterface;
use Predis\Connection\Parameters;
use Predis\Connection\ParametersInterface;
use Predis\Connection\RelayConnection;
use Predis\Consumer\PubSub\Consumer as PubSubConsumer;
use Predis\Consumer\PubSub\RelayConsumer as RelayPubSubConsumer;
use Predis\Consumer\Push\Consumer as PushConsumer;
use Predis\Monitor\Consumer as MonitorConsumer;
use Predis\Pipeline\Atomic;
use Predis\Pipeline\FireAndForget;
use Predis\Pipeline\Pipeline;
use Predis\Pipeline\RelayAtomic;
use Predis\Pipeline\RelayPipeline;
use Predis\PubSub\Consumer as PubSubConsumer;
use Predis\PubSub\RelayConsumer as RelayPubSubConsumer;
use Predis\Response\ErrorInterface as ErrorResponseInterface;
use Predis\Response\ResponseInterface;
use Predis\Response\ServerException;
@@ -54,7 +53,7 @@ use Traversable;
*/
class Client implements ClientInterface, IteratorAggregate
{
public const VERSION = '3.0.0-alpha1';
public const VERSION = '2.2.2';
/** @var OptionsInterface */
private $options;
@@ -380,7 +379,6 @@ class Client implements ClientInterface, IteratorAggregate
public function executeCommand(CommandInterface $command)
{
$response = $this->connection->executeCommand($command);
$parameters = $this->connection->getParameters();
if ($response instanceof ResponseInterface) {
if ($response instanceof ErrorResponseInterface) {
@@ -390,11 +388,7 @@ class Client implements ClientInterface, IteratorAggregate
return $response;
}
if ($parameters->protocol === 2) {
return $command->parseResponse($response);
}
return $command->parseResp3Response($response);
return $command->parseResponse($response);
}
/**
@@ -555,17 +549,6 @@ class Client implements ClientInterface, IteratorAggregate
return $this->sharedContextFactory('createPubSub', func_get_args());
}
/**
* Creates new push notifications consumer.
*
* @param callable|null $preLoopCallback Callback that should be called on client before enter a loop.
* @return PushConsumer
*/
public function push(callable $preLoopCallback = null): PushConsumer
{
return new PushConsumer($this, $preLoopCallback);
}
/**
* Actual publish/subscribe context initializer method.
*
+19 -27
View File
@@ -38,14 +38,12 @@ use Predis\Command\Argument\TimeSeries\MGetArguments;
use Predis\Command\Argument\TimeSeries\MRangeArguments;
use Predis\Command\Argument\TimeSeries\RangeArguments;
use Predis\Command\CommandInterface;
use Predis\Command\Container\ACL;
use Predis\Command\Container\CLIENT;
use Predis\Command\Container\FUNCTIONS;
use Predis\Command\Container\Json\JSONDEBUG;
use Predis\Command\Container\Search\FTCONFIG;
use Predis\Command\Container\Search\FTCURSOR;
use Predis\Command\Container\TFUNCTION;
use Predis\Command\Container\XGROUP;
use Predis\Command\Redis\Container\ACL;
use Predis\Command\Redis\Container\CLUSTER;
use Predis\Command\Redis\Container\FunctionContainer;
use Predis\Command\Redis\Container\Json\JSONDEBUG;
use Predis\Command\Redis\Container\Search\FTCONFIG;
use Predis\Command\Redis\Container\Search\FTCURSOR;
/**
* Interface defining a client-side context such as a pipeline or transaction.
@@ -61,8 +59,8 @@ use Predis\Command\Container\XGROUP;
* @method $this move($key, $db)
* @method $this object($subcommand, $key)
* @method $this persist($key)
* @method $this pexpire($key, $milliseconds, string $option = null)
* @method $this pexpireat($key, $timestamp, string $option = null)
* @method $this pexpire($key, $milliseconds)
* @method $this pexpireat($key, $timestamp)
* @method $this pttl($key)
* @method $this randomkey()
* @method $this rename($key, $target)
@@ -228,9 +226,6 @@ use Predis\Command\Container\XGROUP;
* @method $this srandmember($key, $count = null)
* @method $this srem($key, $member)
* @method $this sscan($key, $cursor, array $options = null)
* @method $this ssubscribe(string ...$shardChannels)
* @method $this subscribe(string ...$channels)
* @method $this sunsubscribe(?string ...$shardChannels = null)
* @method $this sunion(array|string $keys)
* @method $this sunionstore($destination, array|string $keys)
* @method $this tdigestadd(string $key, float ...$value)
@@ -247,8 +242,6 @@ use Predis\Command\Container\XGROUP;
* @method $this tdigestreset(string $key)
* @method $this tdigestrevrank(string $key, float ...$value)
* @method $this tdigesttrimmed_mean(string $key, float $lowCutQuantile, float $highCutQuantile)
* @method $this tfcall(string $libraryName, string $functionName, array $keys = [], array $arguments = [])
* @method $this tfcallasync(string $libraryName, string $functionName, array $keys = [], array $arguments = [])
* @method $this topkadd(string $key, ...$items)
* @method $this topkincrby(string $key, ...$itemIncrement)
* @method $this topkinfo(string $key)
@@ -312,31 +305,32 @@ use Predis\Command\Container\XGROUP;
* @method $this exec()
* @method $this multi()
* @method $this unwatch()
* @method $this unsubscribe(string ...$channels)
* @method $this waitaof(int $numLocal, int $numReplicas, int $timeout)
* @method $this watch($key)
* @method $this eval($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
* @method $this eval_ro(string $script, array $keys, ...$argument)
* @method $this evalsha($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
* @method $this evalsha_ro(string $sha1, array $keys, ...$argument)
* @method $this script($subcommand, $argument = null)
* @method $this shutdown(bool $noSave = null, bool $now = false, bool $force = false, bool $abort = false)
* @method $this auth($password)
* @method $this echo($message)
* @method $this ping($message = null)
* @method $this select($database)
* @method $this bgrewriteaof()
* @method $this bgsave()
* @method $this client($subcommand, $argument = null)
* @method $this config($subcommand, $argument = null)
* @method $this dbsize()
* @method $this flushall()
* @method $this flushdb()
* @method $this info(string ...$section = null)
* @method $this info($section = null)
* @method $this lastsave()
* @method $this save()
* @method $this slaveof($host, $port)
* @method $this slowlog($subcommand, $argument = null)
* @method $this spublish(string $shardChannel, string $message)
* @method $this time()
* @method $this command($subcommand, $argument = null)
* @method $this command()
* @method $this geoadd($key, $longitude, $latitude, $member)
* @method $this geohash($key, array $members)
* @method $this geopos($key, array $members)
@@ -347,14 +341,12 @@ use Predis\Command\Container\XGROUP;
* @method $this geosearchstore(string $destination, string $source, FromInterface $from, ByInterface $by, ?string $sorting = null, int $count = -1, bool $any = false, bool $storeDist = false)
*
* Container commands
* @property CLIENT $client
* @property FUNCTIONS $function
* @property FTCONFIG $ftconfig
* @property FTCURSOR $ftcursor
* @property JSONDEBUG $jsondebug
* @property ACL $acl
* @property XGROUP $xgroup
* @property TFUNCTION $tfunction
* @property CLUSTER $cluster
* @property FunctionContainer $function
* @property FTCONFIG $ftconfig
* @property FTCURSOR $ftcursor
* @property JSONDEBUG $jsondebug
* @property ACL $acl
*/
interface ClientContextInterface
{
+29 -41
View File
@@ -38,16 +38,13 @@ use Predis\Command\Argument\TimeSeries\MGetArguments;
use Predis\Command\Argument\TimeSeries\MRangeArguments;
use Predis\Command\Argument\TimeSeries\RangeArguments;
use Predis\Command\CommandInterface;
use Predis\Command\Container\ACL;
use Predis\Command\Container\CLIENT;
use Predis\Command\Container\FUNCTIONS;
use Predis\Command\Container\Json\JSONDEBUG;
use Predis\Command\Container\Search\FTCONFIG;
use Predis\Command\Container\Search\FTCURSOR;
use Predis\Command\Container\TFUNCTION;
use Predis\Command\Container\XGROUP;
use Predis\Command\Container\XINFO;
use Predis\Command\FactoryInterface;
use Predis\Command\Redis\Container\ACL;
use Predis\Command\Redis\Container\CLUSTER;
use Predis\Command\Redis\Container\FunctionContainer;
use Predis\Command\Redis\Container\Json\JSONDEBUG;
use Predis\Command\Redis\Container\Search\FTCONFIG;
use Predis\Command\Redis\Container\Search\FTCURSOR;
use Predis\Configuration\OptionsInterface;
use Predis\Connection\ConnectionInterface;
use Predis\Response\Status;
@@ -71,8 +68,8 @@ use Predis\Response\Status;
* @method int move(string $key, int $db)
* @method mixed object($subcommand, string $key)
* @method int persist(string $key)
* @method int pexpire(string $key, int $milliseconds, string $option = null)
* @method int pexpireat(string $key, int $timestamp, string $option = null)
* @method int pexpire(string $key, int $milliseconds)
* @method int pexpireat(string $key, int $timestamp)
* @method int pttl(string $key)
* @method string|null randomkey()
* @method mixed rename(string $key, string $target)
@@ -83,8 +80,8 @@ use Predis\Response\Status;
* @method int ttl(string $key)
* @method mixed type(string $key)
* @method int append(string $key, $value)
* @method mixed bfadd(string $key, $item)
* @method mixed bfexists(string $key, $item)
* @method int bfadd(string $key, $item)
* @method int bfexists(string $key, $item)
* @method array bfinfo(string $key, string $modifier = '')
* @method array bfinsert(string $key, int $capacity = -1, float $error = -1, int $expansion = -1, bool $noCreate = false, bool $nonScaling = false, string ...$item)
* @method Status bfloadchunk(string $key, int $iterator, $data)
@@ -100,11 +97,11 @@ use Predis\Response\Status;
* @method array bzpopmax(array $keys, int $timeout)
* @method array bzpopmin(array $keys, int $timeout)
* @method array bzmpop(int $timeout, array $keys, string $modifier = 'min', int $count = 1)
* @method mixed cfadd(string $key, $item)
* @method mixed cfaddnx(string $key, $item)
* @method int cfadd(string $key, $item)
* @method int cfaddnx(string $key, $item)
* @method int cfcount(string $key, $item)
* @method mixed cfdel(string $key, $item)
* @method mixed cfexists(string $key, $item)
* @method int cfdel(string $key, $item)
* @method int cfexists(string $key, $item)
* @method Status cfloadchunk(string $key, int $iterator, $data)
* @method int cfmexists(string $key, ...$item)
* @method array cfinfo(string $key)
@@ -189,8 +186,8 @@ use Predis\Response\Status;
* @method array jsonarrtrim(string $key, string $path, int $start, int $stop)
* @method int jsondel(string $key, string $path = '$')
* @method int jsonforget(string $key, string $path = '$')
* @method mixed jsonget(string $key, string $indent = '', string $newline = '', string $space = '', string ...$paths)
* @method mixed jsonnumincrby(string $key, string $path, int $value)
* @method string jsonget(string $key, string $indent = '', string $newline = '', string $space = '', string ...$paths)
* @method string jsonnumincrby(string $key, string $path, int $value)
* @method Status jsonmerge(string $key, string $path, string $value)
* @method array jsonmget(array $keys, string $path)
* @method Status jsonmset(string ...$keyPathValue)
@@ -238,11 +235,8 @@ use Predis\Response\Status;
* @method string|null srandmember(string $key, int $count = null)
* @method int srem(string $key, array|string $member)
* @method array sscan(string $key, int $cursor, array $options = null)
* @method array ssubscribe(string ...$shardChannels)
* @method array subscribe(string ...$channels)
* @method string[] sunion(array|string $keys)
* @method int sunionstore(string $destination, array|string $keys)
* @method array sunsubscribe(?string ...$shardChannels = null)
* @method int touch(string[]|string $keyOrKeys, string ...$keys = null)
* @method Status tdigestadd(string $key, float ...$value)
* @method array tdigestbyrank(string $key, int ...$rank)
@@ -250,16 +244,14 @@ use Predis\Response\Status;
* @method array tdigestcdf(string $key, int ...$value)
* @method Status tdigestcreate(string $key, int $compression = 0)
* @method array tdigestinfo(string $key)
* @method mixed tdigestmax(string $key)
* @method string tdigestmax(string $key)
* @method Status tdigestmerge(string $destinationKey, array $sourceKeys, int $compression = 0, bool $override = false)
* @method string[] tdigestquantile(string $key, float ...$quantile)
* @method mixed tdigestmin(string $key)
* @method string tdigestmin(string $key)
* @method array tdigestrank(string $key, float ...$value)
* @method Status tdigestreset(string $key)
* @method array tdigestrevrank(string $key, float ...$value)
* @method string tdigesttrimmed_mean(string $key, float $lowCutQuantile, float $highCutQuantile)
* @method mixed tfcall(string $libraryName, string $functionName, array $keys = [], array $arguments = [])
* @method mixed tfcallasync(string $libraryName, string $functionName, array $keys = [], array $arguments = [])
* @method array topkadd(string $key, ...$items)
* @method array topkincrby(string $key, ...$itemIncrement)
* @method array topkinfo(string $key)
@@ -284,12 +276,10 @@ use Predis\Response\Status;
* @method array tsrange(string $key, $fromTimestamp, $toTimestamp, ?RangeArguments $arguments = null)
* @method array tsrevrange(string $key, $fromTimestamp, $toTimestamp, ?RangeArguments $arguments = null)
* @method string xadd(string $key, array $dictionary, string $id = '*', array $options = null)
* @method array xautoclaim(string $key, string $group, string $consumer, int $minIdleTime, string $start, ?int $count = null, bool $justId = false)
* @method int xdel(string $key, string ...$id)
* @method int xlen(string $key)
* @method array xrevrange(string $key, string $end, string $start, ?int $count = null)
* @method array xrange(string $key, string $start, string $end, ?int $count = null)
* @method array xreadgroup(string $group, string $consumer, ?int $count = null, ?int $blockMs = null, bool $noAck = false, string ...$keyOrId)
* @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)
@@ -333,31 +323,32 @@ use Predis\Response\Status;
* @method array|null exec()
* @method mixed multi()
* @method mixed unwatch()
* @method array unsubscribe(string ...$channels)
* @method array waitaof(int $numLocal, int $numReplicas, int $timeout)
* @method mixed watch(string $key)
* @method mixed eval(string $script, int $numkeys, string ...$keyOrArg = null)
* @method mixed eval_ro(string $script, array $keys, ...$argument)
* @method mixed evalsha(string $script, int $numkeys, string ...$keyOrArg = null)
* @method mixed evalsha_ro(string $sha1, array $keys, ...$argument)
* @method mixed script($subcommand, $argument = null)
* @method Status shutdown(bool $noSave = null, bool $now = false, bool $force = false, bool $abort = false)
* @method mixed auth(string $password)
* @method string echo(string $message)
* @method mixed ping(string $message = null)
* @method mixed select(int $database)
* @method mixed bgrewriteaof()
* @method mixed bgsave()
* @method mixed client($subcommand, $argument = null)
* @method mixed config($subcommand, $argument = null)
* @method int dbsize()
* @method mixed flushall()
* @method mixed flushdb()
* @method array info(string ...$section = null)
* @method array info($section = null)
* @method int lastsave()
* @method mixed save()
* @method mixed slaveof(string $host, int $port)
* @method mixed slowlog($subcommand, $argument = null)
* @method int spublish(string $shardChannel, string $message)
* @method array time()
* @method array command($subcommand, $argument = null)
* @method array command()
* @method int geoadd(string $key, $longitude, $latitude, $member)
* @method array geohash(string $key, array $members)
* @method array geopos(string $key, array $members)
@@ -368,15 +359,12 @@ use Predis\Response\Status;
* @method int geosearchstore(string $destination, string $source, FromInterface $from, ByInterface $by, ?string $sorting = null, int $count = -1, bool $any = false, bool $storeDist = false)
*
* Container commands
* @property CLIENT $client
* @property FUNCTIONS $function
* @property FTCONFIG $ftconfig
* @property FTCURSOR $ftcursor
* @property JSONDEBUG $jsondebug
* @property ACL $acl
* @property XGROUP $xgroup
* @property XINFO $xinfo
* @property TFUNCTION $tfunction
* @property CLUSTER $cluster
* @property FunctionContainer $function
* @property FTCONFIG $ftconfig
* @property FTCURSOR $ftcursor
* @property JSONDEBUG $jsondebug
* @property ACL $acl
*/
interface ClientInterface
{
+2 -27
View File
@@ -175,15 +175,8 @@ abstract class ClusterStrategy implements StrategyInterface
'GEORADIUS' => [$this, 'getKeyFromGeoradiusCommands'],
'GEORADIUSBYMEMBER' => [$this, 'getKeyFromGeoradiusCommands'],
/* sharded pubsub */
'SSUBSCRIBE' => $getKeyFromAllArguments,
'SUNSUBSCRIBE' => [$this, 'getKeyFromSUnsubscribeCommand'],
'SPUBLISH' => $getKeyFromFirstArgument,
/* gears */
'TFUNCTION' => [$this, 'getFakeKey'],
'TFCALL' => [$this, 'getFakeKey'],
'TFCALLASYNC' => [$this, 'getFakeKey'],
/* cluster */
'CLUSTER' => [$this, 'getFakeKey'],
];
}
@@ -412,24 +405,6 @@ abstract class ClusterStrategy implements StrategyInterface
return $arguments[0];
}
/**
* Extracts key from SUNSUBSCRIBE command if it's given.
*
* @param CommandInterface $command
* @return string
*/
protected function getKeyFromSUnsubscribeCommand(CommandInterface $command): ?string
{
$arguments = $command->getArguments();
// SUNSUBSCRIBE command could be called without arguments, so it doesn't matter on each node it will be called.
if (empty($arguments)) {
return 'fake';
}
return $this->getKeyFromAllArguments($command);
}
/**
* Extracts the key from EVAL and EVALSHA commands.
*
+42
View File
@@ -0,0 +1,42 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Cluster\Hash;
use Predis\NotSupportedException;
/**
* Hash generator implementing the CRC-CCITT-16 algorithm used by redis-cluster.
*
* @deprecated 2.1.2
*/
class PhpiredisCRC16 implements HashGeneratorInterface
{
public function __construct()
{
if (!function_exists('phpiredis_utils_crc16')) {
// @codeCoverageIgnoreStart
throw new NotSupportedException(
'This hash generator requires a compatible version of ext-phpiredis'
);
// @codeCoverageIgnoreEnd
}
}
/**
* {@inheritdoc}
*/
public function hash($value)
{
return phpiredis_utils_crc16($value);
}
}
@@ -1,49 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 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\Stream;
use Predis\Command\Argument\ArrayableArgument;
class XInfoStreamOptions implements ArrayableArgument
{
/**
* @var array
*/
protected $options = [];
/**
* Modifier provides a more verbose reply.
* The COUNT option can be used to limit the number of stream and PEL entries that are returned.
*
* @param int|null $count
* @return self
*/
public function full(int $count = null): self
{
$this->options[] = 'FULL';
if (null !== $count) {
array_push($this->options, 'COUNT', $count);
}
return $this;
}
/**
* {@inheritDoc}
*/
public function toArray(): array
{
return $this->options;
}
}
-8
View File
@@ -80,14 +80,6 @@ abstract class Command implements CommandInterface
return $data;
}
/**
* {@inheritdoc}
*/
public function parseResp3Response($data)
{
return $data;
}
/**
* Normalizes the arguments array passed to a Redis command.
*
-8
View File
@@ -77,12 +77,4 @@ interface CommandInterface
* @return mixed
*/
public function parseResponse($data);
/**
* Parses RESP3 protocol response and returns a PHP object.
*
* @param mixed $data
* @return mixed
*/
public function parseResp3Response($data);
}
-32
View File
@@ -1,32 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 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 string getName()
* @method Status kill(...$arguments)
* @method string list(string $type = null, int ...$clientId)
* @method Status noEvict(bool $enable = null)
* @method Status noTouch(bool $enable = null)
* @method Status setInfo(string $modifier = null, string $value = null)
* @method Status setName(string $connectionName)
*/
class CLIENT extends AbstractContainer
{
public function getContainerCommandId(): string
{
return 'CLIENT';
}
}
-30
View File
@@ -1,30 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 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 create(string $key, string $group, string $id, bool $mkStream = false, ?string $entriesRead = null)
* @method int createConsumer(string $key, string $group, string $consumer)
* @method int delConsumer(string $key, string $group, string $consumer)
* @method int destroy(string $key, string $group)
* @method Status setId(string $key, string $group, string $id, ?string $entriesRead = null)
*/
class XGROUP extends AbstractContainer
{
public function getContainerCommandId(): string
{
return 'xgroup';
}
}
-28
View File
@@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 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\Command\Argument\Stream\XInfoStreamOptions;
/**
* @method array consumers(string $key, string $group)
* @method array groups(string $key)
* @method array stream(string $key, XInfoStreamOptions $options = null)
*/
class XINFO extends AbstractContainer
{
public function getContainerCommandId(): string
{
return 'XINFO';
}
}
-111
View File
@@ -1,111 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 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;
abstract class PrefixableCommand extends Command implements PrefixableCommandInterface
{
/**
* {@inheritDoc}
*/
abstract public function getId();
/**
* {@inheritDoc}
*/
abstract public function prefixKeys($prefix);
/**
* Applies prefix for all arguments.
*
* @param string $prefix
* @return void
*/
public function applyPrefixForAllArguments(string $prefix): void
{
$this->setArguments(
array_map(static function ($key) use ($prefix) {
return $prefix . $key;
}, $this->getArguments())
);
}
/**
* Applies prefix for first argument.
*
* @param string $prefix
* @return void
*/
public function applyPrefixForFirstArgument(string $prefix): void
{
$arguments = $this->getArguments();
$arguments[0] = $prefix . $arguments[0];
$this->setArguments($arguments);
}
/**
* Applies prefix for interleaved arguments.
*
* @param string $prefix
* @return void
*/
public function applyPrefixForInterleavedArgument(string $prefix): void
{
if ($arguments = $this->getArguments()) {
$length = count($arguments);
for ($i = 0; $i < $length; $i += 2) {
$arguments[$i] = "$prefix{$arguments[$i]}";
}
$this->setRawArguments($arguments);
}
}
/**
* Applies prefix for all keys except last one.
*
* @param string $prefix
* @return void
*/
public function applyPrefixSkippingLastArgument(string $prefix): void
{
if ($arguments = $this->getArguments()) {
$length = count($arguments);
for ($i = 0; $i < $length - 1; ++$i) {
$arguments[$i] = "$prefix{$arguments[$i]}";
}
$this->setRawArguments($arguments);
}
}
/**
* Applies prefix for all keys except first one.
*
* @param string $prefix
* @return void
*/
public function applyPrefixSkippingFirstArgument(string $prefix): void
{
if ($arguments = $this->getArguments()) {
$length = count($arguments);
for ($i = 1; $i < $length; ++$i) {
$arguments[$i] = "$prefix{$arguments[$i]}";
}
$this->setRawArguments($arguments);
}
}
}
@@ -31,6 +31,270 @@ class KeyPrefixProcessor implements ProcessorInterface
public function __construct($prefix)
{
$this->prefix = $prefix;
$prefixFirst = static::class . '::first';
$prefixAll = static::class . '::all';
$prefixInterleaved = static::class . '::interleaved';
$prefixSkipFirst = static::class . '::skipFirst';
$prefixSkipLast = static::class . '::skipLast';
$prefixSort = static::class . '::sort';
$prefixEvalKeys = static::class . '::evalKeys';
$prefixZsetStore = static::class . '::zsetStore';
$prefixMigrate = static::class . '::migrate';
$prefixGeoradius = static::class . '::georadius';
$this->commands = [
/* ---------------- Redis 1.2 ---------------- */
'EXISTS' => $prefixAll,
'DEL' => $prefixAll,
'TYPE' => $prefixFirst,
'KEYS' => $prefixFirst,
'RENAME' => $prefixAll,
'RENAMENX' => $prefixAll,
'EXPIRE' => $prefixFirst,
'EXPIREAT' => $prefixFirst,
'TTL' => $prefixFirst,
'MOVE' => $prefixFirst,
'SORT' => $prefixSort,
'DUMP' => $prefixFirst,
'RESTORE' => $prefixFirst,
'SET' => $prefixFirst,
'SETNX' => $prefixFirst,
'MSET' => $prefixInterleaved,
'MSETNX' => $prefixInterleaved,
'GET' => $prefixFirst,
'MGET' => $prefixAll,
'GETSET' => $prefixFirst,
'INCR' => $prefixFirst,
'INCRBY' => $prefixFirst,
'DECR' => $prefixFirst,
'DECRBY' => $prefixFirst,
'RPUSH' => $prefixFirst,
'LPUSH' => $prefixFirst,
'LLEN' => $prefixFirst,
'LRANGE' => $prefixFirst,
'LTRIM' => $prefixFirst,
'LINDEX' => $prefixFirst,
'LSET' => $prefixFirst,
'LREM' => $prefixFirst,
'LPOP' => $prefixFirst,
'RPOP' => $prefixFirst,
'RPOPLPUSH' => $prefixAll,
'SADD' => $prefixFirst,
'SREM' => $prefixFirst,
'SPOP' => $prefixFirst,
'SMOVE' => $prefixSkipLast,
'SCARD' => $prefixFirst,
'SISMEMBER' => $prefixFirst,
'SINTER' => $prefixAll,
'SINTERSTORE' => $prefixAll,
'SUNION' => $prefixAll,
'SUNIONSTORE' => $prefixAll,
'SDIFF' => $prefixAll,
'SDIFFSTORE' => $prefixAll,
'SMEMBERS' => $prefixFirst,
'SRANDMEMBER' => $prefixFirst,
'ZADD' => $prefixFirst,
'ZINCRBY' => $prefixFirst,
'ZREM' => $prefixFirst,
'ZRANGE' => $prefixFirst,
'ZREVRANGE' => $prefixFirst,
'ZRANGEBYSCORE' => $prefixFirst,
'ZCARD' => $prefixFirst,
'ZSCORE' => $prefixFirst,
'ZREMRANGEBYSCORE' => $prefixFirst,
/* ---------------- Redis 2.0 ---------------- */
'SETEX' => $prefixFirst,
'APPEND' => $prefixFirst,
'SUBSTR' => $prefixFirst,
'BLPOP' => $prefixSkipLast,
'BRPOP' => $prefixSkipLast,
'ZUNIONSTORE' => $prefixZsetStore,
'ZINTERSTORE' => $prefixZsetStore,
'ZCOUNT' => $prefixFirst,
'ZRANK' => $prefixFirst,
'ZREVRANK' => $prefixFirst,
'ZREMRANGEBYRANK' => $prefixFirst,
'HSET' => $prefixFirst,
'HSETNX' => $prefixFirst,
'HMSET' => $prefixFirst,
'HINCRBY' => $prefixFirst,
'HGET' => $prefixFirst,
'HMGET' => $prefixFirst,
'HDEL' => $prefixFirst,
'HEXISTS' => $prefixFirst,
'HLEN' => $prefixFirst,
'HKEYS' => $prefixFirst,
'HVALS' => $prefixFirst,
'HGETALL' => $prefixFirst,
'SUBSCRIBE' => $prefixAll,
'UNSUBSCRIBE' => $prefixAll,
'PSUBSCRIBE' => $prefixAll,
'PUNSUBSCRIBE' => $prefixAll,
'PUBLISH' => $prefixFirst,
/* ---------------- Redis 2.2 ---------------- */
'PERSIST' => $prefixFirst,
'STRLEN' => $prefixFirst,
'SETRANGE' => $prefixFirst,
'GETRANGE' => $prefixFirst,
'SETBIT' => $prefixFirst,
'GETBIT' => $prefixFirst,
'RPUSHX' => $prefixFirst,
'LPUSHX' => $prefixFirst,
'LINSERT' => $prefixFirst,
'BRPOPLPUSH' => $prefixSkipLast,
'ZREVRANGEBYSCORE' => $prefixFirst,
'WATCH' => $prefixAll,
/* ---------------- Redis 2.6 ---------------- */
'PTTL' => $prefixFirst,
'PEXPIRE' => $prefixFirst,
'PEXPIREAT' => $prefixFirst,
'PSETEX' => $prefixFirst,
'INCRBYFLOAT' => $prefixFirst,
'BITOP' => $prefixSkipFirst,
'BITCOUNT' => $prefixFirst,
'HINCRBYFLOAT' => $prefixFirst,
'EVAL' => $prefixEvalKeys,
'EVALSHA' => $prefixEvalKeys,
'MIGRATE' => $prefixMigrate,
/* ---------------- Redis 2.8 ---------------- */
'SSCAN' => $prefixFirst,
'ZSCAN' => $prefixFirst,
'HSCAN' => $prefixFirst,
'PFADD' => $prefixFirst,
'PFCOUNT' => $prefixAll,
'PFMERGE' => $prefixAll,
'ZLEXCOUNT' => $prefixFirst,
'ZRANGEBYLEX' => $prefixFirst,
'ZREMRANGEBYLEX' => $prefixFirst,
'ZREVRANGEBYLEX' => $prefixFirst,
'BITPOS' => $prefixFirst,
/* ---------------- Redis 3.2 ---------------- */
'HSTRLEN' => $prefixFirst,
'BITFIELD' => $prefixFirst,
'GEOADD' => $prefixFirst,
'GEOHASH' => $prefixFirst,
'GEOPOS' => $prefixFirst,
'GEODIST' => $prefixFirst,
'GEORADIUS' => $prefixGeoradius,
'GEORADIUSBYMEMBER' => $prefixGeoradius,
/* ---------------- Redis 5.0 ---------------- */
'XADD' => $prefixFirst,
'XRANGE' => $prefixFirst,
'XREVRANGE' => $prefixFirst,
'XDEL' => $prefixFirst,
'XLEN' => $prefixFirst,
'XACK' => $prefixFirst,
'XTRIM' => $prefixFirst,
/* ---------------- Redis 6.2 ---------------- */
'GETDEL' => $prefixFirst,
/* ---------------- Redis 7.0 ---------------- */
'EXPIRETIME' => $prefixFirst,
/* RedisJSON */
'JSON.ARRAPPEND' => $prefixFirst,
'JSON.ARRINDEX' => $prefixFirst,
'JSON.ARRINSERT' => $prefixFirst,
'JSON.ARRLEN' => $prefixFirst,
'JSON.ARRPOP' => $prefixFirst,
'JSON.ARRTRIM' => $prefixFirst,
'JSON.CLEAR' => $prefixFirst,
'JSON.DEBUG MEMORY' => $prefixFirst,
'JSON.DEL' => $prefixFirst,
'JSON.FORGET' => $prefixFirst,
'JSON.GET' => $prefixFirst,
'JSON.MGET' => $prefixAll,
'JSON.NUMINCRBY' => $prefixFirst,
'JSON.OBJKEYS' => $prefixFirst,
'JSON.OBJLEN' => $prefixFirst,
'JSON.RESP' => $prefixFirst,
'JSON.SET' => $prefixFirst,
'JSON.STRAPPEND' => $prefixFirst,
'JSON.STRLEN' => $prefixFirst,
'JSON.TOGGLE' => $prefixFirst,
'JSON.TYPE' => $prefixFirst,
/* RedisBloom */
'BF.ADD' => $prefixFirst,
'BF.EXISTS' => $prefixFirst,
'BF.INFO' => $prefixFirst,
'BF.INSERT' => $prefixFirst,
'BF.LOADCHUNK' => $prefixFirst,
'BF.MADD' => $prefixFirst,
'BF.MEXISTS' => $prefixFirst,
'BF.RESERVE' => $prefixFirst,
'BF.SCANDUMP' => $prefixFirst,
'CF.ADD' => $prefixFirst,
'CF.ADDNX' => $prefixFirst,
'CF.COUNT' => $prefixFirst,
'CF.DEL' => $prefixFirst,
'CF.EXISTS' => $prefixFirst,
'CF.INFO' => $prefixFirst,
'CF.INSERT' => $prefixFirst,
'CF.INSERTNX' => $prefixFirst,
'CF.LOADCHUNK' => $prefixFirst,
'CF.MEXISTS' => $prefixFirst,
'CF.RESERVE' => $prefixFirst,
'CF.SCANDUMP' => $prefixFirst,
'CMS.INCRBY' => $prefixFirst,
'CMS.INFO' => $prefixFirst,
'CMS.INITBYDIM' => $prefixFirst,
'CMS.INITBYPROB' => $prefixFirst,
'CMS.QUERY' => $prefixFirst,
'TDIGEST.ADD' => $prefixFirst,
'TDIGEST.BYRANK' => $prefixFirst,
'TDIGEST.BYREVRANK' => $prefixFirst,
'TDIGEST.CDF' => $prefixFirst,
'TDIGEST.CREATE' => $prefixFirst,
'TDIGEST.INFO' => $prefixFirst,
'TDIGEST.MAX' => $prefixFirst,
'TDIGEST.MIN' => $prefixFirst,
'TDIGEST.QUANTILE' => $prefixFirst,
'TDIGEST.RANK' => $prefixFirst,
'TDIGEST.RESET' => $prefixFirst,
'TDIGEST.REVRANK' => $prefixFirst,
'TDIGEST.TRIMMED_MEAN' => $prefixFirst,
'TOPK.ADD' => $prefixFirst,
'TOPK.INCRBY' => $prefixFirst,
'TOPK.INFO' => $prefixFirst,
'TOPK.LIST' => $prefixFirst,
'TOPK.QUERY' => $prefixFirst,
'TOPK.RESERVE' => $prefixFirst,
/* RediSearch */
'FT.AGGREGATE' => $prefixFirst,
'FT.ALTER' => $prefixFirst,
'FT.CREATE' => $prefixFirst,
'FT.CURSOR DEL' => $prefixFirst,
'FT.CURSOR READ' => $prefixFirst,
'FT.DROPINDEX' => $prefixFirst,
'FT.EXPLAIN' => $prefixFirst,
'FT.INFO' => $prefixFirst,
'FT.PROFILE' => $prefixFirst,
'FT.SEARCH' => $prefixFirst,
'FT.SPELLCHECK' => $prefixFirst,
'FT.SYNDUMP' => $prefixFirst,
'FT.SYNUPDATE' => $prefixFirst,
'FT.TAGVALS' => $prefixFirst,
/* Redis TimeSeries */
'TS.ADD' => $prefixFirst,
'TS.ALTER' => $prefixFirst,
'TS.CREATE' => $prefixFirst,
'TS.DECRBY' => $prefixFirst,
'TS.DEL' => $prefixFirst,
'TS.GET' => $prefixFirst,
'TS.INCRBY' => $prefixFirst,
'TS.INFO' => $prefixFirst,
'TS.MGET' => $prefixFirst,
'TS.MRANGE' => $prefixFirst,
'TS.MREVRANGE' => $prefixFirst,
'TS.QUERYINDEX' => $prefixFirst,
'TS.RANGE' => $prefixFirst,
'TS.REVRANGE' => $prefixFirst,
];
}
/**
@@ -107,4 +371,207 @@ class KeyPrefixProcessor implements ProcessorInterface
{
return $this->getPrefix();
}
/**
* Applies the specified prefix only the first argument.
*
* @param CommandInterface $command Command instance.
* @param string $prefix Prefix string.
*/
public static function first(CommandInterface $command, $prefix)
{
if ($arguments = $command->getArguments()) {
$arguments[0] = "$prefix{$arguments[0]}";
$command->setRawArguments($arguments);
}
}
/**
* Applies the specified prefix to all the arguments.
*
* @param CommandInterface $command Command instance.
* @param string $prefix Prefix string.
*/
public static function all(CommandInterface $command, $prefix)
{
if ($arguments = $command->getArguments()) {
foreach ($arguments as &$key) {
$key = "$prefix$key";
}
$command->setRawArguments($arguments);
}
}
/**
* Applies the specified prefix only to even arguments in the list.
*
* @param CommandInterface $command Command instance.
* @param string $prefix Prefix string.
*/
public static function interleaved(CommandInterface $command, $prefix)
{
if ($arguments = $command->getArguments()) {
$length = count($arguments);
for ($i = 0; $i < $length; $i += 2) {
$arguments[$i] = "$prefix{$arguments[$i]}";
}
$command->setRawArguments($arguments);
}
}
/**
* Applies the specified prefix to all the arguments but the first one.
*
* @param CommandInterface $command Command instance.
* @param string $prefix Prefix string.
*/
public static function skipFirst(CommandInterface $command, $prefix)
{
if ($arguments = $command->getArguments()) {
$length = count($arguments);
for ($i = 1; $i < $length; ++$i) {
$arguments[$i] = "$prefix{$arguments[$i]}";
}
$command->setRawArguments($arguments);
}
}
/**
* Applies the specified prefix to all the arguments but the last one.
*
* @param CommandInterface $command Command instance.
* @param string $prefix Prefix string.
*/
public static function skipLast(CommandInterface $command, $prefix)
{
if ($arguments = $command->getArguments()) {
$length = count($arguments);
for ($i = 0; $i < $length - 1; ++$i) {
$arguments[$i] = "$prefix{$arguments[$i]}";
}
$command->setRawArguments($arguments);
}
}
/**
* Applies the specified prefix to the keys of a SORT command.
*
* @param CommandInterface $command Command instance.
* @param string $prefix Prefix string.
*/
public static function sort(CommandInterface $command, $prefix)
{
if ($arguments = $command->getArguments()) {
$arguments[0] = "$prefix{$arguments[0]}";
if (($count = count($arguments)) > 1) {
for ($i = 1; $i < $count; ++$i) {
switch (strtoupper($arguments[$i])) {
case 'BY':
case 'STORE':
$arguments[$i] = "$prefix{$arguments[++$i]}";
break;
case 'GET':
$value = $arguments[++$i];
if ($value !== '#') {
$arguments[$i] = "$prefix$value";
}
break;
case 'LIMIT':
$i += 2;
break;
}
}
}
$command->setRawArguments($arguments);
}
}
/**
* Applies the specified prefix to the keys of an EVAL-based command.
*
* @param CommandInterface $command Command instance.
* @param string $prefix Prefix string.
*/
public static function evalKeys(CommandInterface $command, $prefix)
{
if ($arguments = $command->getArguments()) {
for ($i = 2; $i < $arguments[1] + 2; ++$i) {
$arguments[$i] = "$prefix{$arguments[$i]}";
}
$command->setRawArguments($arguments);
}
}
/**
* Applies the specified prefix to the keys of Z[INTERSECTION|UNION]STORE.
*
* @param CommandInterface $command Command instance.
* @param string $prefix Prefix string.
*/
public static function zsetStore(CommandInterface $command, $prefix)
{
if ($arguments = $command->getArguments()) {
$arguments[0] = "$prefix{$arguments[0]}";
$length = ((int) $arguments[1]) + 2;
for ($i = 2; $i < $length; ++$i) {
$arguments[$i] = "$prefix{$arguments[$i]}";
}
$command->setRawArguments($arguments);
}
}
/**
* Applies the specified prefix to the key of a MIGRATE command.
*
* @param CommandInterface $command Command instance.
* @param string $prefix Prefix string.
*/
public static function migrate(CommandInterface $command, $prefix)
{
if ($arguments = $command->getArguments()) {
$arguments[2] = "$prefix{$arguments[2]}";
$command->setRawArguments($arguments);
}
}
/**
* Applies the specified prefix to the key of a GEORADIUS command.
*
* @param CommandInterface $command Command instance.
* @param string $prefix Prefix string.
*/
public static function georadius(CommandInterface $command, $prefix)
{
if ($arguments = $command->getArguments()) {
$arguments[0] = "$prefix{$arguments[0]}";
$startIndex = $command->getId() === 'GEORADIUS' ? 5 : 4;
if (($count = count($arguments)) > $startIndex) {
for ($i = $startIndex; $i < $count; ++$i) {
switch (strtoupper($arguments[$i])) {
case 'STORE':
case 'STOREDIST':
$arguments[$i] = "$prefix{$arguments[++$i]}";
break;
}
}
}
$command->setRawArguments($arguments);
}
}
}
-8
View File
@@ -120,12 +120,4 @@ final class RawCommand implements CommandInterface
{
return $data;
}
/**
* {@inheritdoc}
*/
public function parseResp3Response($data)
{
return $data;
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/append
@@ -26,9 +26,4 @@ class APPEND extends RedisCommand
{
return 'APPEND';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
@@ -40,13 +40,4 @@ abstract class BZPOPBase extends RedisCommand
return array_combine([$key], [[$data[0] => $data[1]]]);
}
/**
* @param $data
* @return array|false|mixed|null[]|string|null
*/
public function parseResp3Response($data)
{
return $this->parseResponse($data);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
use Predis\Command\Traits\BitByte;
/**
@@ -31,9 +31,4 @@ class BITCOUNT extends RedisCommand
{
return 'BITCOUNT';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/bitfield
@@ -26,9 +26,4 @@ class BITFIELD extends RedisCommand
{
return 'BITFIELD';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/bitop
@@ -40,9 +40,4 @@ class BITOP extends RedisCommand
parent::setArguments($arguments);
}
public function prefixKeys($prefix)
{
$this->applyPrefixSkippingFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
use Predis\Command\Traits\BitByte;
/**
@@ -31,9 +31,4 @@ class BITPOS extends RedisCommand
{
return 'BITPOS';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/blpop
@@ -39,9 +39,4 @@ class BLPOP extends RedisCommand
parent::setArguments($arguments);
}
public function prefixKeys($prefix)
{
$this->applyPrefixSkippingLastArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/brpop
@@ -39,9 +39,4 @@ class BRPOP extends RedisCommand
parent::setArguments($arguments);
}
public function prefixKeys($prefix)
{
$this->applyPrefixSkippingLastArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/brpoplpush
@@ -26,9 +26,4 @@ class BRPOPLPUSH extends RedisCommand
{
return 'BRPOPLPUSH';
}
public function prefixKeys($prefix)
{
$this->applyPrefixSkippingLastArgument($prefix);
}
}
-80
View File
@@ -30,77 +30,6 @@ class CLIENT extends RedisCommand
return 'CLIENT';
}
public function setArguments(array $arguments)
{
switch ($arguments[0]) {
case 'LIST':
$this->setListArguments($arguments);
break;
case 'NOEVICT':
$arguments[0] = 'NO-EVICT';
$this->setNoTouchArguments($arguments);
break;
case 'NOTOUCH':
$arguments[0] = 'NO-TOUCH';
$this->setNoTouchArguments($arguments);
break;
case 'SETINFO':
$this->setSetInfoArguments($arguments);
break;
default:
parent::setArguments($arguments);
}
}
private function setListArguments(array $arguments): void
{
$processedArguments = [$arguments[0]];
if (array_key_exists(1, $arguments) && null !== $arguments[1]) {
array_push($processedArguments, 'TYPE', strtoupper($arguments[1]));
}
if (array_key_exists(2, $arguments)) {
array_push($processedArguments, 'ID', $arguments[2]);
}
if (count($arguments) > 3) {
for ($i = 3, $iMax = count($arguments); $i < $iMax; $i++) {
$processedArguments[] = $arguments[$i];
}
}
parent::setArguments($processedArguments);
}
private function setNoTouchArguments(array $arguments): void
{
$processedArguments = [$arguments[0]];
if (array_key_exists(1, $arguments) && null !== $arguments[1]) {
$modifier = ($arguments[1]) ? 'ON' : 'OFF';
$processedArguments[] = $modifier;
}
parent::setArguments($processedArguments);
}
private function setSetInfoArguments(array $arguments): void
{
$processedArguments = [$arguments[0]];
if (
array_key_exists(1, $arguments)
&& null !== $arguments[1]
&& array_key_exists(2, $arguments)
&& null !== $arguments[2]
) {
array_push($processedArguments, strtoupper($arguments[1]), $arguments[2]);
}
parent::setArguments($processedArguments);
}
/**
* {@inheritdoc}
*/
@@ -143,13 +72,4 @@ class CLIENT extends RedisCommand
return $clients;
}
/**
* @param $data
* @return array|mixed|string|null
*/
public function parseResp3Response($data)
{
return $this->parseResponse($data);
}
}
@@ -12,17 +12,15 @@
namespace Predis\Command\Redis;
use Predis\Command\Command as RedisCommand;
/**
* Same as TFCALL command but executes in async mode.
* @see TFCALL
*
* In order to be used in cluster mode
* @see https://github.com/predis/predis#redis-gears-with-cluster
* @see https://redis.io/commands/?name=cluster
*/
class TFCALLASYNC extends TFCALL
class CLUSTER extends RedisCommand
{
public function getId()
{
return 'TFCALLASYNC';
return 'CLUSTER';
}
}
@@ -10,7 +10,7 @@
* file that was distributed with this source code.
*/
namespace Predis\Command\Container;
namespace Predis\Command\Redis\Container;
use Predis\Response\Status;
@@ -10,7 +10,7 @@
* file that was distributed with this source code.
*/
namespace Predis\Command\Container;
namespace Predis\Command\Redis\Container;
use Predis\ClientInterface;
@@ -10,19 +10,20 @@
* file that was distributed with this source code.
*/
namespace Predis\Command\Container;
namespace Predis\Command\Redis\Container;
use Predis\Response\Status;
/**
* @method Status load(string $libraryCode, bool $replace = false, string $config = null)
* @method Status delete(string $libraryName)
* @method array list(bool $withCode = false, int $verboseLevel = 0, string $libraryName = null)
* @method Status addSlotsRange(int ...$startEndSlots)
* @method Status delSlotsRange(int ...$startEndSlots)
* @method array links()
* @method array shards()
*/
class TFUNCTION extends AbstractContainer
class CLUSTER extends AbstractContainer
{
public function getContainerCommandId(): string
{
return 'TFUNCTION';
return 'CLUSTER';
}
}
@@ -10,7 +10,7 @@
* file that was distributed with this source code.
*/
namespace Predis\Command\Container;
namespace Predis\Command\Redis\Container;
use Predis\ClientConfiguration;
use Predis\ClientInterface;
@@ -18,7 +18,7 @@ use UnexpectedValueException;
class ContainerFactory
{
private const CONTAINER_NAMESPACE = "Predis\Command\Container";
private const CONTAINER_NAMESPACE = "Predis\Command\Redis\Container";
/**
* Mappings for class names that corresponds to PHP reserved words.
@@ -26,7 +26,7 @@ class ContainerFactory
* @var array
*/
private static $specialMappings = [
'FUNCTION' => FUNCTIONS::class,
'FUNCTION' => FunctionContainer::class,
];
/**
@@ -10,7 +10,7 @@
* file that was distributed with this source code.
*/
namespace Predis\Command\Container;
namespace Predis\Command\Redis\Container;
interface ContainerInterface
{
@@ -10,7 +10,7 @@
* file that was distributed with this source code.
*/
namespace Predis\Command\Container;
namespace Predis\Command\Redis\Container;
use Predis\Response\Status;
@@ -24,7 +24,7 @@ use Predis\Response\Status;
* @method Status restore(string $value, string $policy = null)
* @method array stats()
*/
class FUNCTIONS extends AbstractContainer
class FunctionContainer extends AbstractContainer
{
public function getContainerCommandId(): string
{
@@ -10,9 +10,9 @@
* file that was distributed with this source code.
*/
namespace Predis\Command\Container\Json;
namespace Predis\Command\Redis\Container\Json;
use Predis\Command\Container\AbstractContainer;
use Predis\Command\Redis\Container\AbstractContainer;
/**
* @method array memory(string $key, string $path)
@@ -10,9 +10,9 @@
* file that was distributed with this source code.
*/
namespace Predis\Command\Container\Search;
namespace Predis\Command\Redis\Container\Search;
use Predis\Command\Container\AbstractContainer;
use Predis\Command\Redis\Container\AbstractContainer;
use Predis\Response\Status;
/**
@@ -10,10 +10,10 @@
* file that was distributed with this source code.
*/
namespace Predis\Command\Container\Search;
namespace Predis\Command\Redis\Container\Search;
use Predis\Command\Argument\Search\CursorArguments;
use Predis\Command\Container\AbstractContainer;
use Predis\Command\Redis\Container\AbstractContainer;
use Predis\Response\Status;
/**
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/decr
@@ -26,9 +26,4 @@ class DECR extends RedisCommand
{
return 'DECR';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/decrby
@@ -26,9 +26,4 @@ class DECRBY extends RedisCommand
{
return 'DECRBY';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/del
@@ -36,9 +36,4 @@ class DEL extends RedisCommand
parent::setArguments($arguments);
}
public function prefixKeys($prefix)
{
$this->applyPrefixForAllArguments($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/dump
@@ -26,9 +26,4 @@ class DUMP extends RedisCommand
{
return 'DUMP';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -12
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/eval
@@ -36,15 +36,4 @@ class EVAL_ extends RedisCommand
{
return sha1($this->getArgument(0));
}
public function prefixKeys($prefix)
{
if ($arguments = $this->getArguments()) {
for ($i = 2; $i < $arguments[1] + 2; ++$i) {
$arguments[$i] = "$prefix{$arguments[$i]}";
}
$this->setRawArguments($arguments);
}
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/exists
@@ -26,9 +26,4 @@ class EXISTS extends RedisCommand
{
return 'EXISTS';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForAllArguments($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
use Predis\Command\Traits\Expire\ExpireOptions;
/**
@@ -33,9 +33,4 @@ class EXPIRE extends RedisCommand
{
return 'EXPIRE';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
use Predis\Command\Traits\Expire\ExpireOptions;
/**
@@ -32,9 +32,4 @@ class EXPIREAT extends RedisCommand
{
return 'EXPIREAT';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -16
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
use Predis\Command\Traits\Keys;
/**
@@ -30,19 +30,4 @@ class FCALL extends RedisCommand
{
return 'FCALL';
}
public function prefixKeys($prefix)
{
$arguments = $this->getArguments();
if (isset($arguments[1])) {
$numkeys = $arguments[1];
for ($i = 2; $i < $numkeys + 2; $i++) {
$arguments[$i] = $prefix . $arguments[$i];
}
}
$this->setRawArguments($arguments);
}
}
+15 -95
View File
@@ -13,6 +13,8 @@
namespace Predis\Command\Redis;
use Predis\Command\Command as RedisCommand;
use Predis\Command\Strategy\StrategyResolverInterface;
use Predis\Command\Strategy\SubcommandStrategyResolver;
/**
* @see https://redis.io/commands/?name=function
@@ -22,6 +24,16 @@ use Predis\Command\Command as RedisCommand;
*/
class FUNCTIONS extends RedisCommand
{
/**
* @var StrategyResolverInterface
*/
private $strategyResolver;
public function __construct()
{
$this->strategyResolver = new SubcommandStrategyResolver();
}
public function getId()
{
return 'FUNCTION';
@@ -29,102 +41,10 @@ class FUNCTIONS extends RedisCommand
public function setArguments(array $arguments)
{
switch ($arguments[0]) {
case 'FLUSH':
$this->setFlushArguments($arguments);
break;
case 'LIST':
$this->setListArguments($arguments);
break;
case 'LOAD':
$this->setLoadArguments($arguments);
break;
case 'RESTORE':
$this->setRestoreArguments($arguments);
break;
default:
parent::setArguments($arguments);
}
$strategy = $this->strategyResolver->resolve('functions', strtolower($arguments[0]));
$arguments = $strategy->processArguments($arguments);
parent::setArguments($arguments);
$this->filterArguments();
}
/**
* @param array $arguments
* @return void
*/
private function setFlushArguments(array $arguments): void
{
$processedArguments = [$arguments[0]];
if (array_key_exists(1, $arguments) && null !== $arguments[1]) {
$processedArguments[] = strtoupper($arguments[1]);
}
parent::setArguments($processedArguments);
}
/**
* @param array $arguments
* @return void
*/
private function setListArguments(array $arguments): void
{
$processedArguments = [$arguments[0]];
if (array_key_exists(1, $arguments) && null !== $arguments[1]) {
array_push($processedArguments, 'LIBRARYNAME', $arguments[1]);
}
if (array_key_exists(2, $arguments) && true === $arguments[2]) {
$processedArguments[] = 'WITHCODE';
}
parent::setArguments($processedArguments);
}
/**
* @param array $arguments
* @return void
*/
private function setLoadArguments(array $arguments): void
{
if (count($arguments) <= 2) {
parent::setArguments($arguments);
return;
}
$processedArguments = [$arguments[0]];
$replace = array_pop($arguments);
if (is_bool($replace) && $replace) {
$processedArguments[] = 'REPLACE';
} elseif (!is_bool($replace)) {
$processedArguments[] = $replace;
}
$processedArguments[] = $arguments[1];
parent::setArguments($processedArguments);
}
/**
* @param array $arguments
* @return void
*/
private function setRestoreArguments(array $arguments): void
{
$processedArguments = [$arguments[0], $arguments[1]];
if (array_key_exists(2, $arguments) && null !== $arguments[2]) {
$processedArguments[] = strtoupper($arguments[2]);
}
parent::setArguments($processedArguments);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/geoadd
@@ -40,9 +40,4 @@ class GEOADD extends RedisCommand
parent::setArguments($arguments);
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/geodist
@@ -26,9 +26,4 @@ class GEODIST extends RedisCommand
{
return 'GEODIST';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/geohash
@@ -39,9 +39,4 @@ class GEOHASH extends RedisCommand
parent::setArguments($arguments);
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/geopos
@@ -39,9 +39,4 @@ class GEOPOS extends RedisCommand
parent::setArguments($arguments);
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -22
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @deprecated As of Redis version 6.2.0, this command is regarded as deprecated.
@@ -74,25 +74,4 @@ class GEORADIUS extends RedisCommand
parent::setArguments($arguments);
}
public function prefixKeys($prefix)
{
if ($arguments = $this->getArguments()) {
$arguments[0] = "$prefix{$arguments[0]}";
$startIndex = $this->getId() === 'GEORADIUS' ? 5 : 4;
if (($count = count($arguments)) > $startIndex) {
for ($i = $startIndex; $i < $count; ++$i) {
switch (strtoupper($arguments[$i])) {
case 'STORE':
case 'STOREDIST':
$arguments[$i] = "$prefix{$arguments[++$i]}";
break;
}
}
}
$this->setRawArguments($arguments);
}
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/get
@@ -26,9 +26,4 @@ class GET extends RedisCommand
{
return 'GET';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/getbit
@@ -26,9 +26,4 @@ class GETBIT extends RedisCommand
{
return 'GETBIT';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/getrange
@@ -26,9 +26,4 @@ class GETRANGE extends RedisCommand
{
return 'GETRANGE';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/getset
@@ -26,9 +26,4 @@ class GETSET extends RedisCommand
{
return 'GETSET';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/hdel
@@ -36,9 +36,4 @@ class HDEL extends RedisCommand
parent::setArguments($arguments);
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/hexists
@@ -26,9 +26,4 @@ class HEXISTS extends RedisCommand
{
return 'HEXISTS';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/hget
@@ -26,9 +26,4 @@ class HGET extends RedisCommand
{
return 'HGET';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/hgetall
@@ -44,9 +44,4 @@ class HGETALL extends RedisCommand
return $result;
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/hincrby
@@ -26,9 +26,4 @@ class HINCRBY extends RedisCommand
{
return 'HINCRBY';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/hincrbyfloat
@@ -26,9 +26,4 @@ class HINCRBYFLOAT extends RedisCommand
{
return 'HINCRBYFLOAT';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/hkeys
@@ -26,9 +26,4 @@ class HKEYS extends RedisCommand
{
return 'HKEYS';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/hlen
@@ -26,9 +26,4 @@ class HLEN extends RedisCommand
{
return 'HLEN';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/hmget
@@ -36,9 +36,4 @@ class HMGET extends RedisCommand
parent::setArguments($arguments);
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/hmset
@@ -46,9 +46,4 @@ class HMSET extends RedisCommand
parent::setArguments($arguments);
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -15
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/hscan
@@ -83,18 +83,4 @@ class HSCAN extends RedisCommand
return $data;
}
/**
* @param $data
* @return array|mixed|string|null
*/
public function parseResp3Response($data)
{
return $this->parseResponse($data);
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/hset
@@ -26,9 +26,4 @@ class HSET extends RedisCommand
{
return 'HSET';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/hsetnx
@@ -26,9 +26,4 @@ class HSETNX extends RedisCommand
{
return 'HSETNX';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/hstrlen
@@ -26,9 +26,4 @@ class HSTRLEN extends RedisCommand
{
return 'HSTRLEN';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/hvals
@@ -26,9 +26,4 @@ class HVALS extends RedisCommand
{
return 'HVALS';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/incr
@@ -26,9 +26,4 @@ class INCR extends RedisCommand
{
return 'INCR';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/incrby
@@ -26,9 +26,4 @@ class INCRBY extends RedisCommand
{
return 'INCRBY';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/incrbyfloat
@@ -26,9 +26,4 @@ class INCRBYFLOAT extends RedisCommand
{
return 'INCRBYFLOAT';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}
-9
View File
@@ -154,13 +154,4 @@ class INFO extends RedisCommand
return $parsedData;
}
/**
* @param $data
* @return array|mixed|string|null
*/
public function parseResp3Response($data)
{
return $this->parseResponse($data);
}
}
+1 -6
View File
@@ -12,7 +12,7 @@
namespace Predis\Command\Redis;
use Predis\Command\PrefixableCommand as RedisCommand;
use Predis\Command\Command as RedisCommand;
/**
* @see http://redis.io/commands/keys
@@ -26,9 +26,4 @@ class KEYS extends RedisCommand
{
return 'KEYS';
}
public function prefixKeys($prefix)
{
$this->applyPrefixForFirstArgument($prefix);
}
}

Some files were not shown because too many files have changed in this diff Show More