Compare commits

..

5 Commits

Author SHA1 Message Date
vladvildanov ebdd22ff61 Added this PR to changelog 2025-03-20 15:01:28 +02:00
vladvildanov 25b33f50ae Merge branch 'vv-added-missing-types' of github.com:predis/predis into vv-added-missing-types 2025-03-20 15:00:36 +02:00
vladvildanov 3864a7b125 Updated CHANGELOG.md 2025-03-20 15:00:21 +02:00
Vladyslav Vildanov 6f4ac2a012 Merge branch 'v2.x' into vv-added-missing-types 2025-03-20 14:45:42 +02:00
vladvildanov 72f6baef26 Added missing types for commands API 2025-03-20 14:44:36 +02:00
22 changed files with 123 additions and 1072 deletions
-29
View File
@@ -165,32 +165,3 @@ jobs:
- name: Search for misspellings
run: $(python -m site --user-base)/bin/codespell
changelog:
name: Changelog
runs-on: ubuntu-latest
timeout-minutes: 5
if: >-
github.event_name == 'pull_request' &&
!contains(github.event.head_commit.message, 'nochangelog') &&
!contains(github.event.head_commit.message, 'no-changelog') &&
!contains(github.event.head_commit.message, 'no changelog') &&
!contains(github.event.pull_request.labels.*.name, 'no-changelog')
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check for CHANGELOG entry
env:
TARGET: ${{ github.event.pull_request.base.ref }}
run: |
FILES_CHANGED=$(git diff --name-only origin/$TARGET...HEAD | grep -E 'CHANGELOG\.md' -c)
if [ "$FILES_CHANGED" != "1" ]; then
echo "CHANGELOG.md was not updated";
exit 1;
fi;
+1 -1
View File
@@ -38,7 +38,7 @@ jobs:
run: |
# Mapping of original redis versions to client test containers
declare -A redis_clients_version_mapping=(
["8.0"]="8.0-RC2-pre"
["8.0"]="8.0-M04-pre"
["7.4"]="7.4.2"
["7.2"]="7.2.7"
["6.2"]="6.2.17"
+12 -20
View File
@@ -1,30 +1,22 @@
## Changelog
## v2.4.1 (2025-11-12)
## Unreleased
### Fixed
- Fixed return type for `ZCOUNT` to be `int` (#1546)
- Removed automatic `conn_uid` parameter assignment (#1551)
## v2.4.0 (2025-04-30)
### Added
- Added new hash-field expiration commands (#1520)
- Added missing `FT._LIST` and `BITFIELD_RO` commands (#1521)
### Changed
- Update `WATCH` command to accept `string|string[]` (#1476)
- Optimize cluster slotmap with compact slot range object (#1493)
### Fixed
- Fixed `EVAL_RO` cluster support (#1449)
- Fixed PHP 8.4 compatibility with `stream_context_set_option()` (#1503)
- Prevent named arguments runtime failure (#1509)
- Mark `GEOSEARCH` as read-only to ensure execution on replica (#1481)
- Fixed protocol loss during redis cluster `MOVED` / `ASK` (#1530)
- Mark GEOSEARCH as read-only to ensure execution on replica (#1481)
- Fix eval_ro cluster support (#1449)
### Maintenance
- Added CI testing with Redis 8.0 (#1510)
- Added test coverage for compatibility with Redis 8.0 (#1513)
### Changed
- Use parallel on PHP-CS-Fixer (#1489)
- Update watch command accepting string and string[] (#1476)
- Optimize redis cluster slotmap with compact slot range object (#1493)
### Added
- Added testing with 8.0 (#1510)
- Added test coverage for compatibility with Redis 8.0 (#1513)
- Added missing FT._LIST and BITFIELD_RO commands (#1521)
- Added missing types for commands API (#1522)
## v2.3.0 (2024-11-21)
### Added
+1 -45
View File
@@ -14,7 +14,7 @@ More details about this project can be found on the [frequently asked questions]
## Main features ##
- Support for Redis from __3.0__ to __8.0__.
- Support for Redis from __3.0__ to __7.4__.
- Support for clustering using client-side sharding and pluggable keyspace distributors.
- Support for [redis-cluster](http://redis.io/topics/cluster-tutorial) (Redis >= 3.0).
- Support for master-slave replication setups and [redis-sentinel](http://redis.io/topics/sentinel).
@@ -138,50 +138,6 @@ it is still desired to have control of when the connection is opened or closed:
achieved by invoking `$client->connect()` and `$client->disconnect()`. Please note that the effect
of these methods on aggregate connections may differ depending on each specific implementation.
#### Persistent connections ####
To increase a performance of your application you may set up a client to use persistent TCP connection, this way
client saves a time on socket creation and connection handshake. By default, connection is created on first-command
execution and will be automatically closed by GC before the process is being killed.
However, if your application is backed by PHP-FPM the processes are idle, and you may set up it to be persistent and
reusable across multiple script execution within the same process.
To enable the persistent connection mode you should provide following configuration:
```php
// Standalone
$client = new Predis\Client(['persistent' => true]);
// Cluster
$client = new Predis\Client(
['tcp://host:port', 'tcp://host:port', 'tcp://host:port'],
['cluster' => 'redis', 'parameters' => ['persistent' => true]]
);
```
**Important**
If you operate on multiple clients within the same application, and they communicate with the same resource, by default
they will share the same socket (that's the default behaviour of persistent sockets). So in this case you would need
to additionally provide a `conn_uid` identifier for each client, this way each client will create its own socket so
the connection context won't be shared across clients. This socket behaviour explained
[here](https://www.php.net/manual/en/function.stream-socket-client.php#105393)
```php
// Standalone
$client1 = new Predis\Client(['persistent' => true, 'conn_uid' => 'id_1']);
$client2 = new Predis\Client(['persistent' => true, 'conn_uid' => 'id_2']);
// Cluster
$client1 = new Predis\Client(
['tcp://host:port', 'tcp://host:port', 'tcp://host:port'],
['cluster' => 'redis', 'parameters' => ['persistent' => true, 'conn_uid' => 'id_1']]
);
$client2 = new Predis\Client(
['tcp://host:port', 'tcp://host:port', 'tcp://host:port'],
['cluster' => 'redis', 'parameters' => ['persistent' => true, 'conn_uid' => 'id_2']]
);
```
### Client configuration ###
+1 -1
View File
@@ -1 +1 @@
2.4.0
2.3.1-dev
+1 -1
View File
@@ -53,7 +53,7 @@ use Traversable;
*/
class Client implements ClientInterface, IteratorAggregate
{
public const VERSION = '2.4.2-dev';
public const VERSION = '2.3.1-dev';
/** @var OptionsInterface */
private $options;
+48 -53
View File
@@ -44,8 +44,6 @@ use Predis\Command\Redis\Container\FunctionContainer;
use Predis\Command\Redis\Container\Json\JSONDEBUG;
use Predis\Command\Redis\Container\Search\FTCONFIG;
use Predis\Command\Redis\Container\Search\FTCURSOR;
use Predis\Command\Redis\HGETEX;
use Predis\Command\Redis\HSETEX;
/**
* Interface defining a client-side context such as a pipeline or transaction.
@@ -59,7 +57,7 @@ use Predis\Command\Redis\HSETEX;
* @method $this expiretime(string $key)
* @method $this keys($pattern)
* @method $this move($key, $db)
* @method $this object($subcommand, $key)
* @method $this object(string $subcommand, string $key)
* @method $this persist($key)
* @method $this pexpire($key, $milliseconds)
* @method $this pexpireat($key, $timestamp)
@@ -67,37 +65,37 @@ use Predis\Command\Redis\HSETEX;
* @method $this randomkey()
* @method $this rename($key, $target)
* @method $this renamenx($key, $target)
* @method $this scan($cursor, ?array $options = null)
* @method $this scan(int|string $cursor, ?array $options = null)
* @method $this sort($key, ?array $options = null)
* @method $this sort_ro(string $key, ?string $byPattern = null, ?LimitOffsetCount $limit = null, array $getPatterns = [], ?string $sorting = null, bool $alpha = false)
* @method $this ttl($key)
* @method $this type($key)
* @method $this append($key, $value)
* @method $this bfadd(string $key, $item)
* @method $this bfexists(string $key, $item)
* @method $this bfadd(string $key, string $item)
* @method $this bfexists(string $key, string $item)
* @method $this bfinfo(string $key, string $modifier = '')
* @method $this bfinsert(string $key, int $capacity = -1, float $error = -1, int $expansion = -1, bool $noCreate = false, bool $nonScaling = false, string ...$item)
* @method $this bfloadchunk(string $key, int $iterator, $data)
* @method $this bfmadd(string $key, ...$item)
* @method $this bfmexists(string $key, ...$item)
* @method $this bfmadd(string $key, string ...$item)
* @method $this bfmexists(string $key, string ...$item)
* @method $this bfreserve(string $key, float $errorRate, int $capacity, int $expansion = -1, bool $nonScaling = false)
* @method $this bfscandump(string $key, int $iterator)
* @method $this bitcount(string $key, $start = null, $end = null, string $index = 'byte')
* @method $this bitop($operation, $destkey, $key)
* @method $this bitfield($key, $subcommand, ...$subcommandArg)
* @method $this bitop(string $operation, string $destkey, string $key)
* @method $this bitfield($key, string $subcommand, ...$subcommandArg)
* @method $this bitfield_ro(string $key, ?array $encodingOffsetMap = null)
* @method $this bitpos($key, $bit, $start = null, $end = null, string $index = 'byte')
* @method $this bitpos(string $key, int $bit, ?int $start = null, ?int $end = null, string $index = 'byte')
* @method $this blmpop(int $timeout, array $keys, string $modifier = 'left', int $count = 1)
* @method $this bzpopmax(array $keys, int $timeout)
* @method $this bzpopmin(array $keys, int $timeout)
* @method $this bzmpop(int $timeout, array $keys, string $modifier = 'min', int $count = 1)
* @method $this cfadd(string $key, $item)
* @method $this cfaddnx(string $key, $item)
* @method $this cfcount(string $key, $item)
* @method $this cfdel(string $key, $item)
* @method $this cfexists(string $key, $item)
* @method $this cfadd(string $key, string $item)
* @method $this cfaddnx(string $key, string $item)
* @method $this cfcount(string $key, string $item)
* @method $this cfdel(string $key, string $item)
* @method $this cfexists(string $key, string $item)
* @method $this cfloadchunk(string $key, int $iterator, $data)
* @method $this cfmexists(string $key, ...$item)
* @method $this cfmexists(string $key, string ...$item)
* @method $this cfinfo(string $key)
* @method $this cfinsert(string $key, int $capacity = -1, bool $noCreate = false, string ...$item)
* @method $this cfinsertnx(string $key, int $capacity = -1, bool $noCreate = false, string ...$item)
@@ -121,8 +119,8 @@ use Predis\Command\Redis\HSETEX;
* @method $this ftaliasupdate(string $alias, string $index)
* @method $this ftalter(string $index, FieldInterface[] $schema, ?AlterArguments $arguments = null)
* @method $this ftcreate(string $index, FieldInterface[] $schema, ?CreateArguments $arguments = null)
* @method $this ftdictadd(string $dict, ...$term)
* @method $this ftdictdel(string $dict, ...$term)
* @method $this ftdictadd(string $dict, string ...$term)
* @method $this ftdictdel(string $dict, string ...$term)
* @method $this ftdictdump(string $dict)
* @method $this ftdropindex(string $index, ?DropArguments $arguments = null)
* @method $this ftexplain(string $index, string $query, ?ExplainArguments $arguments = null)
@@ -138,23 +136,23 @@ use Predis\Command\Redis\HSETEX;
* @method $this ftsynupdate(string $index, string $synonymGroupId, ?SynUpdateArguments $arguments = null, string ...$terms)
* @method $this fttagvals(string $index, string $fieldName)
* @method $this get($key)
* @method $this getbit($key, $offset)
* @method $this getex(string $key, $modifier = '', $value = false)
* @method $this getrange($key, $start, $end)
* @method $this getbit(string $key, int $offset)
* @method $this getex(string $key, string $modifier = '', string|int $value = false)
* @method $this getrange(string $key, int $start, int $end)
* @method $this getdel(string $key)
* @method $this getset($key, $value)
* @method $this getset(string $key, string|int|float $value)
* @method $this incr($key)
* @method $this incrby($key, $increment)
* @method $this incrbyfloat($key, $increment)
* @method $this mget(array $keys)
* @method $this mset(array $dictionary)
* @method $this msetnx(array $dictionary)
* @method $this psetex($key, $milliseconds, $value)
* @method $this set($key, $value, $expireResolution = null, $expireTTL = null, $flag = null)
* @method $this setbit($key, $offset, $value)
* @method $this setex($key, $seconds, $value)
* @method $this setnx($key, $value)
* @method $this setrange($key, $offset, $value)
* @method $this psetex(string $key, int $milliseconds, string|int|float $value)
* @method $this set(string $key, string|int|float $value, ?string $expireResolution = null, ?int $expireTTL = null, ?string $flag = null)
* @method $this setbit(string $key, int $offset, string|int|float $value)
* @method $this setex(string $key, int $seconds, string|int|float $value)
* @method $this setnx(string $key, string|int|float $value)
* @method $this setrange(string $key, int $offset, string|int|float $value)
* @method $this strlen($key)
* @method $this hdel($key, array $fields)
* @method $this hexists($key, $field)
@@ -166,9 +164,7 @@ use Predis\Command\Redis\HSETEX;
* @method $this hpexpireat(string $key, int $unixTimeMilliseconds, array $fields, string $flag = null)
* @method $this hpexpiretime(string $key, array $fields)
* @method $this hget($key, $field)
* @method $this hgetex(string $key, array $fields, string $modifier = HGETEX::NULL)
* @method $this hgetall($key)
* @method $this hgetdel(string $key, array $fields)
* @method $this hincrby($key, $field, $increment)
* @method $this hincrbyfloat($key, $field, $increment)
* @method $this hkeys($key)
@@ -176,15 +172,14 @@ use Predis\Command\Redis\HSETEX;
* @method $this hmget($key, array $fields)
* @method $this hmset($key, array $dictionary)
* @method $this hrandfield(string $key, int $count = 1, bool $withValues = false)
* @method $this hscan($key, $cursor, ?array $options = null)
* @method $this hscan(string $key, int|string $cursor, ?array $options = null)
* @method $this hset($key, $field, $value)
* @method $this hsetex(string $key, array $fieldValueMap, string $setModifier = HSETEX::SET_NULL, string $ttlModifier = HSETEX::TTL_NULL, int|bool $ttlModifierValue = false)
* @method $this hsetnx($key, $field, $value)
* @method $this httl(string $key, array $fields)
* @method $this hpttl(string $key, array $fields)
* @method $this hvals($key)
* @method $this hstrlen($key, $field)
* @method $this jsonarrappend(string $key, string $path = '$', ...$value)
* @method $this jsonarrappend(string $key, string $path = '$', string ...$value)
* @method $this jsonarrindex(string $key, string $path, string $value, int $start = 0, int $stop = 0)
* @method $this jsonarrinsert(string $key, string $path, int $index, string ...$value)
* @method $this jsonarrlen(string $key, string $path = '$')
@@ -212,7 +207,7 @@ use Predis\Command\Redis\HSETEX;
* @method $this brpoplpush($source, $destination, $timeout)
* @method $this lcs(string $key1, string $key2, bool $len = false, bool $idx = false, int $minMatchLen = 0, bool $withMatchLen = false)
* @method $this lindex($key, $index)
* @method $this linsert($key, $whence, $pivot, $value)
* @method $this linsert(string $key, string $whence, string|int|float $pivot, string|int|float $value)
* @method $this llen($key)
* @method $this lmove(string $source, string $destination, string $where, string $to)
* @method $this lmpop(array $keys, string $modifier = 'left', int $count = 1)
@@ -258,11 +253,11 @@ use Predis\Command\Redis\HSETEX;
* @method $this tdigestreset(string $key)
* @method $this tdigestrevrank(string $key, float ...$value)
* @method $this tdigesttrimmed_mean(string $key, float $lowCutQuantile, float $highCutQuantile)
* @method $this topkadd(string $key, ...$items)
* @method $this topkincrby(string $key, ...$itemIncrement)
* @method $this topkadd(string $key, string ...$items)
* @method $this topkincrby(string $key, string|int|float ...$itemIncrement)
* @method $this topkinfo(string $key)
* @method $this topklist(string $key, bool $withCount = false)
* @method $this topkquery(string $key, ...$items)
* @method $this topkquery(string $key, string ...$items)
* @method $this topkreserve(string $key, int $topK, int $width = 8, int $depth = 7, float $decay = 0.9)
* @method $this tsadd(string $key, int $timestamp, float $value, ?AddArguments $arguments = null)
* @method $this tsalter(string $key, ?TSAlterArguments $arguments = null)
@@ -276,11 +271,11 @@ use Predis\Command\Redis\HSETEX;
* @method $this tsinfo(string $key, ?InfoArguments $arguments = null)
* @method $this tsmadd(mixed ...$keyTimestampValue)
* @method $this tsmget(MGetArguments $arguments, string ...$filterExpression)
* @method $this tsmrange($fromTimestamp, $toTimestamp, MRangeArguments $arguments)
* @method $this tsmrevrange($fromTimestamp, $toTimestamp, MRangeArguments $arguments)
* @method $this tsmrange(string|int|float $fromTimestamp, string|int|float $toTimestamp, MRangeArguments $arguments)
* @method $this tsmrevrange(string|int|float $fromTimestamp, string|int|float $toTimestamp, MRangeArguments $arguments)
* @method $this tsqueryindex(string ...$filterExpression)
* @method $this tsrange(string $key, $fromTimestamp, $toTimestamp, ?RangeArguments $arguments = null)
* @method $this tsrevrange(string $key, $fromTimestamp, $toTimestamp, ?RangeArguments $arguments = null)
* @method $this tsrange(string $key, string|int|float $fromTimestamp, string|int|float $toTimestamp, ?RangeArguments $arguments = null)
* @method $this tsrevrange(string $key, string|int|float $fromTimestamp, string|int|float $toTimestamp, ?RangeArguments $arguments = null)
* @method $this zadd($key, array $membersAndScoresDictionary)
* @method $this zcard($key)
* @method $this zcount($key, $min, $max)
@@ -315,8 +310,8 @@ use Predis\Command\Redis\HSETEX;
* @method $this pfadd($key, array $elements)
* @method $this pfmerge($destinationKey, array|string $sourceKeys)
* @method $this pfcount(array|string $keys)
* @method $this pubsub($subcommand, $argument)
* @method $this publish($channel, $message)
* @method $this pubsub(string $subcommand, string|int|float $argument)
* @method $this publish(string $channel, string|int|float $message)
* @method $this discard()
* @method $this exec()
* @method $this multi()
@@ -327,7 +322,7 @@ use Predis\Command\Redis\HSETEX;
* @method $this eval_ro(string $script, array $keys, ...$argument)
* @method $this evalsha($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
* @method $this evalsha_ro(string $sha1, array $keys, ...$argument)
* @method $this script($subcommand, $argument = null)
* @method $this script(string $subcommand, $argument = null)
* @method $this shutdown(?bool $noSave = null, bool $now = false, bool $force = false, bool $abort = false)
* @method $this auth($password)
* @method $this echo($message)
@@ -335,24 +330,24 @@ use Predis\Command\Redis\HSETEX;
* @method $this select($database)
* @method $this bgrewriteaof()
* @method $this bgsave()
* @method $this client($subcommand, $argument = null)
* @method $this config($subcommand, $argument = null)
* @method $this client(string $subcommand, $argument = null)
* @method $this config(string $subcommand, $argument = null)
* @method $this dbsize()
* @method $this flushall()
* @method $this flushdb()
* @method $this info($section = null)
* @method $this info(?string $section = null)
* @method $this lastsave()
* @method $this save()
* @method $this slaveof($host, $port)
* @method $this slowlog($subcommand, $argument = null)
* @method $this slowlog(string $subcommand, $argument = null)
* @method $this time()
* @method $this command()
* @method $this geoadd($key, $longitude, $latitude, $member)
* @method $this geoadd(string $key, string|float $longitude, string|float $latitude, string $member)
* @method $this geohash($key, array $members)
* @method $this geopos($key, array $members)
* @method $this geodist($key, $member1, $member2, $unit = null)
* @method $this georadius($key, $longitude, $latitude, $radius, $unit, ?array $options = null)
* @method $this georadiusbymember($key, $member, $radius, $unit, ?array $options = null)
* @method $this geodist(string $key, string $member1, string $member2, string $unit = null)
* @method $this georadius(string $key, string|float $longitude, string|float $latitude, int $radius, string $unit, ?array $options = null)
* @method $this georadiusbymember(string $key, string $member, int $radius, string $unit, ?array $options = null)
* @method $this geosearch(string $key, FromInterface $from, ByInterface $by, ?string $sorting = null, int $count = -1, bool $any = false, bool $withCoord = false, bool $withDist = false, bool $withHash = false)
* @method $this geosearchstore(string $destination, string $source, FromInterface $from, ByInterface $by, ?string $sorting = null, int $count = -1, bool $any = false, bool $storeDist = false)
*
+49 -54
View File
@@ -45,8 +45,6 @@ use Predis\Command\Redis\Container\FunctionContainer;
use Predis\Command\Redis\Container\Json\JSONDEBUG;
use Predis\Command\Redis\Container\Search\FTCONFIG;
use Predis\Command\Redis\Container\Search\FTCURSOR;
use Predis\Command\Redis\HGETEX;
use Predis\Command\Redis\HSETEX;
use Predis\Configuration\OptionsInterface;
use Predis\Connection\ConnectionInterface;
use Predis\Response\Status;
@@ -68,7 +66,7 @@ use Predis\Response\Status;
* @method int expiretime(string $key)
* @method array keys(string $pattern)
* @method int move(string $key, int $db)
* @method mixed object($subcommand, string $key)
* @method mixed object(string $subcommand, string $key)
* @method int persist(string $key)
* @method int pexpire(string $key, int $milliseconds)
* @method int pexpireat(string $key, int $timestamp)
@@ -76,37 +74,37 @@ use Predis\Response\Status;
* @method string|null randomkey()
* @method mixed rename(string $key, string $target)
* @method int renamenx(string $key, string $target)
* @method array scan($cursor, ?array $options = null)
* @method array scan(int|string $cursor, ?array $options = null)
* @method array sort(string $key, ?array $options = null)
* @method array sort_ro(string $key, ?string $byPattern = null, ?LimitOffsetCount $limit = null, array $getPatterns = [], ?string $sorting = null, bool $alpha = false)
* @method int ttl(string $key)
* @method mixed type(string $key)
* @method int append(string $key, $value)
* @method int bfadd(string $key, $item)
* @method int bfexists(string $key, $item)
* @method int bfadd(string $key, string $item)
* @method int bfexists(string $key, string $item)
* @method array bfinfo(string $key, string $modifier = '')
* @method array bfinsert(string $key, int $capacity = -1, float $error = -1, int $expansion = -1, bool $noCreate = false, bool $nonScaling = false, string ...$item)
* @method Status bfloadchunk(string $key, int $iterator, $data)
* @method array bfmadd(string $key, ...$item)
* @method array bfmexists(string $key, ...$item)
* @method array bfmadd(string $key, string ...$item)
* @method array bfmexists(string $key, string ...$item)
* @method Status bfreserve(string $key, float $errorRate, int $capacity, int $expansion = -1, bool $nonScaling = false)
* @method array bfscandump(string $key, int $iterator)
* @method int bitcount(string $key, $start = null, $end = null, string $index = 'byte')
* @method int bitop($operation, $destkey, $key)
* @method array|null bitfield(string $key, $subcommand, ...$subcommandArg)
* @method int bitop(string $operation, string $destkey, string $key)
* @method array|null bitfield(string $key, string $subcommand, ...$subcommandArg)
* @method array|null bitfield_ro(string $key, ?array $encodingOffsetMap = null)
* @method int bitpos(string $key, $bit, $start = null, $end = null, string $index = 'byte')
* @method int bitpos(string $key, int $bit, ?int $start = null, ?int $end = null, string $index = 'byte')
* @method array blmpop(int $timeout, array $keys, string $modifier = 'left', int $count = 1)
* @method array bzpopmax(array $keys, int $timeout)
* @method array bzpopmin(array $keys, int $timeout)
* @method array bzmpop(int $timeout, array $keys, string $modifier = 'min', int $count = 1)
* @method int cfadd(string $key, $item)
* @method int cfaddnx(string $key, $item)
* @method int cfcount(string $key, $item)
* @method int cfdel(string $key, $item)
* @method int cfexists(string $key, $item)
* @method int cfadd(string $key, string $item)
* @method int cfaddnx(string $key, string $item)
* @method int cfcount(string $key, string $item)
* @method int cfdel(string $key, string $item)
* @method int cfexists(string $key, string $item)
* @method Status cfloadchunk(string $key, int $iterator, $data)
* @method int cfmexists(string $key, ...$item)
* @method int cfmexists(string $key, string ...$item)
* @method array cfinfo(string $key)
* @method array cfinsert(string $key, int $capacity = -1, bool $noCreate = false, string ...$item)
* @method array cfinsertnx(string $key, int $capacity = -1, bool $noCreate = false, string ...$item)
@@ -130,8 +128,8 @@ use Predis\Response\Status;
* @method Status ftaliasupdate(string $alias, string $index)
* @method Status ftalter(string $index, FieldInterface[] $schema, ?AlterArguments $arguments = null)
* @method Status ftcreate(string $index, FieldInterface[] $schema, ?CreateArguments $arguments = null)
* @method int ftdictadd(string $dict, ...$term)
* @method int ftdictdel(string $dict, ...$term)
* @method int ftdictadd(string $dict, string ...$term)
* @method int ftdictdel(string $dict, string ...$term)
* @method array ftdictdump(string $dict)
* @method Status ftdropindex(string $index, ?DropArguments $arguments = null)
* @method string ftexplain(string $index, string $query, ?ExplainArguments $arguments = null)
@@ -147,23 +145,23 @@ use Predis\Response\Status;
* @method Status ftsynupdate(string $index, string $synonymGroupId, ?SynUpdateArguments $arguments = null, string ...$terms)
* @method array fttagvals(string $index, string $fieldName)
* @method string|null get(string $key)
* @method int getbit(string $key, $offset)
* @method int|null getex(string $key, $modifier = '', $value = false)
* @method string getrange(string $key, $start, $end)
* @method int getbit(string $key, int $offset)
* @method int|null getex(string $key, string $modifier = '', int|string $value = false)
* @method string getrange(string $key, int $start, int $end)
* @method string getdel(string $key)
* @method string|null getset(string $key, $value)
* @method string|null getset(string $key, string|int|float $value)
* @method int incr(string $key)
* @method int incrby(string $key, int $increment)
* @method string incrbyfloat(string $key, int|float $increment)
* @method array mget(string[]|string $keyOrKeys, string ...$keys = null)
* @method mixed mset(array $dictionary)
* @method int msetnx(array $dictionary)
* @method Status psetex(string $key, $milliseconds, $value)
* @method Status|null set(string $key, $value, $expireResolution = null, $expireTTL = null, $flag = null)
* @method int setbit(string $key, $offset, $value)
* @method Status setex(string $key, $seconds, $value)
* @method int setnx(string $key, $value)
* @method int setrange(string $key, $offset, $value)
* @method Status psetex(string $key, int $milliseconds, string|int|float $value)
* @method Status|null set(string $key, string|int|float $value, ?string $expireResolution = null, ?int $expireTTL = null, ?string $flag = null)
* @method int setbit(string $key, int $offset, string|int|float $value)
* @method Status setex(string $key, int $seconds, string|int|float $value)
* @method int setnx(string $key, string|int|float $value)
* @method int setrange(string $key, int $offset, string|int|float $value)
* @method int strlen(string $key)
* @method int hdel(string $key, array $fields)
* @method int hexists(string $key, string $field)
@@ -175,9 +173,7 @@ use Predis\Response\Status;
* @method array|null hpexpireat(string $key, int $unixTimeMilliseconds, array $fields, string $flag = null)
* @method array|null hpexpiretime(string $key, array $fields)
* @method string|null hget(string $key, string $field)
* @method array|null hgetex(string $key, array $fields, string $modifier = HGETEX::NULL, int|bool $modifierValue = false)
* @method array hgetall(string $key)
* @method array hgetdel(string $key, array $fields)
* @method int hincrby(string $key, string $field, int $increment)
* @method string hincrbyfloat(string $key, string $field, int|float $increment)
* @method array hkeys(string $key)
@@ -185,15 +181,14 @@ use Predis\Response\Status;
* @method array hmget(string $key, array $fields)
* @method mixed hmset(string $key, array $dictionary)
* @method array hrandfield(string $key, int $count = 1, bool $withValues = false)
* @method array hscan(string $key, $cursor, ?array $options = null)
* @method array hscan(string $key, int|string $cursor, ?array $options = null)
* @method int hset(string $key, string $field, string $value)
* @method int hsetex(string $key, array $fieldValueMap, string $setModifier = HSETEX::SET_NULL, string $ttlModifier = HSETEX::TTL_NULL, int|bool $ttlModifierValue = false)
* @method int hsetnx(string $key, string $field, string $value)
* @method array|null httl(string $key, array $fields)
* @method array|null hpttl(string $key, array $fields)
* @method array hvals(string $key)
* @method int hstrlen(string $key, string $field)
* @method array jsonarrappend(string $key, string $path = '$', ...$value)
* @method array jsonarrappend(string $key, string $path = '$', string ...$value)
* @method array jsonarrindex(string $key, string $path, string $value, int $start = 0, int $stop = 0)
* @method array jsonarrinsert(string $key, string $path, int $index, string ...$value)
* @method array jsonarrlen(string $key, string $path = '$')
@@ -221,7 +216,7 @@ use Predis\Response\Status;
* @method string|null brpoplpush(string $source, string $destination, int|float $timeout)
* @method mixed lcs(string $key1, string $key2, bool $len = false, bool $idx = false, int $minMatchLen = 0, bool $withMatchLen = false)
* @method string|null lindex(string $key, int $index)
* @method int linsert(string $key, $whence, $pivot, $value)
* @method int linsert(string $key, string $whence, string|int|float $pivot, string|int|float $value)
* @method int llen(string $key)
* @method string lmove(string $source, string $destination, string $where, string $to)
* @method array|null lmpop(array $keys, string $modifier = 'left', int $count = 1)
@@ -268,11 +263,11 @@ use Predis\Response\Status;
* @method Status tdigestreset(string $key)
* @method array tdigestrevrank(string $key, float ...$value)
* @method string tdigesttrimmed_mean(string $key, float $lowCutQuantile, float $highCutQuantile)
* @method array topkadd(string $key, ...$items)
* @method array topkincrby(string $key, ...$itemIncrement)
* @method array topkadd(string $key, string ...$items)
* @method array topkincrby(string $key, string|int|float ...$itemIncrement)
* @method array topkinfo(string $key)
* @method array topklist(string $key, bool $withCount = false)
* @method array topkquery(string $key, ...$items)
* @method array topkquery(string $key, string|int|float ...$items)
* @method Status topkreserve(string $key, int $topK, int $width = 8, int $depth = 7, float $decay = 0.9)
* @method int tsadd(string $key, int $timestamp, float $value, ?AddArguments $arguments = null)
* @method Status tsalter(string $key, ?TSAlterArguments $arguments = null)
@@ -286,11 +281,11 @@ use Predis\Response\Status;
* @method array tsinfo(string $key, ?InfoArguments $arguments = null)
* @method array tsmadd(mixed ...$keyTimestampValue)
* @method array tsmget(MGetArguments $arguments, string ...$filterExpression)
* @method array tsmrange($fromTimestamp, $toTimestamp, MRangeArguments $arguments)
* @method array tsmrevrange($fromTimestamp, $toTimestamp, MRangeArguments $arguments)
* @method array tsmrange(string|int|float $fromTimestamp, string|int|float $toTimestamp, MRangeArguments $arguments)
* @method array tsmrevrange(string|int|float $fromTimestamp, string|int|float $toTimestamp, MRangeArguments $arguments)
* @method array tsqueryindex(string ...$filterExpression)
* @method array tsrange(string $key, $fromTimestamp, $toTimestamp, ?RangeArguments $arguments = null)
* @method array tsrevrange(string $key, $fromTimestamp, $toTimestamp, ?RangeArguments $arguments = null)
* @method array tsrange(string $key, string|int|float $fromTimestamp, string|int|float $toTimestamp, ?RangeArguments $arguments = null)
* @method array tsrevrange(string $key, string|int|float $fromTimestamp, string|int|float $toTimestamp, ?RangeArguments $arguments = null)
* @method string xadd(string $key, array $dictionary, string $id = '*', ?array $options = null)
* @method int xdel(string $key, string ...$id)
* @method int xlen(string $key)
@@ -300,7 +295,7 @@ use Predis\Response\Status;
* @method array|null xread(int $count = null, int $block = null, array $streams = null, string ...$id)
* @method int zadd(string $key, array $membersAndScoresDictionary)
* @method int zcard(string $key)
* @method int zcount(string $key, int|string $min, int|string $max)
* @method string zcount(string $key, int|string $min, int|string $max)
* @method array zdiff(array $keys, bool $withScores = false)
* @method int zdiffstore(string $destination, array $keys)
* @method string zincrby(string $key, int $increment, string $member)
@@ -334,8 +329,8 @@ use Predis\Response\Status;
* @method int pfadd(string $key, array $elements)
* @method mixed pfmerge(string $destinationKey, array|string $sourceKeys)
* @method int pfcount(string[]|string $keyOrKeys, string ...$keys = null)
* @method mixed pubsub($subcommand, $argument)
* @method int publish($channel, $message)
* @method mixed pubsub(string $subcommand, string|int|float $argument)
* @method int publish(string $channel, string|int|float $message)
* @method mixed discard()
* @method array|null exec()
* @method mixed multi()
@@ -346,7 +341,7 @@ use Predis\Response\Status;
* @method mixed eval_ro(string $script, array $keys, ...$argument)
* @method mixed evalsha(string $script, int $numkeys, string ...$keyOrArg = null)
* @method mixed evalsha_ro(string $sha1, array $keys, ...$argument)
* @method mixed script($subcommand, $argument = null)
* @method mixed script(string $subcommand, $argument = null)
* @method Status shutdown(?bool $noSave = null, bool $now = false, bool $force = false, bool $abort = false)
* @method mixed auth(string $password)
* @method string echo(string $message)
@@ -354,24 +349,24 @@ use Predis\Response\Status;
* @method mixed select(int $database)
* @method mixed bgrewriteaof()
* @method mixed bgsave()
* @method mixed client($subcommand, $argument = null)
* @method mixed config($subcommand, $argument = null)
* @method mixed client(string $subcommand, $argument = null)
* @method mixed config(string $subcommand, $argument = null)
* @method int dbsize()
* @method mixed flushall()
* @method mixed flushdb()
* @method array info($section = null)
* @method array info(?string $section = null)
* @method int lastsave()
* @method mixed save()
* @method mixed slaveof(string $host, int $port)
* @method mixed slowlog($subcommand, $argument = null)
* @method mixed slowlog(string $subcommand, $argument = null)
* @method array time()
* @method array command()
* @method int geoadd(string $key, $longitude, $latitude, $member)
* @method int geoadd(string $key, string|float $longitude, string|float $latitude, string $member)
* @method array geohash(string $key, array $members)
* @method array geopos(string $key, array $members)
* @method string|null geodist(string $key, $member1, $member2, $unit = null)
* @method array georadius(string $key, $longitude, $latitude, $radius, $unit, ?array $options = null)
* @method array georadiusbymember(string $key, $member, $radius, $unit, ?array $options = null)
* @method string|null geodist(string $key, string $member1, string $member2, string $unit = null)
* @method array georadius(string $key, string|float $longitude, string|float $latitude, int $radius, string $unit, ?array $options = null)
* @method array georadiusbymember(string $key, string $member, int $radius, string $unit, ?array $options = null)
* @method array geosearch(string $key, FromInterface $from, ByInterface $by, ?string $sorting = null, int $count = -1, bool $any = false, bool $withCoord = false, bool $withDist = false, bool $withHash = false)
* @method int geosearchstore(string $destination, string $source, FromInterface $from, ByInterface $by, ?string $sorting = null, int $count = -1, bool $any = false, bool $storeDist = false)
*
-35
View File
@@ -1,35 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Redis;
use Predis\Command\Command as RedisCommand;
class HGETDEL extends RedisCommand
{
public function getId()
{
return 'HGETDEL';
}
/**
* @param array $arguments
* @return void
*/
public function setArguments(array $arguments)
{
$processedArguments = [$arguments[0], 'FIELDS', count($arguments[1])];
$processedArguments = array_merge($processedArguments, $arguments[1]);
parent::setArguments($processedArguments);
}
}
-81
View File
@@ -1,81 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Redis;
use Predis\Command\Command as RedisCommand;
use UnexpectedValueException;
class HGETEX extends RedisCommand
{
public const NULL = '';
public const EX = 'ex';
public const PX = 'px';
public const EXAT = 'exat';
public const PXAT = 'pxat';
public const PERSIST = 'persist';
/**
* @var string[]
*/
private static $modifierEnum = [
self::EX => 'EX',
self::PX => 'PX',
self::EXAT => 'EXAT',
self::PXAT => 'PXAT',
self::PERSIST => 'PERSIST',
];
public function getId()
{
return 'HGETEX';
}
public function setArguments(array $arguments)
{
$processedArguments = [$arguments[0]];
// Only required arguments
if (!array_key_exists(2, $arguments) || $arguments[2] == '') {
array_push($processedArguments, 'FIELDS', count($arguments[1]));
$processedArguments = array_merge($processedArguments, $arguments[1]);
parent::setArguments($processedArguments);
return;
}
if (!in_array(strtoupper($arguments[2]), self::$modifierEnum)) {
$enumValues = implode(', ', array_keys(self::$modifierEnum));
throw new UnexpectedValueException("Modifier argument accepts only: {$enumValues} values");
}
// PERSIST requires no additional value
if (strtoupper($arguments[2]) === self::$modifierEnum['persist']) {
$processedArguments[] = self::$modifierEnum['persist'];
array_push($processedArguments, 'FIELDS', count($arguments[1]));
$processedArguments = array_merge($processedArguments, $arguments[1]);
parent::setArguments($processedArguments);
return;
}
if (!array_key_exists(3, $arguments) || !is_int($arguments[3])) {
throw new UnexpectedValueException('Modifier value is missing or incorrect type');
}
// Order matters so FIELDS should be at the end
array_push($processedArguments, self::$modifierEnum[strtolower($arguments[2])], $arguments[3], 'FIELDS', count($arguments[1]));
$processedArguments = array_merge($processedArguments, $arguments[1]);
parent::setArguments($processedArguments);
}
}
-117
View File
@@ -1,117 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Redis;
use Predis\Command\Command as RedisCommand;
use UnexpectedValueException;
class HSETEX extends RedisCommand
{
public const TTL_NULL = '';
public const TTL_EX = 'ex';
public const TTL_PX = 'px';
public const TTL_EXAT = 'exat';
public const TTL_PXAT = 'pxat';
public const TTL_KEEP_TTL = 'keepttl';
public const SET_NULL = '';
public const SET_FNX = 'fnx';
public const SET_FXX = 'fxx';
/**
* @var string[]
*/
private static $ttlModifierEnum = [
self::TTL_EX => 'EX',
self::TTL_PX => 'PX',
self::TTL_EXAT => 'EXAT',
self::TTL_PXAT => 'PXAT',
self::TTL_KEEP_TTL => 'KEEPTTL',
];
/**
* @var string[]
*/
private static $setModifierEnum = [
self::SET_FNX => 'FNX',
self::SET_FXX => 'FXX',
];
public function getId()
{
return 'HSETEX';
}
public function setArguments(array $arguments)
{
$processedArguments = [$arguments[0]];
$flatArray = [];
// Convert key => value, into key, value
array_walk($arguments[1], function ($value, $key) use (&$flatArray) {
array_push($flatArray, $key, $value);
});
// Only required arguments
if (!array_key_exists(2, $arguments)) {
array_push($processedArguments, 'FIELDS', count($flatArray) / 2);
$processedArguments = array_merge($processedArguments, $flatArray);
parent::setArguments($processedArguments);
return;
}
if ($arguments[2] !== '') {
if (!in_array(strtoupper($arguments[2]), self::$setModifierEnum)) {
$enumValues = implode(', ', array_keys(self::$setModifierEnum));
throw new UnexpectedValueException("Modifier argument accepts only: {$enumValues} values");
}
$processedArguments[] = self::$setModifierEnum[strtolower($arguments[2])];
}
// Required + set modifier
if (!array_key_exists(3, $arguments) || $arguments[3] == '') {
array_push($processedArguments, 'FIELDS', count($flatArray) / 2);
$processedArguments = array_merge($processedArguments, $flatArray);
parent::setArguments($processedArguments);
return;
}
if (!in_array(strtoupper($arguments[3]), self::$ttlModifierEnum)) {
$enumValues = implode(', ', array_keys(self::$ttlModifierEnum));
throw new UnexpectedValueException("Modifier argument accepts only: {$enumValues} values");
}
// KEEPTTL requires no additional value
if (strtoupper($arguments[3]) === self::$ttlModifierEnum[self::TTL_KEEP_TTL]) {
$processedArguments[] = self::$ttlModifierEnum[self::TTL_KEEP_TTL];
array_push($processedArguments, 'FIELDS', count($flatArray) / 2);
$processedArguments = array_merge($processedArguments, $flatArray);
parent::setArguments($processedArguments);
return;
}
if (!array_key_exists(4, $arguments) || !is_int($arguments[4])) {
throw new UnexpectedValueException('Modifier value is missing or incorrect type');
}
// Order matters so FIELDS should be at the end
array_push($processedArguments, self::$ttlModifierEnum[strtolower($arguments[3])], $arguments[4], 'FIELDS', count($flatArray) / 2);
$processedArguments = array_merge($processedArguments, $flatArray);
parent::setArguments($processedArguments);
}
}
+3 -12
View File
@@ -254,7 +254,7 @@ class RedisCluster implements ClusterInterface, IteratorAggregate, Countable
}
if (!$connection = $this->getRandomConnection()) {
throw new ClientException('No connections left in the pool for `CLUSTER SLOTS` (' . $exception->getMessage() . ')');
throw new ClientException('No connections left in the pool for `CLUSTER SLOTS`');
}
usleep($retryAfter * 1000);
@@ -337,19 +337,10 @@ class RedisCluster implements ClusterInterface, IteratorAggregate, Countable
{
$separator = strrpos($connectionID, ':');
$parameters = [
return $this->connections->create([
'host' => substr($connectionID, 0, $separator),
'port' => substr($connectionID, $separator + 1),
];
$existConnection = current($this->pool);
if ($existConnection instanceof NodeConnectionInterface) {
$existParameters = $existConnection->getParameters()->toArray();
unset($existParameters['alias'], $existParameters['slots']);
$parameters = array_merge($existParameters, $parameters);
}
return $this->connections->create($parameters);
]);
}
/**
+1
View File
@@ -41,6 +41,7 @@ class StreamConnection extends AbstractConnection
public function __construct(ParametersInterface $parameters)
{
parent::__construct($parameters);
$this->parameters->conn_uid = spl_object_hash($this);
}
/**
+4 -22
View File
@@ -1285,35 +1285,17 @@ class ClientTest extends PredisTestCase
/**
* @group connected
* @requiresRedisVersion >= 5.0.0
*/
public function testClientsCreateDifferentPersistentConnections(): void
{
$client1 = new Client($this->getParameters(['database' => 14, 'persistent' => true, 'conn_uid' => 1]));
$client2 = new Client($this->getParameters(['database' => 15, 'persistent' => true, 'conn_uid' => 2]));
$client1 = new Client($this->getParameters(['database' => 14, 'persistent' => true]));
$client2 = new Client($this->getParameters(['database' => 15, 'persistent' => true]));
$client1->set('foo', 'bar');
$client2->set('foo', 'baz');
$this->assertSame('bar', $client1->get('foo'));
$this->assertSame('baz', $client2->get('foo'));
$this->assertNotSame($client1->client('ID'), $client2->client('ID'));
}
/**
* @group connected
* @requiresRedisVersion >= 5.0.0
*/
public function testClientsCreateSamePersistentConnections(): void
{
$client1 = new Client($this->getParameters(['persistent' => true]));
$client2 = new Client($this->getParameters(['persistent' => true]));
$client1->set('foo', 'bar');
$client2->set('foo', 'baz');
$this->assertSame('baz', $client2->get('foo'));
$this->assertSame($client1->client('ID'), $client2->client('ID'));
}
/**
@@ -1325,11 +1307,11 @@ class ClientTest extends PredisTestCase
{
$client1 = new Client(
$this->getDefaultParametersArray(),
['cluster' => 'redis', 'parameters' => ['persistent' => true, 'conn_uid' => 1]]
['cluster' => 'redis', 'parameters' => ['persistent' => true]]
);
$client2 = new Client(
$this->getDefaultParametersArray(),
['cluster' => 'redis', 'parameters' => ['persistent' => true, 'conn_uid' => 2]]
['cluster' => 'redis', 'parameters' => ['persistent' => true]]
);
$client1->set('{shard1}foo', 'bar');
@@ -1008,14 +1008,6 @@ class KeyPrefixProcessorTest extends PredisTestCase
['key', 'MAXLEN', 100],
['prefix:key', 'MAXLEN', 100],
],
['ZPOPMIN',
['key'],
['prefix:key'],
],
['ZPOPMAX',
['key'],
['prefix:key'],
],
/* ---------------- Redis 6.2 ---------------- */
['GETDEL',
['key'],
@@ -1,69 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Redis;
class HGETDEL_Test extends PredisCommandTestCase
{
/**
* {@inheritDoc}
*/
protected function getExpectedCommand(): string
{
return HGETDEL::class;
}
/**
* {@inheritDoc}
*/
protected function getExpectedId(): string
{
return 'HGETDEL';
}
/**
* @group disconnected
*/
public function testFilterArguments(): void
{
$command = $this->getCommand();
$command->setArguments(['key', ['field1', 'field2']]);
$this->assertSame(['key', 'FIELDS', 2, 'field1', 'field2'], $command->getArguments());
}
/**
* @group disconnected
*/
public function testParseResponse(): void
{
$command = $this->getCommand();
$this->assertSame(0, $command->parseResponse(0));
$this->assertSame(1, $command->parseResponse(1));
}
/**
* @group connected
* @return void
* @requiresRedisVersion >= 7.9.0
*/
public function testReturnsAndRemoveFieldsFromHash(): void
{
$redis = $this->getClient();
$redis->hset('hashkey', 'field1', 'value1', 'field2', 'value2', 'field3', 'value3');
$this->assertSame(['value1', 'value2'], $redis->hgetdel('hashkey', ['field1', 'field2']));
$this->assertSame(['field3' => 'value3'], $redis->hgetall('hashkey'));
}
}
-193
View File
@@ -1,193 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Redis;
use UnexpectedValueException;
class HGETEX_Test extends PredisCommandTestCase
{
/**
* {@inheritdoc}
*/
protected function getExpectedCommand(): string
{
return HGETEX::class;
}
/**
* {@inheritdoc}
*/
protected function getExpectedId(): string
{
return 'HGETEX';
}
/**
* @group disconnected
* @dataProvider argumentsProvider
*/
public function testFilterArguments(array $actualArguments, array $expectedArguments): void
{
$command = $this->getCommand();
$command->setArguments($actualArguments);
$this->assertSame($expectedArguments, $command->getArguments());
}
/**
* @group disconnected
*/
public function testParseResponse(): void
{
$command = $this->getCommand();
$this->assertSame(1, $command->parseResponse(1));
}
/**
* @group connected
* @dataProvider hashProvider
* @param array $hash
* @param array $arguments
* @param array $expectedResponse
* @param float $timeout
* @return void
* @requiresRedisVersion >= 7.9.0
*/
public function testReturnsValueAndSetExpirationTimeForGivenHash(
array $hash,
array $arguments,
array $expectedResponse,
float $timeout
): void {
$redis = $this->getClient();
$redis->hset(...$hash);
$this->assertSame($expectedResponse, $redis->hgetex(...$arguments));
$this->sleep($timeout);
$this->assertSame([], $redis->hgetall('hash_key'));
}
/**
* @group connected
* @return void
* @requiresRedisVersion >= 7.9.0
*/
public function testRemovesAssociatedTTLFromHash()
{
$redis = $this->getClient();
$redis->hsetex(
'hash_key', ['field1' => 'value1'],
HSETEX::SET_NULL, HSETEX::TTL_EX, 100
);
$this->assertGreaterThan(0, $redis->hexpiretime('hash_key', ['field1'])[0]);
$redis->hgetex('hash_key', ['field1'], HGETEX::PERSIST);
$this->assertEquals(-1, $redis->hexpiretime('hash_key', ['field1'])[0]);
}
/**
* @group connected
* @dataProvider unexpectedValuesProvider
* @param array $arguments
* @param string $expectedExceptionMessage
* @return void
*/
public function testThrowsExceptionOnUnexpectedValueGiven(
array $arguments,
string $expectedExceptionMessage
): void {
$redis = $this->getClient();
$this->expectException(UnexpectedValueException::class);
$this->expectExceptionMessage($expectedExceptionMessage);
$redis->hgetex(...$arguments);
}
public function argumentsProvider(): array
{
return [
'with default arguments' => [
['key', ['field1', 'field2']],
['key', 'FIELDS', 2, 'field1', 'field2'],
],
'with EX modifier' => [
['key', ['field1', 'field2'], HGETEX::EX, 10],
['key', 'EX', 10, 'FIELDS', 2, 'field1', 'field2'],
],
'with PX modifier' => [
['key', ['field1', 'field2'], HGETEX::PX, 10],
['key', 'PX', 10, 'FIELDS', 2, 'field1', 'field2'],
],
'with EXAT modifier' => [
['key', ['field1', 'field2'], HGETEX::EXAT, 10],
['key', 'EXAT', 10, 'FIELDS', 2, 'field1', 'field2'],
],
'with PXAT modifier' => [
['key', ['field1', 'field2'], HGETEX::PXAT, 10],
['key', 'PXAT', 10, 'FIELDS', 2, 'field1', 'field2'],
],
'with PERSIST modifier' => [
['key', ['field1', 'field2'], HGETEX::PERSIST],
['key', 'PERSIST', 'FIELDS', 2, 'field1', 'field2'],
],
];
}
public function hashProvider(): array
{
return [
'with expiration - EX modifier' => [
['hash_key', 'field1', 'value1', 'field2', 'value2'],
['hash_key', ['field1', 'field2'], HGETEX::EX, 1],
['value1', 'value2'],
1.2,
],
'with expiration - PX modifier' => [
['hash_key', 'field1', 'value1', 'field2', 'value2'],
['hash_key', ['field1', 'field2'], HGETEX::PX, 100],
['value1', 'value2'],
0.2,
],
'with expiration - EXAT modifier' => [
['hash_key', 'field1', 'value1', 'field2', 'value2'],
['hash_key', ['field1', 'field2'], HGETEX::EXAT, time() + 1],
['value1', 'value2'],
2,
],
'with expiration - PXAT modifier' => [
['hash_key', 'field1', 'value1', 'field2', 'value2'],
['hash_key', ['field1', 'field2'], HGETEX::PXAT, (time() * 1000) + 100],
['value1', 'value2'],
0.3,
],
];
}
public function unexpectedValuesProvider(): array
{
return [
'with wrong modifier' => [
['key', ['field1', 'field2'], 'wrong', 10],
'Modifier argument accepts only: ex, px, exat, pxat, persist values',
],
'with wrong type value' => [
['key', ['field1', 'field2'], 'ex', true],
'Modifier value is missing or incorrect type',
],
];
}
}
-257
View File
@@ -1,257 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2025 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Redis;
use UnexpectedValueException;
class HSETEX_Test extends PredisCommandTestCase
{
/**
* {@inheritdoc}
*/
protected function getExpectedCommand(): string
{
return HSETEX::class;
}
/**
* {@inheritdoc}
*/
protected function getExpectedId(): string
{
return 'HSETEX';
}
/**
* @group disconnected
* @dataProvider argumentsProvider
*/
public function testFilterArguments(array $actualArguments, array $expectedArguments): void
{
$command = $this->getCommand();
$command->setArguments($actualArguments);
$this->assertSame($expectedArguments, $command->getArguments());
}
/**
* @group connected
* @group slow
* @dataProvider hashProvider
* @param array $arguments
* @param int $expectedResponse
* @param float $timeout
* @return void
* @requiresRedisVersion >= 7.9.0
*/
public function testSetHashWithExpiration(
array $arguments,
int $expectedResponse,
float $timeout
): void {
$redis = $this->getClient();
$this->assertSame($expectedResponse, $redis->hsetex(...$arguments));
$this->sleep($timeout);
$this->assertSame([], $redis->hgetall('hash_key'));
}
/**
* @group connected
* @return void
* @requiresRedisVersion >= 7.9.0
*/
public function testSetHashFieldsIfNotExists(): void
{
$redis = $this->getClient();
$this->assertSame(
1,
$redis->hsetex('hash_key', ['field1' => 'value1', 'field2' => 'value2'], HSETEX::SET_FNX)
);
$this->assertSame(
0,
$redis->hsetex('hash_key', ['field1' => 'value1', 'field2' => 'value2'], HSETEX::SET_FNX)
);
}
/**
* @group connected
* @return void
* @requiresRedisVersion >= 7.9.0
*/
public function testSetHashFieldsOnlyIfExists(): void
{
$redis = $this->getClient();
$this->assertSame(
0,
$redis->hsetex('hash_key', ['field1' => 'value1', 'field2' => 'value2'], HSETEX::SET_FXX)
);
$this->assertSame(
1,
$redis->hsetex('hash_key', ['field1' => 'value1', 'field2' => 'value2'], HSETEX::SET_FNX)
);
$this->assertSame(
1,
$redis->hsetex('hash_key', ['field1' => 'value1', 'field2' => 'value2'], HSETEX::SET_FXX)
);
}
/**
* @group connected
* @return void
* @requiresRedisVersion >= 7.9.0
*/
public function testSetHashFieldRetainingTTLValue(): void
{
$redis = $this->getClient();
$this->assertSame(
1,
$redis->hsetex(
'hash_key',
['field1' => 'value1', 'field2' => 'value2'],
HSETEX::SET_FNX,
HSETEX::TTL_EX,
100
)
);
$this->assertGreaterThan(0, $redis->hexpiretime('hash_key', ['field1'])[0]);
$this->assertSame(
1,
$redis->hsetex(
'hash_key',
['field1' => 'value1'],
HSETEX::SET_FXX,
HSETEX::TTL_KEEP_TTL
)
);
$this->assertGreaterThan(0, $redis->hexpiretime('hash_key', ['field1'])[0]);
}
/**
* @group connected
* @dataProvider unexpectedValuesProvider
* @param array $arguments
* @param string $expectedExceptionMessage
* @return void
*/
public function testThrowsExceptionOnUnexpectedValueGiven(
array $arguments,
string $expectedExceptionMessage
): void {
$redis = $this->getClient();
$this->expectException(UnexpectedValueException::class);
$this->expectExceptionMessage($expectedExceptionMessage);
$redis->hsetex(...$arguments);
}
public function argumentsProvider(): array
{
return [
'with default arguments' => [
['key', ['field1' => 'value1', 'field2' => 'value2']],
['key', 'FIELDS', 2, 'field1', 'value1', 'field2', 'value2'],
],
'with FNX modifier' => [
['key', ['field1' => 'value1', 'field2' => 'value2'], HSETEX::SET_FNX],
['key', 'FNX', 'FIELDS', 2, 'field1', 'value1', 'field2', 'value2'],
],
'with FXX modifier' => [
['key', ['field1' => 'value1', 'field2' => 'value2'], HSETEX::SET_FXX],
['key', 'FXX', 'FIELDS', 2, 'field1', 'value1', 'field2', 'value2'],
],
'with EX modifier' => [
['key', ['field1' => 'value1', 'field2' => 'value2'], HSETEX::SET_NULL, HSETEX::TTL_EX, 10],
['key', 'EX', 10, 'FIELDS', 2, 'field1', 'value1', 'field2', 'value2'],
],
'with PX modifier' => [
['key', ['field1' => 'value1', 'field2' => 'value2'], HSETEX::SET_NULL, HSETEX::TTL_PX, 10],
['key', 'PX', 10, 'FIELDS', 2, 'field1', 'value1', 'field2', 'value2'],
],
'with EXAT modifier' => [
['key', ['field1' => 'value1', 'field2' => 'value2'], HSETEX::SET_NULL, HSETEX::TTL_EXAT, 10],
['key', 'EXAT', 10, 'FIELDS', 2, 'field1', 'value1', 'field2', 'value2'],
],
'with PXAT modifier' => [
['key', ['field1' => 'value1', 'field2' => 'value2'], HSETEX::SET_NULL, HSETEX::TTL_PXAT, 10],
['key', 'PXAT', 10, 'FIELDS', 2, 'field1', 'value1', 'field2', 'value2'],
],
'with KEEPTTL modifier' => [
['key', ['field1' => 'value1', 'field2' => 'value2'], HSETEX::SET_NULL, HSETEX::TTL_KEEP_TTL],
['key', 'KEEPTTL', 'FIELDS', 2, 'field1', 'value1', 'field2', 'value2'],
],
'with combined modifiers' => [
['key', ['field1' => 'value1', 'field2' => 'value2'], HSETEX::SET_FXX, HSETEX::TTL_PXAT, 10],
['key', 'FXX', 'PXAT', 10, 'FIELDS', 2, 'field1', 'value1', 'field2', 'value2'],
],
];
}
public function hashProvider(): array
{
return [
'with EX modifier' => [
['key', ['field1' => 'value1', 'field2' => 'value2'], HSETEX::SET_NULL, HSETEX::TTL_EX, 1],
1,
1.2,
],
'with PX modifier' => [
['key', ['field1' => 'value1', 'field2' => 'value2'], HSETEX::SET_NULL, HSETEX::TTL_PX, 100],
1,
0.2,
],
'with EXAT modifier' => [
['key', ['field1' => 'value1', 'field2' => 'value2'], HSETEX::SET_NULL, HSETEX::TTL_EXAT, time() + 1],
1,
2,
],
'with PXAT modifier' => [
['key', ['field1' => 'value1', 'field2' => 'value2'], HSETEX::SET_NULL, HSETEX::TTL_PXAT, (time() * 1000) + 100],
1,
0.3,
],
'with combined modifiers' => [
['key', ['field1' => 'value1', 'field2' => 'value2'], HSETEX::SET_FNX, HSETEX::TTL_PX, 100],
1,
0.2,
],
];
}
public function unexpectedValuesProvider(): array
{
return [
'with wrong set modifier' => [
['key', ['field1', 'field2'], 'wrong'],
'Modifier argument accepts only: fnx, fxx values',
],
'with wrong ttl modifier' => [
['key', ['field1', 'field2'], '', 'wrong'],
'Modifier argument accepts only: ex, px, exat, pxat, keepttl values',
],
'with wrong ttl modifier value' => [
['key', ['field1', 'field2'], '', HSETEX::TTL_PXAT, 'wrong'],
'Modifier value is missing or incorrect type',
],
];
}
}
-2
View File
@@ -319,8 +319,6 @@ BUFFER;
*/
public function testExposeSearchInformation(): void
{
$this->markTestSkipped('Skipped due to a bug in 8.0-M05. Should be removed in the next version.');
$redis = $this->getClient();
$this->assertArrayHasKey('search', $redis->info('modules')['Modules']);
@@ -69,7 +69,7 @@ class TSINFO_Test extends PredisCommandTestCase
public function testReturnsInformationAboutGivenTimeSeries(): void
{
$redis = $this->getClient();
$expectedResponse = ['totalSamples', 0, 'memoryUsage', 5000, 'firstTimestamp', 0, 'lastTimestamp', 0,
$expectedResponse = ['totalSamples', 0, 'memoryUsage', 4239, 'firstTimestamp', 0, 'lastTimestamp', 0,
'retentionTime', 60000, 'chunkCount', 1, 'chunkSize', 4096, 'chunkType', 'compressed', 'duplicatePolicy',
'max', 'labels', [['sensor_id', '2'], ['area_id', '32']], 'sourceKey', null, 'rules', [],
'ignoreMaxTimeDiff', 0, 'ignoreMaxValDiff', 0];
@@ -84,7 +84,7 @@ class TSINFO_Test extends PredisCommandTestCase
$redis->tscreate('temperature:2:32', $arguments)
);
$this->assertEqualsWithDelta($expectedResponse, $redis->tsinfo('temperature:2:32'), 1000);
$this->assertEquals($expectedResponse, $redis->tsinfo('temperature:2:32'));
}
public function argumentsProvider(): array
@@ -319,14 +319,12 @@ class RedisClusterTest extends PredisTestCase
->withConsecutive(
[
[
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => '6383',
],
],
[
[
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => '6384',
],
@@ -646,7 +644,6 @@ class RedisClusterTest extends PredisTestCase
->expects($this->once())
->method('create')
->with([
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => '9381',
])
@@ -713,7 +710,6 @@ class RedisClusterTest extends PredisTestCase
->expects($this->once())
->method('create')
->with([
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => '9381',
])
@@ -1024,7 +1020,6 @@ class RedisClusterTest extends PredisTestCase
->expects($this->once())
->method('create')
->with([
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => '6381',
])
@@ -1113,58 +1108,6 @@ class RedisClusterTest extends PredisTestCase
->expects($this->once())
->method('create')
->with([
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => '6381',
])
->willReturn($connection3);
$cluster = new RedisCluster($factory);
$cluster->useClusterSlots(false);
$cluster->add($connection1);
$cluster->add($connection2);
$this->assertSame('foobar', $cluster->executeCommand($command));
$this->assertSame('foobar', $cluster->executeCommand($command));
$this->assertCount(3, $cluster);
}
/**
* @group disconnected
*/
public function testNotTCPMovedResponseWithConnectionNotInPool(): void
{
$movedResponse = new Response\Error('MOVED 1970 127.0.0.1:6381');
$command = $this->getCommandFactory()->create('get', ['node:1001']);
$connection1 = $this->getMockConnection('tls://127.0.0.1:6379');
$connection1
->expects($this->once())
->method('executeCommand')
->with($command)
->willReturn($movedResponse);
$connection2 = $this->getMockConnection('tls://127.0.0.1:6380');
$connection2
->expects($this->never())
->method('executeCommand');
$connection3 = $this->getMockConnection('tls://127.0.0.1:6381');
$connection3
->expects($this->exactly(2))
->method('executeCommand')
->with($command)
->willReturnOnConsecutiveCalls('foobar', 'foobar');
/** @var Connection\FactoryInterface|MockObject */
$factory = $this->getMockBuilder('Predis\Connection\FactoryInterface')->getMock();
$factory
->expects($this->once())
->method('create')
->with([
'scheme' => 'tls',
'host' => '127.0.0.1',
'port' => '6381',
])
@@ -1210,7 +1153,6 @@ class RedisClusterTest extends PredisTestCase
->expects($this->once())
->method('create')
->with([
'scheme' => 'tcp',
'host' => '2001:db8:0:f101::2',
'port' => '6379',
])
@@ -1308,7 +1250,6 @@ class RedisClusterTest extends PredisTestCase
->expects($this->once())
->method('create')
->with([
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => '6380',
])
@@ -403,17 +403,6 @@ class ParametersTest extends PredisTestCase
$this->assertSame($expected, Parameters::parse($uri));
}
/**
* @group disconnected
*/
public function testSetParameters(): void
{
$parameters = new Parameters();
$parameters->property = 'value';
$this->assertEquals('value', $parameters->property);
}
// ******************************************************************** //
// ---- HELPER METHODS ------------------------------------------------ //
// ******************************************************************** //