fix: Bug with single persistent connection to the same resource (#1512)

* fix: Bug with single persistent connection to the same resource

* Fixed tests

* Additional test fix

* Codestyle fixes
This commit is contained in:
Vladyslav Vildanov
2025-02-24 09:51:55 +02:00
committed by GitHub
parent 974379bd05
commit 09e88b6fd0
6 changed files with 65 additions and 8 deletions
+5
View File
@@ -166,6 +166,11 @@ class Parameters implements ParametersInterface
}
}
public function __set($parameter, $value)
{
$this->parameters[$parameter] = $value;
}
/**
* {@inheritdoc}
*/
+1
View File
@@ -28,6 +28,7 @@ namespace Predis\Connection;
* @property float $timeout Timeout for the connect() operation.
* @property float $read_write_timeout Timeout for read() and write() operations.
* @property bool $persistent Leaves the connection open after a GC collection.
* @property string $conn_uid Unique identifier of connection, needs to create a multiple persistent connections to the same resource.
* @property string $username Username to access Redis (see the AUTH command).
* @property string $password Password to access Redis (see the AUTH command).
* @property string $database Database index (see the SELECT command).
+12
View File
@@ -194,6 +194,18 @@ class StreamFactory implements StreamFactoryInterface
$timeout = (isset($parameters->timeout) ? (float) $parameters->timeout : 5.0);
$context = stream_context_create(['socket' => ['tcp_nodelay' => (bool) $parameters->tcp_nodelay]]);
if (
(isset($parameters->persistent) && $parameters->persistent)
&& (isset($parameters->conn_uid) && $parameters->conn_uid)
) {
$conn_uid = '/' . $parameters->conn_uid;
} else {
$conn_uid = '';
}
// Needs to create multiple persistent connections to the same resource
$address = $address . $conn_uid;
if (!$resource = @stream_socket_client($address, $errno, $errstr, $timeout, $flags, $context)) {
$this->onInitializationError($resource, $parameters, trim($errstr), $errno);
}
+1
View File
@@ -59,6 +59,7 @@ class StreamConnection extends AbstractConnection
public function __construct(ParametersInterface $parameters, ?StreamFactoryInterface $factory = null)
{
parent::__construct($parameters);
$this->parameters->conn_uid = spl_object_hash($this);
$this->streamFactory = $factory ?? new StreamFactory();
}
+38
View File
@@ -1323,6 +1323,44 @@ class ClientTest extends PredisTestCase
$this->assertSame(Client::VERSION, $libVer);
}
/**
* @group connected
*/
public function testClientsCreateDifferentPersistentConnections(): void
{
$client1 = new Client($this->getParameters(['database' => 14, 'persistent' => true]));
$client2 = new Client($this->getParameters(['database' => 15, 'persistent' => true]));
$client1->set('foo', 'bar');
$client2->set('foo', 'baz');
$this->assertSame('bar', $client1->get('foo'));
$this->assertSame('baz', $client2->get('foo'));
}
/**
* @group connected
* @group cluster
* @requiresRedisVersion >= 2.0.0
*/
public function testClusterClientsCreateDifferentPersistentConnections(): void
{
$client1 = new Client(
$this->getDefaultParametersArray(),
['cluster' => 'redis', 'parameters' => ['persistent' => true]]
);
$client2 = new Client(
$this->getDefaultParametersArray(),
['cluster' => 'redis', 'parameters' => ['persistent' => true]]
);
$client1->set('{shard1}foo', 'bar');
$client2->set('{shard2}foo', 'baz');
$this->assertSame('bar', $client1->get('{shard1}foo'));
$this->assertSame('baz', $client2->get('{shard2}foo'));
}
/**
* @group connected
* @group cluster
@@ -94,7 +94,7 @@ class StreamConnectionTest extends PredisConnectionTestCase
$this->mockStreamFactory
->expects($this->once())
->method('createStream')
->with(new Parameters())
->withAnyParameters()
->willReturn($this->mockStream);
$this->mockStream
@@ -125,7 +125,7 @@ class StreamConnectionTest extends PredisConnectionTestCase
$this->mockStreamFactory
->expects($this->once())
->method('createStream')
->with(new Parameters())
->withAnyParameters()
->willReturn($this->mockStream);
$this->mockStream
@@ -190,7 +190,7 @@ class StreamConnectionTest extends PredisConnectionTestCase
$this->mockStreamFactory
->expects($this->once())
->method('createStream')
->with(new Parameters())
->withAnyParameters()
->willReturn($this->mockStream);
$this->mockStream
@@ -215,7 +215,7 @@ class StreamConnectionTest extends PredisConnectionTestCase
$this->mockStreamFactory
->expects($this->once())
->method('createStream')
->with(new Parameters())
->withAnyParameters()
->willReturn($this->mockStream);
$this->mockStream
@@ -241,7 +241,7 @@ class StreamConnectionTest extends PredisConnectionTestCase
$this->mockStreamFactory
->expects($this->once())
->method('createStream')
->with(new Parameters())
->withAnyParameters()
->willReturn($this->mockStream);
$this->mockStream
@@ -265,7 +265,7 @@ class StreamConnectionTest extends PredisConnectionTestCase
$this->mockStreamFactory
->expects($this->once())
->method('createStream')
->with(new Parameters())
->withAnyParameters()
->willReturn($this->mockStream);
$this->mockStream
@@ -480,7 +480,7 @@ class StreamConnectionTest extends PredisConnectionTestCase
$this->mockStreamFactory
->expects($this->once())
->method('createStream')
->with(new Parameters())
->withAnyParameters()
->willReturn($this->mockStream);
$this->mockStream
@@ -503,7 +503,7 @@ class StreamConnectionTest extends PredisConnectionTestCase
$this->mockStreamFactory
->expects($this->once())
->method('createStream')
->with(new Parameters())
->withAnyParameters()
->willReturn($this->mockStream);
$this->mockStream