Predis to v2.2.2

This commit is contained in:
the-djmaze 2024-04-02 20:15:23 +02:00
parent f6b440adef
commit 84ffe1e552
259 changed files with 2407 additions and 9937 deletions

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (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.
@ -11,21 +12,17 @@
namespace Predis\Cluster;
use InvalidArgumentException;
use Predis\Command\CommandInterface;
use Predis\Command\ScriptCommand;
/**
* Common class implementing the logic needed to support clustering strategies.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
abstract class ClusterStrategy implements StrategyInterface
{
protected $commands;
/**
*
*/
public function __construct()
{
$this->commands = $this->getDefaultCommands();
@ -38,12 +35,12 @@ abstract class ClusterStrategy implements StrategyInterface
*/
protected function getDefaultCommands()
{
$getKeyFromFirstArgument = array($this, 'getKeyFromFirstArgument');
$getKeyFromAllArguments = array($this, 'getKeyFromAllArguments');
$getKeyFromFirstArgument = [$this, 'getKeyFromFirstArgument'];
$getKeyFromAllArguments = [$this, 'getKeyFromAllArguments'];
return array(
return [
/* commands operating on the key space */
'EXISTS' => $getKeyFromFirstArgument,
'EXISTS' => $getKeyFromAllArguments,
'DEL' => $getKeyFromAllArguments,
'TYPE' => $getKeyFromFirstArgument,
'EXPIRE' => $getKeyFromFirstArgument,
@ -53,9 +50,10 @@ abstract class ClusterStrategy implements StrategyInterface
'PEXPIREAT' => $getKeyFromFirstArgument,
'TTL' => $getKeyFromFirstArgument,
'PTTL' => $getKeyFromFirstArgument,
'SORT' => $getKeyFromFirstArgument, // TODO
'SORT' => [$this, 'getKeyFromSortCommand'],
'DUMP' => $getKeyFromFirstArgument,
'RESTORE' => $getKeyFromFirstArgument,
'FLUSHDB' => [$this, 'getFakeKey'],
/* commands operating on string values */
'APPEND' => $getKeyFromFirstArgument,
@ -72,14 +70,15 @@ abstract class ClusterStrategy implements StrategyInterface
'INCRBYFLOAT' => $getKeyFromFirstArgument,
'SETBIT' => $getKeyFromFirstArgument,
'SETEX' => $getKeyFromFirstArgument,
'MSET' => array($this, 'getKeyFromInterleavedArguments'),
'MSETNX' => array($this, 'getKeyFromInterleavedArguments'),
'MSET' => [$this, 'getKeyFromInterleavedArguments'],
'MSETNX' => [$this, 'getKeyFromInterleavedArguments'],
'SETNX' => $getKeyFromFirstArgument,
'SETRANGE' => $getKeyFromFirstArgument,
'STRLEN' => $getKeyFromFirstArgument,
'SUBSTR' => $getKeyFromFirstArgument,
'BITOP' => array($this, 'getKeyFromBitOp'),
'BITOP' => [$this, 'getKeyFromBitOp'],
'BITCOUNT' => $getKeyFromFirstArgument,
'BITFIELD' => $getKeyFromFirstArgument,
/* commands operating on lists */
'LINSERT' => $getKeyFromFirstArgument,
@ -88,9 +87,9 @@ abstract class ClusterStrategy implements StrategyInterface
'LPOP' => $getKeyFromFirstArgument,
'RPOP' => $getKeyFromFirstArgument,
'RPOPLPUSH' => $getKeyFromAllArguments,
'BLPOP' => array($this, 'getKeyFromBlockingListCommands'),
'BRPOP' => array($this, 'getKeyFromBlockingListCommands'),
'BRPOPLPUSH' => array($this, 'getKeyFromBlockingListCommands'),
'BLPOP' => [$this, 'getKeyFromBlockingListCommands'],
'BRPOP' => [$this, 'getKeyFromBlockingListCommands'],
'BRPOPLPUSH' => [$this, 'getKeyFromBlockingListCommands'],
'LPUSH' => $getKeyFromFirstArgument,
'LPUSHX' => $getKeyFromFirstArgument,
'RPUSH' => $getKeyFromFirstArgument,
@ -121,7 +120,7 @@ abstract class ClusterStrategy implements StrategyInterface
'ZCARD' => $getKeyFromFirstArgument,
'ZCOUNT' => $getKeyFromFirstArgument,
'ZINCRBY' => $getKeyFromFirstArgument,
'ZINTERSTORE' => array($this, 'getKeyFromZsetAggregationCommands'),
'ZINTERSTORE' => [$this, 'getKeyFromZsetAggregationCommands'],
'ZRANGE' => $getKeyFromFirstArgument,
'ZRANGEBYSCORE' => $getKeyFromFirstArgument,
'ZRANK' => $getKeyFromFirstArgument,
@ -132,7 +131,7 @@ abstract class ClusterStrategy implements StrategyInterface
'ZREVRANGEBYSCORE' => $getKeyFromFirstArgument,
'ZREVRANK' => $getKeyFromFirstArgument,
'ZSCORE' => $getKeyFromFirstArgument,
'ZUNIONSTORE' => array($this, 'getKeyFromZsetAggregationCommands'),
'ZUNIONSTORE' => [$this, 'getKeyFromZsetAggregationCommands'],
'ZSCAN' => $getKeyFromFirstArgument,
'ZLEXCOUNT' => $getKeyFromFirstArgument,
'ZRANGEBYLEX' => $getKeyFromFirstArgument,
@ -162,9 +161,23 @@ abstract class ClusterStrategy implements StrategyInterface
'PFMERGE' => $getKeyFromAllArguments,
/* scripting */
'EVAL' => array($this, 'getKeyFromScriptingCommands'),
'EVALSHA' => array($this, 'getKeyFromScriptingCommands'),
);
'EVAL' => [$this, 'getKeyFromScriptingCommands'],
'EVALSHA' => [$this, 'getKeyFromScriptingCommands'],
/* server */
'INFO' => [$this, 'getFakeKey'],
/* commands performing geospatial operations */
'GEOADD' => $getKeyFromFirstArgument,
'GEOHASH' => $getKeyFromFirstArgument,
'GEOPOS' => $getKeyFromFirstArgument,
'GEODIST' => $getKeyFromFirstArgument,
'GEORADIUS' => [$this, 'getKeyFromGeoradiusCommands'],
'GEORADIUSBYMEMBER' => [$this, 'getKeyFromGeoradiusCommands'],
/* cluster */
'CLUSTER' => [$this, 'getFakeKey'],
];
}
/**
@ -189,7 +202,7 @@ abstract class ClusterStrategy implements StrategyInterface
* @param string $commandID Command ID.
* @param mixed $callback A valid callable object, or NULL to unset the handler.
*
* @throws \InvalidArgumentException
* @throws InvalidArgumentException
*/
public function setCommandHandler($commandID, $callback = null)
{
@ -202,7 +215,7 @@ abstract class ClusterStrategy implements StrategyInterface
}
if (!is_callable($callback)) {
throw new \InvalidArgumentException(
throw new InvalidArgumentException(
'The argument must be a callable object or NULL.'
);
}
@ -210,6 +223,16 @@ abstract class ClusterStrategy implements StrategyInterface
$this->commands[$commandID] = $callback;
}
/**
* Get fake key for commands with no key argument.
*
* @return string
*/
protected function getFakeKey(): string
{
return 'key';
}
/**
* Extracts the key from the first argument of a command instance.
*
@ -234,9 +257,11 @@ abstract class ClusterStrategy implements StrategyInterface
{
$arguments = $command->getArguments();
if ($this->checkSameSlotForKeys($arguments)) {
return $arguments[0];
if (!$this->checkSameSlotForKeys($arguments)) {
return null;
}
return $arguments[0];
}
/**
@ -250,15 +275,48 @@ abstract class ClusterStrategy implements StrategyInterface
protected function getKeyFromInterleavedArguments(CommandInterface $command)
{
$arguments = $command->getArguments();
$keys = array();
$keys = [];
for ($i = 0; $i < count($arguments); $i += 2) {
$keys[] = $arguments[$i];
}
if ($this->checkSameSlotForKeys($keys)) {
return $arguments[0];
if (!$this->checkSameSlotForKeys($keys)) {
return null;
}
return $arguments[0];
}
/**
* Extracts the key from SORT command.
*
* @param CommandInterface $command Command instance.
*
* @return string|null
*/
protected function getKeyFromSortCommand(CommandInterface $command)
{
$arguments = $command->getArguments();
$firstKey = $arguments[0];
if (1 === $argc = count($arguments)) {
return $firstKey;
}
$keys = [$firstKey];
for ($i = 1; $i < $argc; ++$i) {
if (strtoupper($arguments[$i]) === 'STORE') {
$keys[] = $arguments[++$i];
}
}
if (!$this->checkSameSlotForKeys($keys)) {
return null;
}
return $firstKey;
}
/**
@ -272,9 +330,11 @@ abstract class ClusterStrategy implements StrategyInterface
{
$arguments = $command->getArguments();
if ($this->checkSameSlotForKeys(array_slice($arguments, 0, count($arguments) - 1))) {
return $arguments[0];
if (!$this->checkSameSlotForKeys(array_slice($arguments, 0, count($arguments) - 1))) {
return null;
}
return $arguments[0];
}
/**
@ -288,9 +348,42 @@ abstract class ClusterStrategy implements StrategyInterface
{
$arguments = $command->getArguments();
if ($this->checkSameSlotForKeys(array_slice($arguments, 1, count($arguments)))) {
return $arguments[1];
if (!$this->checkSameSlotForKeys(array_slice($arguments, 1, count($arguments)))) {
return null;
}
return $arguments[1];
}
/**
* Extracts the key from GEORADIUS and GEORADIUSBYMEMBER commands.
*
* @param CommandInterface $command Command instance.
*
* @return string|null
*/
protected function getKeyFromGeoradiusCommands(CommandInterface $command)
{
$arguments = $command->getArguments();
$argc = count($arguments);
$startIndex = $command->getId() === 'GEORADIUS' ? 5 : 4;
if ($argc > $startIndex) {
$keys = [$arguments[0]];
for ($i = $startIndex; $i < $argc; ++$i) {
$argument = strtoupper($arguments[$i]);
if ($argument === 'STORE' || $argument === 'STOREDIST') {
$keys[] = $arguments[++$i];
}
}
if (!$this->checkSameSlotForKeys($keys)) {
return null;
}
}
return $arguments[0];
}
/**
@ -303,11 +396,13 @@ abstract class ClusterStrategy implements StrategyInterface
protected function getKeyFromZsetAggregationCommands(CommandInterface $command)
{
$arguments = $command->getArguments();
$keys = array_merge(array($arguments[0]), array_slice($arguments, 2, $arguments[1]));
$keys = array_merge([$arguments[0]], array_slice($arguments, 2, $arguments[1]));
if ($this->checkSameSlotForKeys($keys)) {
return $arguments[0];
if (!$this->checkSameSlotForKeys($keys)) {
return null;
}
return $arguments[0];
}
/**
@ -319,15 +414,15 @@ abstract class ClusterStrategy implements StrategyInterface
*/
protected function getKeyFromScriptingCommands(CommandInterface $command)
{
if ($command instanceof ScriptCommand) {
$keys = $command->getKeys();
} else {
$keys = array_slice($args = $command->getArguments(), 2, $args[1]);
$keys = $command instanceof ScriptCommand
? $command->getKeys()
: array_slice($args = $command->getArguments(), 2, $args[1]);
if (!$keys || !$this->checkSameSlotForKeys($keys)) {
return null;
}
if ($keys && $this->checkSameSlotForKeys($keys)) {
return $keys[0];
}
return $keys[0];
}
/**