Compare commits

..

15 Commits

Author SHA1 Message Date
Nicolas Grekas deee2b6d60 Fix deprecation when using "static" in callables (#1403) 2023-09-19 09:11:21 -07:00
Till Krüss bb8cce7bcf adjust travis config 2023-01-10 08:48:39 -08:00
Stefano Borghi dc14604f3e Check resource before reading (#803) 2022-09-20 09:13:12 -07:00
Stefano Borghi b000013f22 check resource before writing (#799) 2022-09-19 12:27:07 -07:00
angeljqv d6da14daa8 Don't export changeling and contribution notes 2022-04-05 09:13:30 -07:00
Andrii Dembitskyi acb2460f4c PHP 8.1 and symfony/error handler deprecations (#748)
* Be sure that position always have type integer

* Annotate properly return types for SPL interfaces implementation

It is allows avoiding deprecation messages from `symfony/error-handler` like a '[info] User Deprecated: Method "Iterator::rewind()" might add "void" as a native return type declaration in the future. Do the same in implementation "Predis\Collection\Iterator\CursorBasedIterator" now to avoid errors or add an explicit @return annotation to suppress this message.'

Fixed via `symfony/error-handler` patch script: ` SYMFONY_PATCH_TYPE_DECLARATIONS="force=phpdoc&php=5.3" ./vendor/bin/patch-type-declarations` and some additional manual work

Some details about why this is necessary and how checks with trigger deprecations works: https://wouterj.nl/2021/09/symfony-6-native-typing
2022-03-15 10:50:51 -07:00
Karol Hrusza 213f00042f Add clear method to pipeline (#749)
* Add clear method to pipeline

Ability to clean pipeline and responses when reusing pipelines.
Allows pipeline to be executed using chunks without out-of-control
increase in memory usage.

* spacing

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2022-03-11 08:48:10 -08:00
Julian Haupt ab0c46332c throw exception if connection->read() returns an error object in cons… (#746)
* throw exception if connection->read() returns an error object in consumer

* Add test case for Consumer throwing a ServerException when no subscription could be established

* spacing

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2022-02-17 10:13:02 -08:00
Ondřej Ešler ed19ec3483 #742 create new context for socket connection (#743)
Co-authored-by: Ondřej Ešler <ondrej.esler@peoplepath.com>
2022-02-04 08:41:14 -08:00
fluffycondor 90496e76b5 Fix wrong return iterator value type: implementation returns \stdClass but it's typehinted as array (#740) 2022-01-26 09:22:03 -08:00
Till Krüss 4231c35e09 back to dev 2022-01-05 09:49:10 -08:00
Till Krüss a2fb02d738 bump version to 1.1.10 stable 2022-01-05 09:46:08 -08:00
Pim Jansen ca1f398f7c Fix for changing return types for PHP8.1 (#730)
Co-authored-by: Pim Jansen <pjansen@senet.nl>
2021-12-18 11:23:39 -08:00
kgasienica 5e07be785a bugfix/cannot-use-object-of-type-error-as-array-722 (#724)
Co-authored-by: Karol Gąsienica-Fronek <karol.gasienica-fronek@lppsa.com>
2021-12-01 10:18:59 -08:00
Till Krüss b3cd02e2ba back to dev 2021-10-05 12:03:21 -07:00
22 changed files with 177 additions and 23 deletions
+2
View File
@@ -11,3 +11,5 @@
/.travis.yml export-ignore
/phpunit.xml.dist export-ignore
/phpunit.xml.travisci export-ignore
/CHANGELOG.md export-ignore
/CONTRIBUTING.md export-ignore
+2 -7
View File
@@ -2,10 +2,8 @@ language: php
branches:
except:
- v0.5
- v0.6
- v0.6-PHP_5.2
- documentation
- main
- v2.0
before_install:
- docker run -d --rm -p 127.0.0.1:6379:6379 redis:3
@@ -36,6 +34,3 @@ matrix:
- php: 7.3
- php: 7.4
- php: 8.0
- php: nightly
allow_failures:
- php: nightly
+10 -2
View File
@@ -1,13 +1,21 @@
v1.1.10 (2022-01-05)
================================================================================
- __FIX__: Avoid PHP 8.1 deprecation notices in `Session/Handler`
- __FIX__: Fixed "Cannot use object of type Predis\Response\Error as array"
error in `Connection/Aggregate/SentinelReplication`
v1.1.9 (2021-10-05)
================================================================================
- Fixed PHP 8.1 compatibility in `StreamConnection`
- __FIX__: Fixed PHP 8.1 compatibility in `StreamConnection`
v1.1.8 (2021-09-29)
================================================================================
- Ensure compatibility with PHP 8.1.
- __FIX__: Ensure compatibility with PHP 8.1.
v1.1.7 (2021-04-04)
+1 -1
View File
@@ -1 +1 @@
1.1.9
1.1.11-dev
+2 -2
View File
@@ -10,8 +10,8 @@ name = "Predis"
desc = "Flexible and feature-complete Redis client for PHP and HHVM"
homepage = "http://github.com/nrk/predis"
license = "MIT"
version = "1.1.9"
stability = "stable"
version = "1.1.11"
stability = "devel"
channel = "pear.nrk.io"
author = "Daniele Alessandri \"nrk\" <suppakilla@gmail.com>"
+1 -1
View File
@@ -40,7 +40,7 @@ use Predis\Transaction\MultiExec as MultiExecTransaction;
*/
class Client implements ClientInterface, \IteratorAggregate
{
const VERSION = '1.1.9';
const VERSION = '1.1.11-dev';
protected $connection;
protected $options;
@@ -138,6 +138,7 @@ abstract class CursorBasedIterator implements \Iterator
/**
* {@inheritdoc}
* @return void
*/
#[\ReturnTypeWillChange]
public function rewind()
@@ -148,6 +149,7 @@ abstract class CursorBasedIterator implements \Iterator
/**
* {@inheritdoc}
* @return mixed
*/
#[\ReturnTypeWillChange]
public function current()
@@ -157,6 +159,7 @@ abstract class CursorBasedIterator implements \Iterator
/**
* {@inheritdoc}
* @return int
*/
#[\ReturnTypeWillChange]
public function key()
@@ -166,6 +169,7 @@ abstract class CursorBasedIterator implements \Iterator
/**
* {@inheritdoc}
* @return void
*/
#[\ReturnTypeWillChange]
public function next()
@@ -187,6 +191,7 @@ abstract class CursorBasedIterator implements \Iterator
/**
* {@inheritdoc}
* @return bool
*/
#[\ReturnTypeWillChange]
public function valid()
+5
View File
@@ -127,6 +127,7 @@ class ListKey implements \Iterator
/**
* {@inheritdoc}
* @return void
*/
#[\ReturnTypeWillChange]
public function rewind()
@@ -137,6 +138,7 @@ class ListKey implements \Iterator
/**
* {@inheritdoc}
* @return mixed
*/
#[\ReturnTypeWillChange]
public function current()
@@ -146,6 +148,7 @@ class ListKey implements \Iterator
/**
* {@inheritdoc}
* @return int
*/
#[\ReturnTypeWillChange]
public function key()
@@ -155,6 +158,7 @@ class ListKey implements \Iterator
/**
* {@inheritdoc}
* @return void
*/
#[\ReturnTypeWillChange]
public function next()
@@ -172,6 +176,7 @@ class ListKey implements \Iterator
/**
* {@inheritdoc}
* @return bool
*/
#[\ReturnTypeWillChange]
public function valid()
+7 -1
View File
@@ -197,7 +197,13 @@ class KeyPrefixProcessor implements ProcessorInterface
if ($command instanceof PrefixableCommandInterface) {
$command->prefixKeys($this->prefix);
} elseif (isset($this->commands[$commandID = strtoupper($command->getId())])) {
call_user_func($this->commands[$commandID], $command, $this->prefix);
$callable = $this->commands[$commandID];
if (is_string($callable) && 0 === strpos($callable, 'static::')) {
$callable = substr_replace($callable, get_class($this), 0, 6);
}
call_user_func($callable, $command, $this->prefix);
}
}
+3
View File
@@ -99,6 +99,7 @@ class ProcessorChain implements \ArrayAccess, ProcessorInterface
/**
* {@inheritdoc}
* @return ProcessorInterface|null
*/
#[\ReturnTypeWillChange]
public function offsetGet($index)
@@ -108,6 +109,7 @@ class ProcessorChain implements \ArrayAccess, ProcessorInterface
/**
* {@inheritdoc}
* @return void
*/
#[\ReturnTypeWillChange]
public function offsetSet($index, $processor)
@@ -124,6 +126,7 @@ class ProcessorChain implements \ArrayAccess, ProcessorInterface
/**
* {@inheritdoc}
* @return void
*/
#[\ReturnTypeWillChange]
public function offsetUnset($index)
@@ -20,6 +20,7 @@ use Predis\Connection\NodeConnectionInterface;
use Predis\Connection\Parameters;
use Predis\Replication\ReplicationStrategy;
use Predis\Replication\RoleException;
use Predis\Response\Error;
use Predis\Response\ErrorInterface as ErrorResponseInterface;
use Predis\Response\ServerException;
@@ -523,13 +524,17 @@ class SentinelReplication implements ReplicationInterface
* @param NodeConnectionInterface $connection Connection to a redis server.
* @param string $role Expected role of the server ("master", "slave" or "sentinel").
*
* @throws RoleException
* @throws RoleException|ConnectionException
*/
protected function assertConnectionRole(NodeConnectionInterface $connection, $role)
{
$role = strtolower($role);
$actualRole = $connection->executeCommand(RawCommand::create('ROLE'));
if ($actualRole instanceof Error) {
throw new ConnectionException($connection, $actualRole->getMessage());
}
if ($role !== $actualRole[0]) {
throw new RoleException($connection, "Expected $role but got $actualRole[0] [$connection]");
}
+2 -1
View File
@@ -123,8 +123,9 @@ class PhpiredisStreamConnection extends StreamConnection
{
$socket = null;
$timeout = (isset($parameters->timeout) ? (float) $parameters->timeout : 5.0);
$context = stream_context_create();
$resource = @stream_socket_client($address, $errno, $errstr, $timeout, $flags);
$resource = @stream_socket_client($address, $errno, $errstr, $timeout, $flags, $context);
if (!$resource) {
$this->onConnectionError(trim($errstr), $errno);
+4 -3
View File
@@ -123,8 +123,9 @@ class StreamConnection extends AbstractConnection
protected function createStreamSocket(ParametersInterface $parameters, $address, $flags)
{
$timeout = (isset($parameters->timeout) ? (float) $parameters->timeout : 5.0);
$context = stream_context_create();
if (!$resource = @stream_socket_client($address, $errno, $errstr, $timeout, $flags)) {
if (!$resource = @stream_socket_client($address, $errno, $errstr, $timeout, $flags, $context)) {
$this->onConnectionError(trim($errstr), $errno);
}
@@ -288,7 +289,7 @@ class StreamConnection extends AbstractConnection
$socket = $this->getResource();
while (($length = strlen($buffer)) > 0) {
$written = @fwrite($socket, $buffer);
$written = is_resource($socket) ? @fwrite($socket, $buffer) : false;
if ($length === $written) {
return;
@@ -332,7 +333,7 @@ class StreamConnection extends AbstractConnection
$bytesLeft = ($size += 2);
do {
$chunk = fread($socket, min($bytesLeft, 4096));
$chunk = is_resource($socket) ? fread($socket, min($bytesLeft, 4096)) : false;
if ($chunk === false || $chunk === '') {
$this->onConnectionError('Error while reading bytes from the server.');
+4 -1
View File
@@ -24,7 +24,7 @@ class Consumer implements \Iterator
{
private $client;
private $valid;
private $position;
private $position = 0;
/**
* @param ClientInterface $client Client instance used by the consumer.
@@ -90,6 +90,7 @@ class Consumer implements \Iterator
/**
* {@inheritdoc}
* @return void
*/
#[\ReturnTypeWillChange]
public function rewind()
@@ -110,6 +111,7 @@ class Consumer implements \Iterator
/**
* {@inheritdoc}
* @return int
*/
#[\ReturnTypeWillChange]
public function key()
@@ -119,6 +121,7 @@ class Consumer implements \Iterator
/**
* {@inheritdoc}
* @return void
*/
#[\ReturnTypeWillChange]
public function next()
+13
View File
@@ -225,6 +225,19 @@ class Pipeline implements ClientContextInterface
return $this->responses;
}
/**
* Clear the buffer holding all of the commands and responses.
*
* @return $this
*/
public function clear()
{
$this->responses = array();
$this->pipeline = new \SplQueue();
return $this;
}
/**
* Returns if the pipeline should throw exceptions on server errors.
*
+5 -3
View File
@@ -30,7 +30,7 @@ abstract class AbstractConsumer implements \Iterator
const STATUS_SUBSCRIBED = 2; // 0b0010
const STATUS_PSUBSCRIBED = 4; // 0b0100
private $position = null;
private $position = 0;
private $statusFlags = self::STATUS_VALID;
/**
@@ -150,6 +150,7 @@ abstract class AbstractConsumer implements \Iterator
/**
* {@inheritdoc}
* @return void
*/
#[\ReturnTypeWillChange]
public function rewind()
@@ -161,7 +162,7 @@ abstract class AbstractConsumer implements \Iterator
* Returns the last message payload retrieved from the server and generated
* by one of the active subscriptions.
*
* @return array
* @return \stdClass
*/
#[\ReturnTypeWillChange]
public function current()
@@ -171,6 +172,7 @@ abstract class AbstractConsumer implements \Iterator
/**
* {@inheritdoc}
* @return int
*/
#[\ReturnTypeWillChange]
public function key()
@@ -218,7 +220,7 @@ abstract class AbstractConsumer implements \Iterator
* Waits for a new message from the server generated by one of the active
* subscriptions and returns it when available.
*
* @return array
* @return \stdClass
*/
abstract protected function getValue();
}
+6
View File
@@ -16,6 +16,8 @@ use Predis\ClientInterface;
use Predis\Command\Command;
use Predis\Connection\AggregateConnectionInterface;
use Predis\NotSupportedException;
use Predis\Response\ServerException;
use Predis\Response\Error;
/**
* PUB/SUB consumer abstraction.
@@ -116,6 +118,10 @@ class Consumer extends AbstractConsumer
{
$response = $this->client->getConnection()->read();
if ($response instanceof Error) {
throw new ServerException($response->getMessage());
}
switch ($response[0]) {
case self::SUBSCRIBE:
case self::UNSUBSCRIBE:
@@ -33,6 +33,7 @@ abstract class MultiBulkIterator implements \Iterator, \Countable, ResponseInter
/**
* {@inheritdoc}
* @return void
*/
#[\ReturnTypeWillChange]
public function rewind()
@@ -42,6 +43,7 @@ abstract class MultiBulkIterator implements \Iterator, \Countable, ResponseInter
/**
* {@inheritdoc}
* @return mixed
*/
#[\ReturnTypeWillChange]
public function current()
@@ -51,6 +53,7 @@ abstract class MultiBulkIterator implements \Iterator, \Countable, ResponseInter
/**
* {@inheritdoc}
* @return int
*/
#[\ReturnTypeWillChange]
public function key()
@@ -60,6 +63,7 @@ abstract class MultiBulkIterator implements \Iterator, \Countable, ResponseInter
/**
* {@inheritdoc}
* @return void
*/
#[\ReturnTypeWillChange]
public function next()
@@ -71,6 +75,7 @@ abstract class MultiBulkIterator implements \Iterator, \Countable, ResponseInter
/**
* {@inheritdoc}
* @return bool
*/
#[\ReturnTypeWillChange]
public function valid()
+1
View File
@@ -60,6 +60,7 @@ class MultiBulkTuple extends MultiBulk implements \OuterIterator
/**
* {@inheritdoc}
* @return \Iterator
*/
#[\ReturnTypeWillChange]
public function getInnerIterator()
+12
View File
@@ -64,7 +64,9 @@ class Handler implements \SessionHandlerInterface
/**
* {@inheritdoc}
* @return bool
*/
#[\ReturnTypeWillChange]
public function open($save_path, $session_id)
{
// NOOP
@@ -73,7 +75,9 @@ class Handler implements \SessionHandlerInterface
/**
* {@inheritdoc}
* @return bool
*/
#[\ReturnTypeWillChange]
public function close()
{
// NOOP
@@ -82,7 +86,9 @@ class Handler implements \SessionHandlerInterface
/**
* {@inheritdoc}
* @return int|bool
*/
#[\ReturnTypeWillChange]
public function gc($maxlifetime)
{
// NOOP
@@ -91,7 +97,9 @@ class Handler implements \SessionHandlerInterface
/**
* {@inheritdoc}
* @return string
*/
#[\ReturnTypeWillChange]
public function read($session_id)
{
if ($data = $this->client->get($session_id)) {
@@ -102,7 +110,9 @@ class Handler implements \SessionHandlerInterface
}
/**
* {@inheritdoc}
* @return bool
*/
#[\ReturnTypeWillChange]
public function write($session_id, $session_data)
{
$this->client->setex($session_id, $this->ttl, $session_data);
@@ -112,7 +122,9 @@ class Handler implements \SessionHandlerInterface
/**
* {@inheritdoc}
* @return bool
*/
#[\ReturnTypeWillChange]
public function destroy($session_id)
{
$this->client->del($session_id);
+53
View File
@@ -234,6 +234,59 @@ class PipelineTest extends PredisTestCase
$this->assertSame(array('one', 'two', 'three', 'four'), $pipeline->execute());
}
/**
* @group disconnected
*/
public function testClearBuffer()
{
$connection = $this->getMock('Predis\Connection\NodeConnectionInterface');
$connection->expects($this->never())
->method('writeRequest');
$connection->expects($this->never())
->method('readResponse')
->will($this->returnCallback($this->getReadCallback()));
$pipeline = new Pipeline(new Client($connection));
$pipeline->echo('one');
$pipeline->echo('two');
$pipeline->clear();
$this->assertSame(array(), $pipeline->execute());
}
/**
* @group disconnected
*/
public function testClearResponses()
{
$connection = $this->getMock('Predis\Connection\NodeConnectionInterface');
$connection->expects($this->exactly(4))
->method('writeRequest');
$connection->expects($this->exactly(4))
->method('readResponse')
->will($this->returnCallback($this->getReadCallback()));
$pipeline = new Pipeline(new Client($connection));
$pipeline->echo('one');
$pipeline->echo('two');
$this->assertSame(array('one', 'two'), $pipeline->execute());
$pipeline->clear();
$pipeline->echo('three');
$pipeline->echo('four');
$this->assertSame(array('three', 'four'), $pipeline->execute());
$pipeline->clear();
$this->assertSame(array(), $pipeline->execute());
}
/**
* @group disconnected
*/
+28
View File
@@ -426,4 +426,32 @@ class ConsumerTest extends PredisTestCase
exit(0);
}
}
/**
* @group connected
* @expectedException \Predis\Response\ServerException
*/
public function testInvalidSubscriptionThrowsServerException()
{
$parameters = array(
'host' => REDIS_SERVER_HOST,
'port' => REDIS_SERVER_PORT,
'database' => REDIS_SERVER_DBNUM,
'read_write_timeout' => -1, // -1 to set blocking reads
);
$options = array('profile' => REDIS_SERVER_VERSION);
$consumer = new Client($parameters, $options);
$consumer->connect();
$pubsub = $consumer->pubSubLoop();
// calling psubscribe with invalid empty parameter list
$pubsub->psubscribe(array());
foreach ($pubsub as $message) {
// should trigger the ServerException
}
}
}