Compare commits

..

6 Commits

Author SHA1 Message Date
Till Krüss 2033429520 tag v3.4.2 2026-03-09 13:33:04 -07:00
Till Krüss 87390e7381 Use static closures (#1652) 2026-03-09 13:30:46 -07:00
Till Krüss f57dfcbeea Format changelog entry [skip ci] 2026-03-09 13:04:50 -07:00
Vasil Chomakov 7388d91153 Add upstream_driver option for CLIENT SETINFO upstream reporting (#1645)
* Add driver_info option for CLIENT SETINFO upstream reporting

* Use null default for upstreamDriver and ternary operator

* Remove redundant null initialization

* fix: remove trailing newline from VERSION file

* fix: update copyright year to 2026 in DriverInfo files

* refactor: rename driver_info to upstream_driver

* fix: code style issues

* docs: update CHANGELOG to reflect upstream_driver rename
2026-03-05 17:05:02 +02:00
Wolfgang Kerschbaumer d0f6671a60 Fix sentinel discovery methods not catching StreamInitException (#1650)
* Fix sentinel discovery methods not catching StreamInitException

The getMaster(), getSlaves(), and updateSentinels() methods only catch
ConnectionException when connecting to Sentinel nodes. StreamInitException
(thrown by stream_socket_client() failures) extends PredisException directly,
not ConnectionException, so it propagates uncaught — preventing fallback to
the next Sentinel node.

This causes complete application failure when any single Sentinel is
unreachable, even if other Sentinels are healthy.

Add StreamInitException to the catch clause using a union type in all three
methods. This is more precise than catching PredisException, which would
also swallow ServerException (e.g. "ERR No such master with that name")
and mask configuration errors.

See also #1577 which applied a similar fix to retryCommandOnFailure().

* Fix coding standards and add changelog entry

- Remove spaces around | in union catch (php-cs-fixer)
- Add CHANGELOG.md entry for #1650

* Codestlye fixes

---------

Co-authored-by: Wolfgang Kerschbaumer <wolfgang.kerschbaumer@bergfex.at>
Co-authored-by: vladvildanov <vladyslav.vildanov@redis.com>
2026-03-05 17:01:40 +02:00
Vladyslav Vildanov 274cb866bd Fixed Sentinel getParameters() executed on string configuration (#1649) 2026-02-26 11:01:54 -08:00
69 changed files with 581 additions and 274 deletions
+9
View File
@@ -1,7 +1,16 @@
## Changelog
## v3.4.2 (2026-03-09)
### Changed
- Switch to `static` closures
### Fixed
- Fixed Sentinel `getParameters()` executed on string configuration (#1649)
- Fixed Sentinel discovery methods not catching `StreamInitException` on connection failure (#1650)
## v3.4.1 (2026-02-23)
### Added
- Added `upstream_driver` option for CLIENT SETINFO upstream reporting (#1645)
- Made `H(P)TTL` commands prefixable (#1639)
- Made `(B)LMPOP` commands prefixable (#1643)
+1 -1
View File
@@ -1 +1 @@
3.4.1
3.4.2
+2 -2
View File
@@ -40,7 +40,7 @@ class NaiveDistributor implements DistributorInterface, HashGeneratorInterface
public function remove($node)
{
$this->nodes = array_filter($this->nodes, function ($n) use ($node) {
$this->nodes = array_filter($this->nodes, static function ($n) use ($node) {
return $n !== $node;
});
@@ -89,7 +89,7 @@ class NaiveDistributor implements DistributorInterface, HashGeneratorInterface
}
$options = [
'cluster' => function () {
'cluster' => static function () {
$distributor = new NaiveDistributor();
$strategy = new PredisStrategy($distributor);
$cluster = new PredisCluster($strategy);
+1 -1
View File
@@ -62,7 +62,7 @@ class EventsListener implements Countable
$dispatcher->attachCallback('events', $events = new EventsListener());
// Attach a function to control the dispatcher loop termination with a message.
$dispatcher->attachCallback('control', function ($payload, $dispatcher) {
$dispatcher->attachCallback('control', static function ($payload, $dispatcher) {
if ($payload === 'terminate_dispatcher') {
$dispatcher->stop();
}
+1 -1
View File
@@ -18,7 +18,7 @@ require __DIR__ . '/shared.php';
$client = new Predis\Client($single_server);
$responses = $client->pipeline(function ($pipe) {
$responses = $client->pipeline(static function ($pipe) {
$pipe->flushdb();
$pipe->incrby('counter', 10);
$pipe->incrby('counter', 30);
+1 -1
View File
@@ -19,7 +19,7 @@ require __DIR__ . '/shared.php';
$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(function (ClientInterface $client) {
$push = $client->push(static function (ClientInterface $client) {
$response = $client->subscribe('channel', 'control');
$status = ($response[2] === 1) ? 'OK' : 'FAILED';
echo "Channel subscription status: {$status}\n";
+1 -1
View File
@@ -21,7 +21,7 @@ require __DIR__ . '/shared.php';
$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(function (ClientInterface $client) {
$push = $client->push(static function (ClientInterface $client) {
$response = $client->subscribe('channel', 'control');
$status = ($response[2] === 1) ? 'OK' : 'FAILED';
echo "Channel subscription status: {$status}\n";
+1 -1
View File
@@ -23,7 +23,7 @@ $pubsub = $client->pubSubLoop();
// When using Relay you cannot use foreach-loops to iterate
// over messages instead use a callback function
$poorMansKafka = function ($message, $client) {
$poorMansKafka = static function ($message, $client) {
switch ($message->kind) {
case 'subscribe':
echo "Subscribed to {$message->channel}", PHP_EOL;
+1 -1
View File
@@ -56,7 +56,7 @@ $options = [
'commands' => [
'hmgetall' => 'HashMultipleGetAll',
],
'replication' => function () {
'replication' => static function () {
$strategy = new ReplicationStrategy();
$strategy->setScriptReadOnly(HashMultipleGetAll::BODY);
+1 -1
View File
@@ -74,7 +74,7 @@ class EventsListener implements Countable
$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) {
$dispatcher->attachCallback('control', static function ($payload, $dispatcher) {
if ($payload === 'terminate_dispatcher') {
$dispatcher->stop();
}
+1 -1
View File
@@ -35,7 +35,7 @@ function zpop($client, $key)
// which the client bails out with an exception.
];
$client->transaction($options, function ($tx) use ($key, &$element) {
$client->transaction($options, static function ($tx) use ($key, &$element) {
@[$element] = $tx->zrange($key, 0, 0);
if (isset($element)) {
+1 -1
View File
@@ -56,7 +56,7 @@ use Traversable;
*/
class Client implements ClientInterface, IteratorAggregate
{
public const VERSION = '3.4.1';
public const VERSION = '3.4.2';
/** @var OptionsInterface */
private $options;
+5 -5
View File
@@ -87,7 +87,7 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
{
return array_reduce(
$this->slotRanges,
function ($carry, $slotRange) {
static function ($carry, $slotRange) {
return $carry + $slotRange->toArray();
},
[]
@@ -102,7 +102,7 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
public function getNodes()
{
return array_unique(array_map(
function ($slotRange) {
static function ($slotRange) {
return $slotRange->getConnection();
},
$this->slotRanges
@@ -192,7 +192,7 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
return array_reduce(
$intersections,
function ($carry, $slotRange) {
static function ($carry, $slotRange) {
return $carry + $slotRange->toArray();
},
[]
@@ -287,7 +287,7 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
public function count()
{
return array_sum(array_map(
function ($slotRange) {
static function ($slotRange) {
return $slotRange->count();
},
$this->slotRanges
@@ -370,7 +370,7 @@ class SlotMap implements ArrayAccess, IteratorAggregate, Countable
{
usort(
$slotRanges,
function (SlotRange $a, SlotRange $b) {
static function (SlotRange $a, SlotRange $b) {
if ($a->getStart() == $b->getStart()) {
return 0;
}
+1 -1
View File
@@ -33,7 +33,7 @@ abstract class PrefixableCommand extends Command implements PrefixableCommandInt
public function applyPrefixForAllArguments(string $prefix): void
{
$this->setRawArguments(
array_map(function ($key) use ($prefix) {
array_map(static function ($key) use ($prefix) {
return $prefix . $key;
}, $this->getArguments())
);
+1 -1
View File
@@ -43,7 +43,7 @@ class ACL extends RedisCommand
// flatten Relay (RESP3) maps
$return = [];
array_walk($data, function ($value, $key) use (&$return) {
array_walk($data, static function ($value, $key) use (&$return) {
$return[] = $key;
$return[] = $value;
});
+1 -1
View File
@@ -34,7 +34,7 @@ class BITFIELD_RO extends RedisCommand
if (array_key_exists(1, $arguments) && is_array($arguments[1])) {
// Convert encoding => offset, into GET, encoding, offset
array_walk($arguments[1], function ($value, $key) use (&$processedArguments) {
array_walk($arguments[1], static function ($value, $key) use (&$processedArguments) {
array_push($processedArguments, 'GET', $key, $value);
});
}
+1 -1
View File
@@ -44,7 +44,7 @@ class HRANDFIELD extends RedisCommand
// flatten Relay (RESP3) maps
$return = [];
array_walk_recursive($data, function ($value) use (&$return) {
array_walk_recursive($data, static function ($value) use (&$return) {
$return[] = $value;
});
+1 -1
View File
@@ -58,7 +58,7 @@ class HSETEX extends RedisCommand
$flatArray = [];
// Convert key => value, into key, value
array_walk($arguments[1], function ($value, $key) use (&$flatArray) {
array_walk($arguments[1], static function ($value, $key) use (&$flatArray) {
array_push($flatArray, $key, $value);
});
+1 -1
View File
@@ -29,7 +29,7 @@ class MSETEX extends PrefixableCommand
{
$processedArguments = [count(array_keys($arguments[0]))];
array_walk($arguments[0], function ($value, $key) use (&$processedArguments) {
array_walk($arguments[0], static function ($value, $key) use (&$processedArguments) {
array_push($processedArguments, $key, $value);
});
+1 -1
View File
@@ -36,7 +36,7 @@ class TDIGESTBYRANK extends RedisCommand
}
// convert Relay (RESP3) constants to strings
return array_map(function ($value) {
return array_map(static function ($value) {
if (is_string($value) || !is_float($value)) {
return $value;
}
@@ -36,7 +36,7 @@ class TDIGESTBYREVRANK extends RedisCommand
}
// convert Relay (RESP3) constants to strings
return array_map(function ($value) {
return array_map(static function ($value) {
if (is_string($value) || !is_float($value)) {
return $value;
}
+1 -1
View File
@@ -38,7 +38,7 @@ class TDIGESTCDF extends RedisCommand
}
// convert Relay (RESP3) constants to strings
return array_map(function ($value) {
return array_map(static function ($value) {
if (is_string($value) || !is_float($value)) {
return $value;
}
@@ -36,7 +36,7 @@ class TDIGESTQUANTILE extends RedisCommand
}
// convert Relay (RESP3) constants to strings
return array_map(function ($value) {
return array_map(static function ($value) {
if (is_string($value) || !is_float($value)) {
return $value;
}
+1 -1
View File
@@ -80,7 +80,7 @@ class CommandUtility
{
$array = [];
array_walk($dict, function ($value, $key) use (&$array) {
array_walk($dict, static function ($value, $key) use (&$array) {
array_push($array, $key, $value);
});
+1 -1
View File
@@ -52,7 +52,7 @@ class VEMB extends RedisCommand
public function parseResponse($data)
{
if (!$this->isRaw) {
return array_map(function ($value) { return (float) $value; }, $data);
return array_map(static function ($value) { return (float) $value; }, $data);
}
$parsedData = [];
+1 -1
View File
@@ -58,7 +58,7 @@ class VLINKS extends RedisCommand
if ($this->withScores) {
foreach ($data as $key => $value) {
if ($value === array_values($value)) {
$data[$key] = CommandUtility::arrayToDictionary($value, function ($key, $value) {
$data[$key] = CommandUtility::arrayToDictionary($value, static function ($key, $value) {
return [$key, (float) $value];
});
} else {
+1 -1
View File
@@ -85,7 +85,7 @@ class VSIM extends RedisCommand
{
if ($this->withScores) {
if ($data === array_values($data)) {
$data = CommandUtility::arrayToDictionary($data, function ($key, $value) {
$data = CommandUtility::arrayToDictionary($data, static function ($key, $value) {
return [$key, (float) $value];
});
}
+2 -2
View File
@@ -69,12 +69,12 @@ class XINFO extends RedisCommand
}
if (isset($result['groups']) && is_array($result['groups'])) {
$result['groups'] = array_map(function ($group) {
$result['groups'] = array_map(static function ($group) {
if ($group === array_values($group)) {
$group = CommandUtility::arrayToDictionary($group, null, false);
}
if (isset($group['consumers'])) {
$group['consumers'] = array_map(function ($consumer) {
$group['consumers'] = array_map(static function ($consumer) {
if ($consumer === array_values($consumer)) {
$consumer = CommandUtility::arrayToDictionary($consumer, null, false);
}
+8
View File
@@ -119,6 +119,10 @@ class Connections implements OptionInterface
$factory->setDefaultParameters($options->parameters);
}
if ($options->defined('upstream_driver')) {
$factory->setUpstreamDriver($options->upstream_driver);
}
return $factory;
}
@@ -136,6 +140,10 @@ class Connections implements OptionInterface
$factory->setDefaultParameters($options->parameters);
}
if ($options->defined('upstream_driver')) {
$factory->setUpstreamDriver($options->upstream_driver);
}
return $factory;
}
}
+2 -2
View File
@@ -67,7 +67,7 @@ class Replication extends Aggregate
switch ($description) {
case 'sentinel':
case 'redis-sentinel':
return function ($parameters, $options) {
return static function ($parameters, $options) {
return new SentinelReplication($options->service, $parameters, $options->connections);
};
@@ -90,7 +90,7 @@ class Replication extends Aggregate
*/
protected function getDefaultConnectionInitializer()
{
return function ($parameters, $options) {
return static function ($parameters, $options) {
$connection = new MasterSlaveReplication();
if ($options->autodiscovery) {
@@ -0,0 +1,53 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Configuration\Option;
use InvalidArgumentException;
use Predis\Configuration\OptionInterface;
use Predis\Configuration\OptionsInterface;
/**
* Configures upstream driver information for CLIENT SETINFO.
*
* This option accepts a string or array of strings identifying upstream drivers
* (e.g., 'laravel_v11.0.0' or ['laravel_v11.0.0', 'my-app_v1.0.0']) that will
* be included in the LIB-NAME sent to Redis via CLIENT SETINFO.
*/
class UpstreamDriver implements OptionInterface
{
/**
* {@inheritdoc}
*/
public function filter(OptionsInterface $options, $value)
{
if (is_string($value)) {
return $value;
}
if (is_array($value)) {
return implode(';', $value);
}
throw new InvalidArgumentException(
'UpstreamDriver option expects a string or an array of strings'
);
}
/**
* {@inheritdoc}
*/
public function getDefault(OptionsInterface $options)
{
return '';
}
}
+1
View File
@@ -32,6 +32,7 @@ class Options implements OptionsInterface
'exceptions' => Option\Exceptions::class,
'prefix' => Option\Prefix::class,
'crc16' => Option\CRC16::class,
'upstream_driver' => Option\UpstreamDriver::class,
];
/** @var array */
+10 -9
View File
@@ -17,15 +17,16 @@ use Predis\Connection\FactoryInterface;
use Predis\Connection\ParametersInterface;
/**
* @property callable $aggregate Custom aggregate connection initializer
* @property callable $cluster Aggregate connection initializer for clustering
* @property FactoryInterface $connections Connection factory for creating new connections
* @property bool $exceptions Toggles exceptions in client for -ERR responses
* @property ProcessorInterface $prefix Key prefixing strategy using the supplied string as prefix
* @property FactoryInterface $commands Command factory for creating Redis commands
* @property array|ParametersInterface $parameters Parameters associated with connection.
* @property callable $replication Aggregate connection initializer for replication
* @property int $readTimeout Timeout in milliseconds between read operations on reading from multiple connections.
* @property callable $aggregate Custom aggregate connection initializer
* @property callable $cluster Aggregate connection initializer for clustering
* @property FactoryInterface $connections Connection factory for creating new connections
* @property bool $exceptions Toggles exceptions in client for -ERR responses
* @property ProcessorInterface $prefix Key prefixing strategy using the supplied string as prefix
* @property FactoryInterface $commands Command factory for creating Redis commands
* @property array|ParametersInterface $parameters Parameters associated with connection.
* @property callable $replication Aggregate connection initializer for replication
* @property int $readTimeout Timeout in milliseconds between read operations on reading from multiple connections.
* @property string|string[] $upstream_driver Upstream driver info for CLIENT SETINFO.
*/
interface OptionsInterface
{
+1 -1
View File
@@ -273,7 +273,7 @@ class RedisCluster extends AbstractAggregateConnection implements ClusterInterfa
$command = RawCommand::create('CLUSTER', 'SLOTS');
$doCallback = function () use (&$connection, $command) {
$doCallback = static function () use (&$connection, $command) {
return $connection->executeCommand($command);
};
+36 -1
View File
@@ -25,6 +25,11 @@ class Factory implements FactoryInterface
{
private $defaults = [];
/**
* @var string|null
*/
private $upstreamDriver;
protected $schemes = [
'tcp' => 'Predis\Connection\StreamConnection',
'unix' => 'Predis\Connection\StreamConnection',
@@ -133,6 +138,26 @@ class Factory implements FactoryInterface
return $this->defaults;
}
/**
* Sets upstream driver information for CLIENT SETINFO.
*
* @param string $driver Upstream driver string (e.g., 'laravel_v11.0.0' or 'laravel_v11.0.0;my-app_v1.0.0').
*/
public function setUpstreamDriver(string $driver): void
{
$this->upstreamDriver = $driver;
}
/**
* Returns the configured upstream driver.
*
* @return string|null
*/
public function getUpstreamDriver(): ?string
{
return $this->upstreamDriver;
}
/**
* Creates a connection parameters instance from the supplied argument.
*
@@ -184,7 +209,7 @@ class Factory implements FactoryInterface
}
$connection->addConnectCommand(
new RawCommand('CLIENT', ['SETINFO', 'LIB-NAME', 'predis'])
new RawCommand('CLIENT', ['SETINFO', 'LIB-NAME', $this->buildLibraryName()])
);
$connection->addConnectCommand(
@@ -197,4 +222,14 @@ class Factory implements FactoryInterface
);
}
}
/**
* Builds the library name string for CLIENT SETINFO.
*
* @return string
*/
protected function buildLibraryName(): string
{
return $this->upstreamDriver ? 'predis(' . $this->upstreamDriver . ')' : 'predis';
}
}
+1 -1
View File
@@ -67,7 +67,7 @@ class Parameters implements ParametersInterface
*/
protected function filter(array $parameters)
{
return array_filter($parameters, function ($value) {
return array_filter($parameters, static function ($value) {
return $value !== null && $value !== '';
});
}
@@ -24,6 +24,7 @@ use Predis\Connection\NodeConnectionInterface;
use Predis\Connection\Parameters;
use Predis\Connection\ParametersInterface;
use Predis\Connection\RelayFactory;
use Predis\Connection\Resource\Exception\StreamInitException;
use Predis\Replication\ReplicationStrategy;
use Predis\Replication\RoleException;
use Predis\Response\Error;
@@ -75,7 +76,15 @@ class SentinelReplication extends AbstractAggregateConnection implements Replica
protected $strategy;
/**
* @var NodeConnectionInterface[]
* Sentinel connection parameters.
*
* Can contain:
* - String URIs (e.g., "tcp://127.0.0.1:26379")
* - Arrays of connection parameters (e.g., ['host' => '127.0.0.1', 'port' => 26379])
* - ParametersInterface objects
* - NodeConnectionInterface objects
*
* @var array<string|array|ParametersInterface|NodeConnectionInterface>
*/
protected $sentinels = [];
@@ -338,7 +347,7 @@ class SentinelReplication extends AbstractAggregateConnection implements Replica
'role' => 'sentinel',
];
}
} catch (ConnectionException $exception) {
} catch (ConnectionException|StreamInitException $exception) {
$this->sentinelConnection = null;
goto SENTINEL_QUERY;
@@ -472,7 +481,7 @@ class SentinelReplication extends AbstractAggregateConnection implements Replica
$masterConnection = $this->connectionFactory->create($masterParameters);
$this->add($masterConnection);
} catch (ConnectionException $exception) {
} catch (ConnectionException|StreamInitException $exception) {
$this->sentinelConnection = null;
goto SENTINEL_QUERY;
@@ -504,7 +513,7 @@ class SentinelReplication extends AbstractAggregateConnection implements Replica
foreach ($slavesParameters as $slaveParameters) {
$this->add($this->connectionFactory->create($slaveParameters));
}
} catch (ConnectionException $exception) {
} catch (ConnectionException|StreamInitException $exception) {
$this->sentinelConnection = null;
goto SENTINEL_QUERY;
@@ -570,7 +579,7 @@ class SentinelReplication extends AbstractAggregateConnection implements Replica
{
$role = strtolower($role);
$retry = $connection->getParameters()->retry;
$actualRole = $retry->callWithRetry(function () use ($connection) {
$actualRole = $retry->callWithRetry(static function () use ($connection) {
return $connection->executeCommand(RawCommand::create('ROLE'));
});
@@ -811,6 +820,11 @@ class SentinelReplication extends AbstractAggregateConnection implements Replica
if (!empty($this->sentinels)) {
$sentinel = $this->sentinels[0];
// Handle string URIs (e.g., "tcp://127.0.0.1:26379")
if (is_string($sentinel)) {
return new Parameters(Parameters::parse($sentinel));
}
// After querySentinels(), sentinels array contains plain arrays instead of connection objects
if (is_array($sentinel)) {
return new Parameters($sentinel);
+2 -2
View File
@@ -34,7 +34,7 @@ class RelayConsumer extends Consumer
$command = $this->client->createCommand('subscribe', [
$channels,
function ($relay, $channel, $message) use ($callback) {
static function ($relay, $channel, $message) use ($callback) {
$callback((object) [
'kind' => is_null($message) ? self::SUBSCRIBE : self::MESSAGE,
'channel' => $channel,
@@ -63,7 +63,7 @@ class RelayConsumer extends Consumer
$command = $this->client->createCommand('psubscribe', [
$patterns,
function ($relay, $pattern, $channel, $message) use ($callback) {
static function ($relay, $pattern, $channel, $message) use ($callback) {
$callback((object) [
'kind' => is_null($message) ? self::PSUBSCRIBE : self::PMESSAGE,
'pattern' => $pattern,
+1 -1
View File
@@ -150,7 +150,7 @@ class Consumer implements Iterator
$client = null;
$event = $this->client->getConnection()->read();
$callback = function ($matches) use (&$database, &$client) {
$callback = static function ($matches) use (&$database, &$client) {
if (2 === $count = count($matches)) {
// Redis <= 2.4
$database = (int) $matches[1];
+3 -3
View File
@@ -71,7 +71,7 @@ class Atomic extends Pipeline
$retry->callWithRetry(function () use ($connection, $commands) {
$this->queuePipeline($connection, $commands);
}, function (Throwable $exception) {
}, static function (Throwable $exception) {
if ($exception instanceof CommunicationException) {
$exception->getConnection()->disconnect();
}
@@ -152,9 +152,9 @@ class Atomic extends Pipeline
{
$retry = $connection->getParameters()->retry;
return $retry->callWithRetry(function () use ($connection, $command) {
return $retry->callWithRetry(static function () use ($connection, $command) {
return $connection->executeCommand($command);
}, function (Throwable $e) {
}, static function (Throwable $e) {
if ($e instanceof CommunicationException) {
$e->getConnection()->disconnect();
}
+1 -1
View File
@@ -36,7 +36,7 @@ class FireAndForget extends Pipeline
} else {
$this->writeToSingleNode($connection, $commands);
}
}, function (Throwable $e) {
}, static function (Throwable $e) {
if ($e instanceof CommunicationException) {
$e->getConnection()->disconnect();
}
+3 -3
View File
@@ -352,7 +352,7 @@ abstract class PredisTestCase extends PHPUnit\Framework\TestCase
if ($isSSL && $isCluster) {
// For cluster SSL tests, use non-SSL cluster endpoints
$endpoints = explode(',', constant('REDIS_CLUSTER_ENDPOINTS'));
$parameters = array_map(function (string $elem) {
$parameters = array_map(static function (string $elem) {
return 'tcp://' . $elem;
}, $endpoints);
} elseif ($isSSL) {
@@ -792,7 +792,7 @@ abstract class PredisTestCase extends PHPUnit\Framework\TestCase
);
$scheme = $this->isSSLTest() ? 'tls' : 'tcp';
return array_map(function (string $elem) use ($scheme) {
return array_map(static function (string $elem) use ($scheme) {
return "{$scheme}://" . $elem;
}, $endpoints);
}
@@ -806,7 +806,7 @@ abstract class PredisTestCase extends PHPUnit\Framework\TestCase
{
$endpoints = explode(',', constant('REDIS_SENTINEL_ENDPOINTS'));
return array_map(function (string $elem) {
return array_map(static function (string $elem) {
return "tcp://{$elem}";
}, $endpoints);
}
+5 -5
View File
@@ -1224,7 +1224,7 @@ class ClientTest extends PredisTestCase
$callable
->expects($this->once())
->method('__invoke')
->willReturnCallback(function ($tx) { $tx->ping(); });
->willReturnCallback(static function ($tx) { $tx->ping(); });
$client = new Client($connection);
$client->transaction($options, $callable);
@@ -1523,7 +1523,7 @@ class ClientTest extends PredisTestCase
public function testStandaloneNodeRetryCommandExecutionOnTimeoutException(): void
{
$retries = 0;
$mockDisconnect = function () use (&$retries) {
$mockDisconnect = static function () use (&$retries) {
$streamConnection = new StreamConnection(new Parameters([
'retry' => new Retry(new ExponentialBackoff(1000, 10000), 3),
]));
@@ -1566,8 +1566,8 @@ class ClientTest extends PredisTestCase
// Retry used to wrap callback around, so we can count retries
$retry = new Retry(new ExponentialBackoff(100, 1000), 3);
$retriesCount = 0;
$retryWrapperFunc = function (callable $do, ?callable $fail = null) use ($retry, &$retriesCount) {
$failWrapperFunc = function (Exception $e) use (&$retriesCount, $fail) {
$retryWrapperFunc = static function (callable $do, ?callable $fail = null) use ($retry, &$retriesCount) {
$failWrapperFunc = static function (Exception $e) use (&$retriesCount, $fail) {
++$retriesCount;
$fail($e);
};
@@ -1621,7 +1621,7 @@ class ClientTest extends PredisTestCase
}
$retries = 0;
$mockDisconnect = function () use (&$retries) {
$mockDisconnect = static function () use (&$retries) {
$streamConnection = new StreamConnection(new Parameters([
'retry' => new Retry(new ExponentialBackoff(1000, 10000), 3),
]));
+1 -1
View File
@@ -514,7 +514,7 @@ class PredisStrategyTest extends PredisTestCase
];
if (isset($type)) {
$commands = array_filter($commands, function (string $expectedType) use ($type) {
$commands = array_filter($commands, static function (string $expectedType) use ($type) {
return $expectedType === $type;
});
}
+1 -1
View File
@@ -537,7 +537,7 @@ class RedisStrategyTest extends PredisTestCase
];
if (isset($type)) {
$commands = array_filter($commands, function (string $expectedType) use ($type) {
$commands = array_filter($commands, static function (string $expectedType) use ($type) {
return $expectedType === $type;
});
}
@@ -34,13 +34,13 @@ class HybridSearchQueryTest extends TestCase
return [
'with default configs' => [
(new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
$config->buildScorerConfig(function (ScorerConfig $scorerConfig) {
->buildSearchConfig(static function (SearchConfig $config) {
$config->buildScorerConfig(static function (ScorerConfig $scorerConfig) {
$scorerConfig->type(ScorerConfig::TYPE_DISMAX);
})
->query('*');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('vector', '$vector')
->k(5)
@@ -50,13 +50,13 @@ class HybridSearchQueryTest extends TestCase
],
'with RANGE vector search' => [
(new HybridSearchQuery(RangeVectorSearchConfig::class))
->buildSearchConfig(function (SearchConfig $config) {
$config->buildScorerConfig(function (ScorerConfig $scorerConfig) {
->buildSearchConfig(static function (SearchConfig $config) {
$config->buildScorerConfig(static function (ScorerConfig $scorerConfig) {
$scorerConfig->type(ScorerConfig::TYPE_DISMAX);
})
->query('*');
})
->buildVectorSearchConfig(function (RangeVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (RangeVectorSearchConfig $config) {
$config
->vector('vector', '$vector')
->radius(5)
@@ -66,19 +66,19 @@ class HybridSearchQueryTest extends TestCase
],
'with COMBINE config - RRF' => [
(new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
$config->buildScorerConfig(function (ScorerConfig $scorerConfig) {
->buildSearchConfig(static function (SearchConfig $config) {
$config->buildScorerConfig(static function (ScorerConfig $scorerConfig) {
$scorerConfig->type(ScorerConfig::TYPE_DISMAX);
})
->query('*');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('vector', '$vector')
->k(5)
->ef(10);
})
->buildCombineConfig(function (RRFCombineConfig $config) {
->buildCombineConfig(static function (RRFCombineConfig $config) {
$config
->window(5)
->rrfConstant(10);
@@ -87,19 +87,19 @@ class HybridSearchQueryTest extends TestCase
],
'with COMBINE config - LINEAR' => [
(new HybridSearchQuery(KNNVectorSearchConfig::class, LinearCombineConfig::class))
->buildSearchConfig(function (SearchConfig $config) {
$config->buildScorerConfig(function (ScorerConfig $scorerConfig) {
->buildSearchConfig(static function (SearchConfig $config) {
$config->buildScorerConfig(static function (ScorerConfig $scorerConfig) {
$scorerConfig->type(ScorerConfig::TYPE_DISMAX);
})
->query('*');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('vector', '$vector')
->k(5)
->ef(10);
})
->buildCombineConfig(function (LinearCombineConfig $config) {
->buildCombineConfig(static function (LinearCombineConfig $config) {
$config
->alpha(0.2)
->beta(0.3);
@@ -108,13 +108,13 @@ class HybridSearchQueryTest extends TestCase
],
'with LOAD' => [
(new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
$config->buildScorerConfig(function (ScorerConfig $scorerConfig) {
->buildSearchConfig(static function (SearchConfig $config) {
$config->buildScorerConfig(static function (ScorerConfig $scorerConfig) {
$scorerConfig->type(ScorerConfig::TYPE_DISMAX);
})
->query('*');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('vector', '$vector')
->k(5)
@@ -125,13 +125,13 @@ class HybridSearchQueryTest extends TestCase
],
'with GROUPBY' => [
(new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
$config->buildScorerConfig(function (ScorerConfig $scorerConfig) {
->buildSearchConfig(static function (SearchConfig $config) {
$config->buildScorerConfig(static function (ScorerConfig $scorerConfig) {
$scorerConfig->type(ScorerConfig::TYPE_DISMAX);
})
->query('*');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('vector', '$vector')
->k(5)
@@ -148,13 +148,13 @@ class HybridSearchQueryTest extends TestCase
],
'with APPLY' => [
(new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
$config->buildScorerConfig(function (ScorerConfig $scorerConfig) {
->buildSearchConfig(static function (SearchConfig $config) {
$config->buildScorerConfig(static function (ScorerConfig $scorerConfig) {
$scorerConfig->type(ScorerConfig::TYPE_DISMAX);
})
->query('*');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('vector', '$vector')
->k(5)
@@ -165,13 +165,13 @@ class HybridSearchQueryTest extends TestCase
],
'with SORTBY' => [
(new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
$config->buildScorerConfig(function (ScorerConfig $scorerConfig) {
->buildSearchConfig(static function (SearchConfig $config) {
$config->buildScorerConfig(static function (ScorerConfig $scorerConfig) {
$scorerConfig->type(ScorerConfig::TYPE_DISMAX);
})
->query('*');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('vector', '$vector')
->k(5)
@@ -182,13 +182,13 @@ class HybridSearchQueryTest extends TestCase
],
'with FILTER' => [
(new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
$config->buildScorerConfig(function (ScorerConfig $scorerConfig) {
->buildSearchConfig(static function (SearchConfig $config) {
$config->buildScorerConfig(static function (ScorerConfig $scorerConfig) {
$scorerConfig->type(ScorerConfig::TYPE_DISMAX);
})
->query('*');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('vector', '$vector')
->k(5)
@@ -199,13 +199,13 @@ class HybridSearchQueryTest extends TestCase
],
'with LIMIT' => [
(new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
$config->buildScorerConfig(function (ScorerConfig $scorerConfig) {
->buildSearchConfig(static function (SearchConfig $config) {
$config->buildScorerConfig(static function (ScorerConfig $scorerConfig) {
$scorerConfig->type(ScorerConfig::TYPE_DISMAX);
})
->query('*');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('vector', '$vector')
->k(5)
@@ -216,13 +216,13 @@ class HybridSearchQueryTest extends TestCase
],
'with PARAMS' => [
(new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
$config->buildScorerConfig(function (ScorerConfig $scorerConfig) {
->buildSearchConfig(static function (SearchConfig $config) {
$config->buildScorerConfig(static function (ScorerConfig $scorerConfig) {
$scorerConfig->type(ScorerConfig::TYPE_DISMAX);
})
->query('*');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('vector', '$vector')
->k(5)
@@ -233,13 +233,13 @@ class HybridSearchQueryTest extends TestCase
],
'with EXPLAINSCORE' => [
(new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
$config->buildScorerConfig(function (ScorerConfig $scorerConfig) {
->buildSearchConfig(static function (SearchConfig $config) {
$config->buildScorerConfig(static function (ScorerConfig $scorerConfig) {
$scorerConfig->type(ScorerConfig::TYPE_DISMAX);
})
->query('*');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('vector', '$vector')
->k(5)
@@ -250,13 +250,13 @@ class HybridSearchQueryTest extends TestCase
],
'with TIMEOUT' => [
(new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
$config->buildScorerConfig(function (ScorerConfig $scorerConfig) {
->buildSearchConfig(static function (SearchConfig $config) {
$config->buildScorerConfig(static function (ScorerConfig $scorerConfig) {
$scorerConfig->type(ScorerConfig::TYPE_DISMAX);
})
->query('*');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('vector', '$vector')
->k(5)
@@ -267,13 +267,13 @@ class HybridSearchQueryTest extends TestCase
],
'with WITHCURSOR' => [
(new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
$config->buildScorerConfig(function (ScorerConfig $scorerConfig) {
->buildSearchConfig(static function (SearchConfig $config) {
$config->buildScorerConfig(static function (ScorerConfig $scorerConfig) {
$scorerConfig->type(ScorerConfig::TYPE_DISMAX);
})
->query('*');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('vector', '$vector')
->k(5)
@@ -33,7 +33,7 @@ class SearchConfigTest extends TestCase
}
if ($type) {
$this->assertEquals($config, $config->buildScorerConfig(function (ScorerConfig $scorerConfig) use ($type) {
$this->assertEquals($config, $config->buildScorerConfig(static function (ScorerConfig $scorerConfig) use ($type) {
$scorerConfig->type($type);
}));
}
@@ -123,7 +123,7 @@ class KeyPrefixProcessorTest extends PredisTestCase
->expects($this->once())
->method('__invoke')
->with($command, 'prefix:')
->willReturnCallback(function ($command, $prefix) {
->willReturnCallback(static function ($command, $prefix) {
$command->setRawArguments(['prefix:key', 'value']);
});
@@ -148,7 +148,7 @@ class KeyPrefixProcessorTest extends PredisTestCase
->expects($this->once())
->method('__invoke')
->with($command, 'prefix:')
->willReturnCallback(function ($command, $prefix) {
->willReturnCallback(static function ($command, $prefix) {
$command->setRawArguments(['prefix:key', 'value']);
});
@@ -53,13 +53,13 @@ class FTHYBRID_Test extends PredisCommandTestCase
{
$command = $this->getCommand();
$query = (new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
$config->buildScorerConfig(function (ScorerConfig $scorerConfig) {
->buildSearchConfig(static function (SearchConfig $config) {
$config->buildScorerConfig(static function (ScorerConfig $scorerConfig) {
$scorerConfig->type(ScorerConfig::TYPE_DISMAX);
})
->query('*');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('vector', '$vector')
->k(5)
@@ -105,14 +105,14 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->generateData($redis, 5);
$query = (new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('@color:{red} @color:{green}')
->buildScorerConfig(function (ScorerConfig $scorerConfig) {
->buildScorerConfig(static function (ScorerConfig $scorerConfig) {
$scorerConfig->type(ScorerConfig::TYPE_TFIDF);
});
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config->vector('@embedding', '$vector');
})
->params([
@@ -135,14 +135,14 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->generateData($redis, 5);
$query = (new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('@color:{red} @color:{green}')
->buildScorerConfig(function (ScorerConfig $scorerConfig) {
->buildScorerConfig(static function (ScorerConfig $scorerConfig) {
$scorerConfig->type(ScorerConfig::TYPE_TFIDF);
});
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config->vector('@embedding', '$vector');
})
->params([
@@ -165,11 +165,11 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->generateData($redis, 5);
$query = (new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('@color:{red} @color:{green}');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config->vector('@embedding', '$vector');
})
->params([
@@ -197,11 +197,11 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->generateData($redis, 5);
$query = (new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('@color:{red} @color:{green}');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config->vector('@embedding', '$vector');
})
->params([
@@ -229,17 +229,17 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->generateData($redis, 10);
$query = (new HybridSearchQuery(KNNVectorSearchConfig::class, LinearCombineConfig::class))
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('shoes')
->buildScorerConfig(function (ScorerConfig $scorerConfig) {
->buildScorerConfig(static function (ScorerConfig $scorerConfig) {
$scorerConfig->type(ScorerConfig::TYPE_TFIDF);
});
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config->vector('@embedding', '$vector');
})
->buildCombineConfig(function (LinearCombineConfig $config) {
->buildCombineConfig(static function (LinearCombineConfig $config) {
$config
->alpha(1)
->beta(0);
@@ -271,17 +271,17 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->assertEquals($expectedResultsTFIDF, $response['results']);
$query = (new HybridSearchQuery(KNNVectorSearchConfig::class, LinearCombineConfig::class))
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('shoes')
->buildScorerConfig(function (ScorerConfig $scorerConfig) {
->buildScorerConfig(static function (ScorerConfig $scorerConfig) {
$scorerConfig->type(ScorerConfig::TYPE_BM25);
});
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config->vector('@embedding', '$vector');
})
->buildCombineConfig(function (LinearCombineConfig $config) {
->buildCombineConfig(static function (LinearCombineConfig $config) {
$config
->alpha(1)
->beta(0);
@@ -326,11 +326,11 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->generateData($redis, 5);
$query = (new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('shoes');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('@embedding-hnsw', '$vector')
->k(3)
@@ -356,11 +356,11 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->generateData($redis, 5);
$query = (new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('@color:{missing}');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('@embedding', '$vector')
->filter('@price:[15 16] @size:[10 11]');
@@ -392,12 +392,12 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->generateData($redis);
$query = (new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('shoes')
->as('search_score');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('@embedding', '$vector');
})
@@ -429,11 +429,11 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->generateData($redis);
$query = (new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('shoes');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('@embedding-hnsw', '$vector')
->k(3)
@@ -468,19 +468,19 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->generateData($redis);
$query = (new HybridSearchQuery(KNNVectorSearchConfig::class, LinearCombineConfig::class))
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('shoes')
->as('search_score');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('@embedding-hnsw', '$vector')
->k(3)
->ef(1)
->as('vsim_score');
})
->buildCombineConfig(function (LinearCombineConfig $config) {
->buildCombineConfig(static function (LinearCombineConfig $config) {
$config
->alpha(0.5)
->beta(0.5)
@@ -524,19 +524,19 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->generateData($redis);
$query = (new HybridSearchQuery(KNNVectorSearchConfig::class, LinearCombineConfig::class))
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('shoes')
->as('search_score');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('@embedding-hnsw', '$vector')
->k(3)
->ef(1)
->as('vsim_score');
})
->buildCombineConfig(function (LinearCombineConfig $config) {
->buildCombineConfig(static function (LinearCombineConfig $config) {
$config
->alpha(0.5)
->beta(0.5)
@@ -568,11 +568,11 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->generateData($redis, 10);
$query = (new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('@color:{none}');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('@embedding', '$vector')
->k(3);
@@ -591,11 +591,11 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->assertEquals($expected_results, $response['results']);
$query = (new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('@color:{none}');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('@embedding-hnsw', '$vector')
->k(3)
@@ -628,11 +628,11 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->generateData($redis, 10);
$query = (new HybridSearchQuery(RangeVectorSearchConfig::class))
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('@color:{none}');
})
->buildVectorSearchConfig(function (RangeVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (RangeVectorSearchConfig $config) {
$config
->vector('@embedding', '$vector');
})
@@ -651,11 +651,11 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->assertEquals($expected_results, $response['results']);
$query = (new HybridSearchQuery(RangeVectorSearchConfig::class))
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('@color:{none}');
})
->buildVectorSearchConfig(function (RangeVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (RangeVectorSearchConfig $config) {
$config
->vector('@embedding-hnsw', '$vector')
->radius(2)
@@ -689,15 +689,15 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->generateData($redis, 10);
$query = (new HybridSearchQuery(KNNVectorSearchConfig::class, LinearCombineConfig::class))
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('@color:{red}');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('@embedding', '$vector');
})
->buildCombineConfig(function (LinearCombineConfig $config) {
->buildCombineConfig(static function (LinearCombineConfig $config) {
$config
->alpha(0.5)
->beta(0.5);
@@ -717,15 +717,15 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->assertEquals($expected_results, $response['results']);
$query = (new HybridSearchQuery(KNNVectorSearchConfig::class, RRFCombineConfig::class))
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('@color:{red}');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('@embedding', '$vector');
})
->buildCombineConfig(function (RRFCombineConfig $config) {
->buildCombineConfig(static function (RRFCombineConfig $config) {
$config
->window(3)
->rrfConstant(0.5);
@@ -758,15 +758,15 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->generateData($redis, 10);
$query = (new HybridSearchQuery(KNNVectorSearchConfig::class, LinearCombineConfig::class))
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('@color:{red|green|black}');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('@embedding', '$vector');
})
->buildCombineConfig(function (LinearCombineConfig $config) {
->buildCombineConfig(static function (LinearCombineConfig $config) {
$config
->alpha(0.5)
->beta(0.5);
@@ -802,11 +802,11 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->generateData($redis, 10);
$query = (new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('@color:{red}');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('@embedding', '$vector');
})
@@ -861,11 +861,11 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->generateData($redis, 10);
$query = (new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('@color:{red|green|black}');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('@embedding', '$vector');
})
@@ -897,11 +897,11 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->generateData($redis, 5);
$query = (new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('@color:{$color_criteria}');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('@embedding', '$vector');
})
@@ -953,11 +953,11 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->generateData($redis);
$query = (new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('@color:{red|green}');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('@embedding', '$vector');
})
@@ -1019,11 +1019,11 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->generateData($redis, 10);
$query = (new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('@color:{red|green}');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('@embedding', '$vector');
})
@@ -1087,11 +1087,11 @@ class FTHYBRID_Test extends PredisCommandTestCase
$this->generateData($redis, 10);
$query = (new HybridSearchQuery())
->buildSearchConfig(function (SearchConfig $config) {
->buildSearchConfig(static function (SearchConfig $config) {
$config
->query('@color:{red|green}');
})
->buildVectorSearchConfig(function (KNNVectorSearchConfig $config) {
->buildVectorSearchConfig(static function (KNNVectorSearchConfig $config) {
$config
->vector('@embedding', '$vector');
})
@@ -1143,7 +1143,7 @@ class FTHYBRID_Test extends PredisCommandTestCase
$mergedItems = array_merge($mergedItems, $items);
}
$client->pipeline(function (ClientContextInterface $pipe) use ($mergedItems) {
$client->pipeline(static function (ClientContextInterface $pipe) use ($mergedItems) {
for ($i = 0; $i < count($mergedItems); ++$i) {
[$vec, $description] = $mergedItems[$i];
+1 -1
View File
@@ -244,7 +244,7 @@ class RedisFactoryTest extends PredisTestCase
->method('process')
->with($this->isInstanceOf('Predis\Command\CommandInterface'))
->willReturnCallback(
function (CommandInterface $cmd) use (&$argsRef) {
static function (CommandInterface $cmd) use (&$argsRef) {
$cmd->setRawArguments($argsRef = array_map('strtoupper', $cmd->getArguments()));
}
);
@@ -104,14 +104,14 @@ class CommandUtilityTest extends PredisTestCase
'with callback applied' => [
['key1', ['key2', ['key3', '0.1']]],
['key1' => ['key2' => ['key3' => 0.1]]],
function ($key, $value) {
static function ($key, $value) {
return [$key, (float) $value];
},
],
'with non-recursive approach' => [
['key1', ['key2', ['key3', '0.1']]],
['key1' => ['key2', ['key3', '0.1']]],
function ($key, $value) {
static function ($key, $value) {
return [$key, (float) $value];
},
false,
@@ -301,7 +301,7 @@ class AggregateTest extends PredisTestCase
$factory
->expects($this->exactly(3))
->method('create')
->willReturnCallback(function () use ($connectionClass) {
->willReturnCallback(static function () use ($connectionClass) {
return new $connectionClass();
});
@@ -71,10 +71,10 @@ class ConnectionsTest extends PredisTestCase
$options = $this->getMockBuilder('Predis\Configuration\OptionsInterface')->getMock();
$options
->expects($this->once())
->expects($this->exactly(2))
->method('defined')
->with('parameters')
->willReturn(false);
->withConsecutive(['parameters'], ['upstream_driver'])
->willReturnOnConsecutiveCalls(false, false);
$option = new Connections();
$factory = $option->filter($options, 'relay');
@@ -91,10 +91,10 @@ class ConnectionsTest extends PredisTestCase
$options = $this->getMockBuilder('Predis\Configuration\OptionsInterface')->getMock();
$options
->expects($this->once())
->expects($this->exactly(2))
->method('defined')
->with('parameters')
->willReturn(true);
->withConsecutive(['parameters'], ['upstream_driver'])
->willReturnOnConsecutiveCalls(true, false);
$options
->expects($this->once())
@@ -160,10 +160,10 @@ class ConnectionsTest extends PredisTestCase
/** @var OptionsInterface|\PHPUnit\Framework\MockObject\MockObject\MockObject */
$options = $this->getMockBuilder('Predis\Configuration\OptionsInterface')->getMock();
$options
->expects($this->once())
->expects($this->exactly(2))
->method('defined')
->with('parameters')
->willReturn(true);
->withConsecutive(['parameters'], ['upstream_driver'])
->willReturnOnConsecutiveCalls(true, false);
$options
->expects($this->once())
->method('__get')
@@ -0,0 +1,93 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2026 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Configuration\Option;
use Predis\Configuration\OptionsInterface;
use PredisTestCase;
class UpstreamDriverTest extends PredisTestCase
{
/**
* @group disconnected
*/
public function testDefaultOptionValue(): void
{
$option = new UpstreamDriver();
/** @var OptionsInterface */
$options = $this->getMockBuilder('Predis\Configuration\OptionsInterface')->getMock();
$this->assertSame('', $option->getDefault($options));
}
/**
* @group disconnected
*/
public function testAcceptsString(): void
{
$option = new UpstreamDriver();
/** @var OptionsInterface */
$options = $this->getMockBuilder('Predis\Configuration\OptionsInterface')->getMock();
$value = 'laravel_v11.0.0';
$filtered = $option->filter($options, $value);
$this->assertSame('laravel_v11.0.0', $filtered);
}
/**
* @group disconnected
*/
public function testAcceptsArrayAndNormalizesToString(): void
{
$option = new UpstreamDriver();
/** @var OptionsInterface */
$options = $this->getMockBuilder('Predis\Configuration\OptionsInterface')->getMock();
$value = ['laravel_v11.0.0', 'my-app_v1.0.0'];
$filtered = $option->filter($options, $value);
$this->assertSame('laravel_v11.0.0;my-app_v1.0.0', $filtered);
}
/**
* @group disconnected
*/
public function testAcceptsEmptyArray(): void
{
$option = new UpstreamDriver();
/** @var OptionsInterface */
$options = $this->getMockBuilder('Predis\Configuration\OptionsInterface')->getMock();
$this->assertSame('', $option->filter($options, []));
}
/**
* @group disconnected
*/
public function testThrowsExceptionOnInvalidValue(): void
{
$this->expectException('InvalidArgumentException');
$this->expectExceptionMessage('UpstreamDriver option expects a string or an array of strings');
$option = new UpstreamDriver();
/** @var OptionsInterface */
$options = $this->getMockBuilder('Predis\Configuration\OptionsInterface')->getMock();
$option->filter($options, 123);
}
}
+1 -1
View File
@@ -218,7 +218,7 @@ class OptionsTest extends PredisTestCase
->expects($this->never())
->method('autoload');
spl_autoload_register($autoload = function ($class) use ($trigger) {
spl_autoload_register($autoload = static function ($class) use ($trigger) {
$trigger->autoload($class);
}, true, false);
@@ -154,13 +154,13 @@ class RedisClusterTest extends PredisTestCase
$connection1
->expects($this->once())
->method('connect')
->willReturnCallback(function () use (&$connect1) {
->willReturnCallback(static function () use (&$connect1) {
$connect1 = true;
});
$connection1
->expects($this->any())
->method('isConnected')
->willReturnCallback(function () use (&$connect1) {
->willReturnCallback(static function () use (&$connect1) {
return $connect1;
});
@@ -168,13 +168,13 @@ class RedisClusterTest extends PredisTestCase
$connection2
->expects($this->once())
->method('connect')
->willReturnCallback(function () use (&$connect2) {
->willReturnCallback(static function () use (&$connect2) {
$connect2 = true;
});
$connection2
->expects($this->any())
->method('isConnected')
->willReturnCallback(function () use (&$connect2) {
->willReturnCallback(static function () use (&$connect2) {
return $connect2;
});
+75 -1
View File
@@ -482,7 +482,7 @@ class FactoryTest extends PredisTestCase
$parameters = new Parameters(['scheme' => 'foobar']);
$factory = new Factory();
$initializer = function ($parameters) use ($connectionClass) {
$initializer = static function ($parameters) use ($connectionClass) {
return new $connectionClass($parameters);
};
@@ -585,6 +585,80 @@ class FactoryTest extends PredisTestCase
$this->assertSame(['SETINFO', 'LIB-VER', Client::VERSION], $initCommands[2]->getArguments());
}
/**
* @group disconnected
*/
public function testSettingUpstreamDriver(): void
{
$factory = new Factory();
$this->assertNull($factory->getUpstreamDriver());
$factory->setUpstreamDriver('laravel_v11.0.0');
$this->assertSame('laravel_v11.0.0', $factory->getUpstreamDriver());
}
/**
* @group disconnected
*/
public function testBuildLibraryNameWithoutUpstreamDriver(): void
{
$factory = new Factory();
$reflection = new ReflectionObject($factory);
$buildLibraryName = $reflection->getMethod('buildLibraryName');
$buildLibraryName->setAccessible(true);
$this->assertSame('predis', $buildLibraryName->invoke($factory));
}
/**
* @group disconnected
*/
public function testBuildLibraryNameWithUpstreamDriver(): void
{
$factory = new Factory();
$factory->setUpstreamDriver('laravel_v11.0.0');
$reflection = new ReflectionObject($factory);
$buildLibraryName = $reflection->getMethod('buildLibraryName');
$buildLibraryName->setAccessible(true);
$this->assertSame('predis(laravel_v11.0.0)', $buildLibraryName->invoke($factory));
}
/**
* @group disconnected
*/
public function testBuildLibraryNameWithMultipleUpstreamDrivers(): void
{
$factory = new Factory();
$factory->setUpstreamDriver('laravel_v11.0.0;my-app_v1.0.0');
$reflection = new ReflectionObject($factory);
$buildLibraryName = $reflection->getMethod('buildLibraryName');
$buildLibraryName->setAccessible(true);
$this->assertSame('predis(laravel_v11.0.0;my-app_v1.0.0)', $buildLibraryName->invoke($factory));
}
/**
* @group disconnected
*/
public function testConnectionUsesUpstreamDriverInClientSetInfo(): void
{
$factory = new Factory();
$factory->setUpstreamDriver('laravel_v11.0.0');
$connection = $factory->create([]);
$initCommands = $connection->getInitCommands();
$this->assertInstanceOf(RawCommand::class, $initCommands[1]);
$this->assertSame('CLIENT', $initCommands[1]->getId());
$this->assertSame(['SETINFO', 'LIB-NAME', 'predis(laravel_v11.0.0)'], $initCommands[1]->getArguments());
}
/**
* @dataProvider onConnectionProvider
* @group disconnected
@@ -995,7 +995,7 @@ class MasterSlaveReplicationTest extends PredisTestCase
$replication
->getReplicationStrategy()
->setCommandReadOnly('exists', function ($cmd) {
->setCommandReadOnly('exists', static function ($cmd) {
[$arg1] = $cmd->getArguments();
return $arg1 === 'foo';
@@ -17,6 +17,7 @@ use PHPUnit\Framework\MockObject\MockObject;
use Predis\Command;
use Predis\Connection;
use Predis\Connection\Parameters;
use Predis\Connection\ParametersInterface;
use Predis\Connection\Resource\StreamFactoryInterface;
use Predis\Connection\StreamConnection;
use Predis\Replication;
@@ -1762,6 +1763,24 @@ class SentinelReplicationTest extends PredisTestCase
$this->assertNull($parameters);
}
/**
* @group disconnected
* @return void
*/
public function testGetParametersHandlesStringUriInSentinelsArray(): void
{
// Test with string URI (e.g., "tcp://127.0.0.1:26379")
$sentinelUri = 'tcp://127.0.0.1:5381?role=sentinel';
$replication = $this->getReplicationConnection('srv', [$sentinelUri]);
$parameters = $replication->getParameters();
$this->assertInstanceOf(ParametersInterface::class, $parameters);
$this->assertSame('127.0.0.1', $parameters->host);
$this->assertSame(5381, $parameters->port);
}
/**
* @group disconnected
*/
@@ -99,7 +99,7 @@ class ConsumerTest extends PredisTestCase
$this->equalTo('psubscribe'),
$this->equalTo('ssubscribe')
))
->willReturnCallback(function ($id, $args) use ($commands) {
->willReturnCallback(static function ($id, $args) use ($commands) {
return $commands->create($id, $args);
});
@@ -71,7 +71,7 @@ class DispatcherLoopTest extends PredisTestCase
$this->equalTo('01:argument'),
$this->equalTo('01:quit')
), $dispatcher)
->willReturnCallback(function ($arg, $dispatcher) {
->willReturnCallback(static function ($arg, $dispatcher) {
if ($arg === '01:quit') {
$dispatcher->stop();
}
@@ -141,7 +141,7 @@ class DispatcherLoopTest extends PredisTestCase
->expects($this->exactly(1))
->method('__invoke')
->with($this->equalTo('arg:prefixed'), $dispatcher)
->willReturnCallback(function ($arg, $dispatcher) {
->willReturnCallback(static function ($arg, $dispatcher) {
$dispatcher->stop();
});
+2 -2
View File
@@ -337,7 +337,7 @@ class AtomicTest extends PredisTestCase
$pipeline = new Atomic(new Client($mockConnection));
$responses = $pipeline->execute(function (Pipeline $pipe) {
$responses = $pipeline->execute(static function (Pipeline $pipe) {
$pipe->ping();
$pipe->ping();
$pipe->ping();
@@ -359,7 +359,7 @@ class AtomicTest extends PredisTestCase
['replication' => 'predis']
);
$results = $client->pipeline(function (Pipeline $pipe) {
$results = $client->pipeline(static function (Pipeline $pipe) {
$pipe->set('foo', "bar\r\nbaz");
$pipe->get('foo');
});
+4 -4
View File
@@ -127,7 +127,7 @@ class FireAndForgetTest extends PredisTestCase
$pipeline = new FireAndForget(new Client($mockConnection));
$pipeline->execute(function (Pipeline $pipe) {
$pipeline->execute(static function (Pipeline $pipe) {
$pipe->ping();
$pipe->ping();
$pipe->ping();
@@ -177,7 +177,7 @@ class FireAndForgetTest extends PredisTestCase
$pipeline = new FireAndForget(new Client($mockClusterConnection));
$pipeline->execute(function (Pipeline $pipe) {
$pipeline->execute(static function (Pipeline $pipe) {
$pipe->ping();
$pipe->ping();
$pipe->ping();
@@ -227,7 +227,7 @@ class FireAndForgetTest extends PredisTestCase
$pipeline = new FireAndForget(new Client($mockReplicationConnection));
$pipeline->execute(function (Pipeline $pipe) {
$pipeline->execute(static function (Pipeline $pipe) {
$pipe->ping();
$pipe->ping();
$pipe->ping();
@@ -267,7 +267,7 @@ class FireAndForgetTest extends PredisTestCase
['replication' => 'predis']
);
$results = $client->pipeline(function (Pipeline $pipe) {
$results = $client->pipeline(static function (Pipeline $pipe) {
$pipe->set('foo', "bar\r\nbaz");
$pipe->get('foo');
});
+19 -19
View File
@@ -373,7 +373,7 @@ class PipelineTest extends PredisTestCase
$test = $this;
$pipeline = new Pipeline(new Client());
$callable = function (Pipeline $pipe) use ($test, $pipeline) {
$callable = static function (Pipeline $pipe) use ($test, $pipeline) {
$test->assertSame($pipeline, $pipe);
$pipe->flushPipeline(false);
};
@@ -403,7 +403,7 @@ class PipelineTest extends PredisTestCase
$pipeline = new Pipeline(new Client());
$pipeline->execute(function (Pipeline $pipe) {
$pipeline->execute(static function (Pipeline $pipe) {
$pipe->execute();
});
}
@@ -446,7 +446,7 @@ class PipelineTest extends PredisTestCase
$pipeline = new Pipeline(new Client($connection));
$responses = $pipeline->execute(function (Pipeline $pipe) {
$responses = $pipeline->execute(static function (Pipeline $pipe) {
$pipe->echo('one');
$pipe->echo('two');
$pipe->echo('three');
@@ -475,7 +475,7 @@ class PipelineTest extends PredisTestCase
$pipeline = new Pipeline(new Client($connection));
try {
$responses = $pipeline->execute(function (Pipeline $pipe) {
$responses = $pipeline->execute(static function (Pipeline $pipe) {
$pipe->echo('one');
$pipe->echo('two');
throw new ClientException('TEST');
@@ -532,7 +532,7 @@ class PipelineTest extends PredisTestCase
$connection = new StreamConnection($parameters, $mockStreamFactory);
$pipeline = new Pipeline(new Client($connection));
$responses = $pipeline->execute(function (Pipeline $pipe) {
$responses = $pipeline->execute(static function (Pipeline $pipe) {
$pipe->ping();
$pipe->ping();
$pipe->ping();
@@ -590,7 +590,7 @@ class PipelineTest extends PredisTestCase
$pipeline = new Pipeline(new Client($connection));
$responses = $pipeline->execute(function (Pipeline $pipe) {
$responses = $pipeline->execute(static function (Pipeline $pipe) {
$pipe->set('key', 'value');
$pipe->set('key', 'value');
$pipe->set('key', 'value');
@@ -669,7 +669,7 @@ class PipelineTest extends PredisTestCase
$pipeline = new Pipeline(new Client($connection));
$responses = $pipeline->execute(function (Pipeline $pipe) {
$responses = $pipeline->execute(static function (Pipeline $pipe) {
$pipe->set('key', 'value');
$pipe->set('key', 'value');
$pipe->set('key', 'value');
@@ -742,7 +742,7 @@ class PipelineTest extends PredisTestCase
$pipeline = new Pipeline(new Client($connection));
$responses = $pipeline->execute(function (Pipeline $pipe) {
$responses = $pipeline->execute(static function (Pipeline $pipe) {
$pipe->set('key', 'value');
$pipe->set('key', 'value');
$pipe->set('key', 'value');
@@ -801,7 +801,7 @@ class PipelineTest extends PredisTestCase
$pipeline = new Pipeline(new Client($connection));
$responses = $pipeline->execute(function (Pipeline $pipe) {
$responses = $pipeline->execute(static function (Pipeline $pipe) {
$pipe->set('key', 'value');
$pipe->set('key', 'value');
$pipe->set('key', 'value');
@@ -854,7 +854,7 @@ class PipelineTest extends PredisTestCase
{
$client = $this->getClient();
$results = $client->pipeline(function (Pipeline $pipe) {
$results = $client->pipeline(static function (Pipeline $pipe) {
$pipe->set('foo', 'bar');
$pipe->get('foo');
});
@@ -871,7 +871,7 @@ class PipelineTest extends PredisTestCase
$oob = null;
$client = $this->getClient();
$results = $client->pipeline(function (Pipeline $pipe) use (&$oob) {
$results = $client->pipeline(static function (Pipeline $pipe) use (&$oob) {
$pipe->set('foo', 'bar');
$oob = $pipe->getClient()->echo('oob message');
$pipe->get('foo');
@@ -892,7 +892,7 @@ class PipelineTest extends PredisTestCase
$client = $this->getClient();
try {
$client->pipeline(function (Pipeline $pipe) {
$client->pipeline(static function (Pipeline $pipe) {
$pipe->set('foo', 'bar');
throw new ClientException('TEST');
});
@@ -915,7 +915,7 @@ class PipelineTest extends PredisTestCase
$client = $this->getClient();
try {
$client->pipeline(function (Pipeline $pipe) {
$client->pipeline(static function (Pipeline $pipe) {
$pipe->set('foo', 'bar');
// LPUSH on a string key fails, but won't stop
// the pipeline to send the commands.
@@ -938,7 +938,7 @@ class PipelineTest extends PredisTestCase
{
$client = $this->getClient([], ['exceptions' => false]);
$results = $client->pipeline(function (Pipeline $pipe) {
$results = $client->pipeline(static function (Pipeline $pipe) {
$pipe->set('foo', 'bar');
$pipe->lpush('foo', 'bar'); // LPUSH on a string key fails.
$pipe->get('foo');
@@ -959,7 +959,7 @@ class PipelineTest extends PredisTestCase
{
$client = $this->getClient();
$results = $client->pipeline(function (Pipeline $pipe) {
$results = $client->pipeline(static function (Pipeline $pipe) {
$pipe->set('foo', 'bar');
$pipe->set('bar', 'foo');
$pipe->set('baz', 'baz');
@@ -995,7 +995,7 @@ class PipelineTest extends PredisTestCase
$this->expectException(TimeoutException::class);
$client->pipeline(function (Pipeline $pipe) use (&$retries) {
$client->pipeline(static function (Pipeline $pipe) use (&$retries) {
$pipe->incr('test_key');
$pipe->blpop('foo', 3);
});
@@ -1021,7 +1021,7 @@ class PipelineTest extends PredisTestCase
$this->expectException(TimeoutException::class);
$client->pipeline(function (Pipeline $pipe) use (&$retries) {
$client->pipeline(static function (Pipeline $pipe) use (&$retries) {
++$retries;
$pipe->blpop('foo', 3);
});
@@ -1041,7 +1041,7 @@ class PipelineTest extends PredisTestCase
['replication' => 'predis']
);
$results = $client->pipeline(function (Pipeline $pipe) {
$results = $client->pipeline(static function (Pipeline $pipe) {
$pipe->set('foo', "bar\r\nbaz");
$pipe->get('foo');
});
@@ -1078,7 +1078,7 @@ class PipelineTest extends PredisTestCase
*/
protected function getReadCallback(): callable
{
return function (CommandInterface $command) {
return static function (CommandInterface $command) {
if (($id = $command->getId()) !== 'ECHO') {
throw new InvalidArgumentException("Expected ECHO, got {$id}");
}
@@ -311,7 +311,7 @@ class ReplicationStrategyTest extends PredisTestCase
$commands = $this->getCommandFactory();
$strategy = new ReplicationStrategy();
$strategy->setCommandReadOnly('SET', function (CommandInterface $command) {
$strategy->setCommandReadOnly('SET', static function (CommandInterface $command) {
return $command->getArgument(1) === true;
});
@@ -362,7 +362,7 @@ class ReplicationStrategyTest extends PredisTestCase
->method('getScript')
->willReturn($script = 'return true');
$strategy->setScriptReadOnly($script, function (CommandInterface $command) {
$strategy->setScriptReadOnly($script, static function (CommandInterface $command) {
return $command->getArgument(2) === true;
});
@@ -557,7 +557,7 @@ class ReplicationStrategyTest extends PredisTestCase
];
if (isset($type)) {
$commands = array_filter($commands, function (string $expectedType) use ($type) {
$commands = array_filter($commands, static function (string $expectedType) use ($type) {
return $expectedType === $type;
});
}
+2 -2
View File
@@ -39,7 +39,7 @@ class RetryTest extends TestCase
$retry = new Retry($backoffStrategy, $retries);
$retriesCount = 0;
$callable = function () use (&$retriesCount, $retries) {
$callable = static function () use (&$retriesCount, $retries) {
if ($retriesCount >= $retries) {
return;
}
@@ -82,7 +82,7 @@ class RetryTest extends TestCase
throw new StreamInitException();
};
$failCallable = function () use (&$retriesCount) {
$failCallable = static function () use (&$retriesCount) {
++$retriesCount;
};
+1 -1
View File
@@ -185,7 +185,7 @@ class SSLTest extends PredisTestCase
// Remove AUTH
$defaultParameters = $this->getDefaultParametersArray();
$trimmedParameters = array_map(function (string $parameter) {
$trimmedParameters = array_map(static function (string $parameter) {
return explode('?', $parameter)[0];
}, $defaultParameters);
+37 -37
View File
@@ -138,7 +138,7 @@ class MultiExecTest extends PredisTestCase
$callback = $this->getExecuteCallback($expected, $commands);
$tx = $this->getMockedTransaction($callback);
$responses = $tx->execute(function ($tx) {
$responses = $tx->execute(static function ($tx) {
$tx->echo('one');
$tx->echo('two');
$tx->echo('three');
@@ -161,7 +161,7 @@ class MultiExecTest extends PredisTestCase
$exception = null;
try {
$tx->echo('foo')->execute(function ($tx) {
$tx->echo('foo')->execute(static function ($tx) {
$tx->echo('bar');
});
} catch (Exception $ex) {
@@ -182,7 +182,7 @@ class MultiExecTest extends PredisTestCase
$callback = $this->getExecuteCallback(null, $commands);
$tx = $this->getMockedTransaction($callback);
$responses = $tx->execute(function ($tx) {
$responses = $tx->execute(static function ($tx) {
// NOOP
});
@@ -203,7 +203,7 @@ class MultiExecTest extends PredisTestCase
$callback = $this->getExecuteCallback(null, $commands);
$tx = $this->getMockedTransaction($callback);
$responses = $tx->execute(function ($tx) {
$responses = $tx->execute(static function ($tx) {
$tx->exec();
});
@@ -221,7 +221,7 @@ class MultiExecTest extends PredisTestCase
$callback = $this->getExecuteCallback(null, $commands);
$tx = $this->getMockedTransaction($callback);
$responses = $tx->execute(function ($tx) {
$responses = $tx->execute(static function ($tx) {
$tx->discard();
});
@@ -239,7 +239,7 @@ class MultiExecTest extends PredisTestCase
$callback = $this->getExecuteCallback(null, $commands);
$tx = $this->getMockedTransaction($callback);
$responses = $tx->execute(function ($tx) {
$responses = $tx->execute(static function ($tx) {
$tx->set('foo', 'bar');
$tx->get('foo');
$tx->discard();
@@ -260,7 +260,7 @@ class MultiExecTest extends PredisTestCase
$callback = $this->getExecuteCallback($expected, $commands);
$tx = $this->getMockedTransaction($callback);
$responses = $tx->execute(function ($tx) {
$responses = $tx->execute(static function ($tx) {
$tx->echo('before DISCARD');
$tx->discard();
$tx->echo('after DISCARD');
@@ -312,7 +312,7 @@ class MultiExecTest extends PredisTestCase
$callback = $this->getExecuteCallback($expected, $txCommands, $casCommands);
$tx = $this->getMockedTransaction($callback, $options);
$responses = $tx->execute(function ($tx) {
$responses = $tx->execute(static function ($tx) {
$tx->get('foo');
$tx->get('hoge');
});
@@ -363,7 +363,7 @@ class MultiExecTest extends PredisTestCase
$tx = $this->getMockedTransaction($callback, $options);
$test = $this;
$responses = $tx->execute(function ($tx) use ($test) {
$responses = $tx->execute(static function ($tx) use ($test) {
$tx->watch('foobar');
$response1 = $tx->get('foo');
@@ -394,7 +394,7 @@ class MultiExecTest extends PredisTestCase
$callback = $this->getExecuteCallback([], $txCommands, $casCommands);
$tx = $this->getMockedTransaction($callback, $options);
$tx->execute(function ($tx) {
$tx->execute(static function ($tx) {
$tx->multi();
});
@@ -413,7 +413,7 @@ class MultiExecTest extends PredisTestCase
$callback = $this->getExecuteCallback([], $txCommands, $casCommands);
$tx = $this->getMockedTransaction($callback, $options);
$tx->execute(function ($tx) {
$tx->execute(static function ($tx) {
$tx->get('foo');
$tx->set('hoge', 'piyo');
});
@@ -457,7 +457,7 @@ class MultiExecTest extends PredisTestCase
$callback = $this->getExecuteCallback($expected, $txCommands, $casCommands);
$tx = $this->getMockedTransaction($callback, $options);
$responses = $tx->execute(function (MultiExec $tx) use ($signal, &$attempts) {
$responses = $tx->execute(static function (MultiExec $tx) use ($signal, &$attempts) {
$tx->get('foo');
if ($attempts > 0) {
@@ -484,7 +484,7 @@ class MultiExecTest extends PredisTestCase
$callback = $this->getExecuteCallback();
$tx = $this->getMockedTransaction($callback);
$tx->execute(function ($tx) {
$tx->execute(static function ($tx) {
$tx->echo('!!ABORT!!');
});
}
@@ -503,7 +503,7 @@ class MultiExecTest extends PredisTestCase
$responses = null;
try {
$responses = $tx->execute(function (MultiExec $tx) {
$responses = $tx->execute(static function (MultiExec $tx) {
$tx->set('foo', 'bar');
$tx->get('foo');
@@ -532,7 +532,7 @@ class MultiExecTest extends PredisTestCase
$responses = null;
try {
$responses = $tx->execute(function (MultiExec $tx) {
$responses = $tx->execute(static function (MultiExec $tx) {
$tx->set('foo', 'bar');
$tx->echo('ERR Invalid operation');
$tx->get('foo');
@@ -550,7 +550,7 @@ class MultiExecTest extends PredisTestCase
*/
public function testProperlyDiscardsTransactionAfterServerExceptionInBlock(): void
{
$connection = $this->getMockedConnection(function (CommandInterface $command) {
$connection = $this->getMockedConnection(static function (CommandInterface $command) {
switch ($command->getId()) {
case 'MULTI':
return true;
@@ -596,7 +596,7 @@ class MultiExecTest extends PredisTestCase
{
$expected = ['before', new Response\Error('ERR simulated error'), 'after'];
$connection = $this->getMockedConnection(function (CommandInterface $command) use ($expected) {
$connection = $this->getMockedConnection(static function (CommandInterface $command) use ($expected) {
switch ($command->getId()) {
case 'MULTI':
return true;
@@ -632,7 +632,7 @@ class MultiExecTest extends PredisTestCase
$expected = ['before', new Response\Error('ERR simulated error'), 'after'];
$connection = $this->getMockedConnection(function (CommandInterface $command) use ($expected) {
$connection = $this->getMockedConnection(static function (CommandInterface $command) use ($expected) {
switch ($command->getId()) {
case 'MULTI':
return true;
@@ -659,7 +659,7 @@ class MultiExecTest extends PredisTestCase
$this->expectException('Predis\Response\ServerException');
$this->expectExceptionMessage('ERR simulated failure on EXEC');
$connection = $this->getMockedConnection(function (CommandInterface $command) {
$connection = $this->getMockedConnection(static function (CommandInterface $command) {
switch ($command->getId()) {
case 'MULTI':
return true;
@@ -718,7 +718,7 @@ class MultiExecTest extends PredisTestCase
$tx = new MultiExec(new Client($mockConnection));
$responses = $tx->execute(function (MultiExec $tx) {
$responses = $tx->execute(static function (MultiExec $tx) {
$tx->set('key', 'value');
$tx->set('key', 'value');
$tx->set('key', 'value');
@@ -740,7 +740,7 @@ class MultiExecTest extends PredisTestCase
$exception = null;
try {
$client->transaction(function (MultiExec $tx) {
$client->transaction(static function (MultiExec $tx) {
$tx->set('foo', 'bar');
throw new RuntimeException('TEST');
});
@@ -762,7 +762,7 @@ class MultiExecTest extends PredisTestCase
$value = (string) rand();
try {
$client->transaction(function (MultiExec $tx) use ($value) {
$client->transaction(static function (MultiExec $tx) use ($value) {
$tx->set('foo', 'bar');
$tx->lpush('foo', 'bar');
$tx->set('foo', $value);
@@ -783,7 +783,7 @@ class MultiExecTest extends PredisTestCase
{
$client = $this->getClient([], ['exceptions' => false]);
$responses = $client->transaction(function (MultiExec $tx) {
$responses = $client->transaction(static function (MultiExec $tx) {
$tx->set('foo', 'bar');
$tx->lpush('foo', 'bar');
$tx->echo('foobar');
@@ -802,7 +802,7 @@ class MultiExecTest extends PredisTestCase
{
$client = $this->getClient([], ['exceptions' => false]);
$responses = $client->transaction(function (MultiExec $tx) {
$responses = $client->transaction(static function (MultiExec $tx) {
$tx->set('foo', 'bar');
$tx->lpush('foo', 'bar');
$tx->echo('foobar');
@@ -821,7 +821,7 @@ class MultiExecTest extends PredisTestCase
{
$client = $this->getClient();
$responses = $client->transaction(function (MultiExec $tx) {
$responses = $client->transaction(static function (MultiExec $tx) {
$tx->set('foo', 'bar');
$tx->discard();
$tx->set('hoge', 'piyo');
@@ -844,7 +844,7 @@ class MultiExecTest extends PredisTestCase
$client2 = $this->getClient();
try {
$client1->transaction(['watch' => 'sentinel'], function ($tx) use ($client2) {
$client1->transaction(['watch' => 'sentinel'], static function ($tx) use ($client2) {
$tx->set('sentinel', 'client1');
$tx->get('sentinel');
$client2->set('sentinel', 'client2');
@@ -869,7 +869,7 @@ class MultiExecTest extends PredisTestCase
$client2 = $this->getClient();
try {
$client1->transaction(['watch' => 'sentinel'], function ($tx) use ($client2) {
$client1->transaction(['watch' => 'sentinel'], static function ($tx) use ($client2) {
$tx->set('sentinel', 'client1');
$tx->get('sentinel');
$client2->set('sentinel', 'client2');
@@ -893,7 +893,7 @@ class MultiExecTest extends PredisTestCase
$client->set('foo', 'bar');
$options = ['watch' => 'foo', 'cas' => true];
$responses = $client->transaction($options, function ($tx) {
$responses = $client->transaction($options, static function ($tx) {
$tx->watch('foobar');
$foo = $tx->get('foo');
@@ -911,7 +911,7 @@ class MultiExecTest extends PredisTestCase
$client->set('foo', 'bar');
$options = ['watch' => 'foo', 'cas' => true, 'retry' => 1];
$responses = $client->transaction($options, function ($tx) use ($client2, &$hijack) {
$responses = $client->transaction($options, static function ($tx) use ($client2, &$hijack) {
$foo = $tx->get('foo');
$tx->multi();
@@ -940,7 +940,7 @@ class MultiExecTest extends PredisTestCase
{
$redis = $this->getClient();
$response = $redis->transaction(function (MultiExec $tx) {
$response = $redis->transaction(static function (MultiExec $tx) {
$tx->set('{foo}foo', 'value');
$tx->set('{foo}bar', 'value');
$tx->set('{foo}baz', 'value');
@@ -964,7 +964,7 @@ class MultiExecTest extends PredisTestCase
'To be able to execute a transaction against cluster, all commands should operate on the same hash slot'
);
$redis->transaction(function (MultiExec $tx) {
$redis->transaction(static function (MultiExec $tx) {
$tx->set('foo_bar_baz', 'value');
$tx->set('{foo}bar', 'value');
$tx->set('{foo}baz', 'value');
@@ -982,7 +982,7 @@ class MultiExecTest extends PredisTestCase
$redis = $this->getClient();
$options = ['cas' => true, 'watch' => ['{foo}foo', '{foo}bar', '{foo}baz']];
$response = $redis->transaction($options, function (MultiExec $tx) {
$response = $redis->transaction($options, static function (MultiExec $tx) {
$tx->multi();
$tx->set('{foo}foo', 'value');
$tx->set('{foo}bar', 'value');
@@ -1003,7 +1003,7 @@ class MultiExecTest extends PredisTestCase
$redis = $this->getClient();
$options = ['cas' => true, 'watch' => ['{foo}foo', '{foo}bar', '{foo}baz']];
$response = $redis->transaction($options, function (MultiExec $tx) {
$response = $redis->transaction($options, static function (MultiExec $tx) {
$tx->multi();
$tx->set('{foo}foo', 'value');
$tx->set('{foo}bar', 'value');
@@ -1028,7 +1028,7 @@ class MultiExecTest extends PredisTestCase
$this->expectException(TransactionException::class);
$this->expectExceptionMessage('WATCHed keys should point to the same hash slot');
$redis->transaction($options, function (MultiExec $tx) {
$redis->transaction($options, static function (MultiExec $tx) {
$tx->multi();
$tx->set('{foo}foo', 'value');
$tx->set('{foo}bar', 'value');
@@ -1052,7 +1052,7 @@ class MultiExecTest extends PredisTestCase
'To be able to execute a transaction against cluster, all commands should operate on the same hash slot'
);
$redis->transaction($options, function (MultiExec $tx) {
$redis->transaction($options, static function (MultiExec $tx) {
$tx->multi();
$tx->set('{foo}foo', 'value');
$tx->set('{foo}bar', 'value');
@@ -1128,7 +1128,7 @@ class MultiExecTest extends PredisTestCase
): callable {
$multi = $watch = $abort = false;
return function (CommandInterface $command) use (&$expected, &$commands, &$cas, &$multi, &$watch, &$abort) {
return static function (CommandInterface $command) use (&$expected, &$commands, &$cas, &$multi, &$watch, &$abort) {
$cmd = $command->getId();
if ($multi || $cmd === 'MULTI') {
@@ -1208,7 +1208,7 @@ class MultiExecTest extends PredisTestCase
*/
protected static function commandsToIDs(array $commands): array
{
return array_map(function ($cmd) { return $cmd->getId(); }, $commands);
return array_map(static function ($cmd) { return $cmd->getId(); }, $commands);
}
/**
@@ -68,7 +68,7 @@ class NodeConnectionStrategyTest extends TestCase
$this->mockConnection
->expects($this->once())
->method('executeCommand')
->with($this->callback(function ($command) {
->with($this->callback(static function ($command) {
return $command->getId() === 'UNWATCH';
}))
->willReturn('OK');
@@ -95,7 +95,7 @@ class NodeConnectionStrategyTest extends TestCase
$this->mockConnection
->expects($this->exactly(4))
->method('executeCommand')
->with($this->callback(function ($command) {
->with($this->callback(static function ($command) {
return $command->getId() === 'UNWATCH';
}))
->willReturnOnConsecutiveCalls(