Added stream commands to ClusterStrategy (#1708)

* Added stream commands to ClusterStrategy

* Fix edge case for XREADGROUP

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Fix merge conflict

---------

Co-authored-by: Vladyslav Vildanov <117659936+vladvildanov@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Róbert Kelčák
2026-07-22 11:26:19 +02:00
committed by GitHub
parent 422990b631
commit c9494ab124
4 changed files with 325 additions and 0 deletions
+122
View File
@@ -208,6 +208,80 @@ class RedisStrategyTest extends PredisTestCase
/**
* @group disconnected
*/
public function testKeysForStreamCommands(): void
{
$strategy = $this->getClusterStrategy();
$commands = $this->getCommandFactory();
// These commands drop or reshape their arguments unless all of them are given.
$arguments = [
'XACKDEL' => ['key', 'group', 'KEEPREF', ['1-1']],
'XCLAIM' => ['key', 'group', 'consumer', 0, ['1-1']],
'XDELEX' => ['key', 'KEEPREF', ['1-1']],
'XNACK' => ['key', 'group', 'silent', ['1-1']],
'XPENDING' => ['key', 'group'],
];
foreach ($this->getExpectedCommands('keys-stream') as $commandID) {
$command = $commands->create($commandID, $arguments[$commandID]);
$this->assertNotNull($strategy->getSlot($command), $commandID);
}
}
/**
* @group disconnected
*/
public function testKeysForStreamSubcommands(): void
{
$strategy = $this->getClusterStrategy();
$commands = $this->getCommandFactory();
// The key of these commands follows the subcommand.
$arguments = [
'XGROUP' => ['CREATE', 'key', 'group', '$'],
'XINFO' => ['GROUPS', 'key'],
];
foreach ($this->getExpectedCommands('keys-stream-subcommand') as $commandID) {
$command = $commands->create($commandID, $arguments[$commandID]);
$this->assertNotNull($strategy->getSlot($command), $commandID);
}
}
/**
* @group disconnected
*/
public function testReturnsNullOnStreamSubcommandsWithoutKey(): void
{
$strategy = $this->getClusterStrategy();
$commands = $this->getCommandFactory();
foreach ($this->getExpectedCommands('keys-stream-subcommand') as $commandID) {
$command = $commands->create($commandID, ['HELP']);
$this->assertNull($strategy->getSlot($command), $commandID);
}
}
/**
* @group disconnected
*/
public function testKeysForStreamReadCommands(): void
{
$strategy = $this->getClusterStrategy();
$commands = $this->getCommandFactory();
// The keys follow the STREAMS token and are trailed by the same number of IDs.
$arguments = [
'XREAD' => [null, null, ['{key}:1', '{key}:2'], '0', '0'],
'XREADGROUP' => ['group', 'consumer', null, null, false, '{key}:1', '{key}:2', '0', '0'],
];
foreach ($this->getExpectedCommands('keys-stream-read') as $commandID) {
$command = $commands->create($commandID, $arguments[$commandID]);
$this->assertNotNull($strategy->getSlot($command), $commandID);
}
}
public function testKeysForFirstTwoKeysCommands(): void
{
$strategy = $this->getClusterStrategy();
@@ -220,6 +294,38 @@ class RedisStrategyTest extends PredisTestCase
}
}
/**
* @group disconnected
*/
public function testKeysForStreamReadCommandsWithReservedNames(): void
{
$strategy = $this->getClusterStrategy();
$commands = $this->getCommandFactory();
// A group or a consumer may be named after the token that separates the keys.
$command = $commands->create('XREADGROUP', ['streams', 'streams', null, null, false, 'key', '0']);
$this->assertSame($strategy->getSlotByKey('key'), $strategy->getSlot($command));
}
/**
* @group disconnected
*/
public function testReturnsNullOnStreamReadCommandsWithDifferentSlots(): void
{
$strategy = $this->getClusterStrategy();
$commands = $this->getCommandFactory();
$arguments = [
'XREAD' => [null, null, ['key:1', 'key:2'], '0', '0'],
'XREADGROUP' => ['group', 'consumer', null, null, false, 'key:1', 'key:2', '0', '0'],
];
foreach ($this->getExpectedCommands('keys-stream-read') as $commandID) {
$command = $commands->create($commandID, $arguments[$commandID]);
$this->assertNull($strategy->getSlot($command), $commandID);
}
}
/**
* @group disconnected
*/
@@ -561,9 +667,25 @@ class RedisStrategyTest extends PredisTestCase
'HSTRLEN' => 'keys-first',
/* commands operating on streams */
'XACK' => 'keys-first',
'XACKDEL' => 'keys-stream',
'XADD' => 'keys-first',
'XAUTOCLAIM' => 'keys-first',
'XCFGSET' => 'keys-first',
'XCLAIM' => 'keys-stream',
'XDEL' => 'keys-first',
'XDELEX' => 'keys-stream',
'XGROUP' => 'keys-stream-subcommand',
'XINFO' => 'keys-stream-subcommand',
'XLEN' => 'keys-first',
'XNACK' => 'keys-stream',
'XPENDING' => 'keys-stream',
'XRANGE' => 'keys-first',
'XREAD' => 'keys-stream-read',
'XREADGROUP' => 'keys-stream-read',
'XREVRANGE' => 'keys-first',
'XSETID' => 'keys-first',
'XTRIM' => 'keys-first',
/* commands operating on time series */
'TS.READ' => 'keys-first',