Browse Source

Use redis-cluster rules for empty key tags for client-side sharding.

This commit represents a breaking change when the first occurrence of
"{}" is found in a key because it will produce a different hash than
previous versions of Predis, thus leading to a different partitioning.

If you really need to stick with the old behavior, you can subclass
Predis\Cluster\PredisStrategy and override extractKeyTag() using the
old implementation of this method and pass the strategy instance when
initializing the cluster connection via client options.
Daniele Alessandri 11 years ago
parent
commit
e23fd9bea8

+ 5 - 0
CHANGELOG.md

@@ -86,6 +86,11 @@ v0.9.0 (201x-xx-xx)
   they can also define the needed logic in their command classes by implementing
   `Predis\Command\PrefixableCommandInterface` just like before.
 
+- The rules for redis-cluster are now leveraged for empty key tags when using
+  client-side sharding, which means that when one or the first occurrence of {}
+  is found in a key it will most likely produce a different hash than previous
+  versions of Predis thus leading to a different partitioning in these cases.
+
 - Renamed interface `Predis\Command\Processor\CommandProcessorInterface` to a
   shorter `Predis\Command\Processor\ProcessorInterface`. Also removed interface
   for chain processors since it is basically useless.

+ 2 - 2
lib/Predis/Cluster/PredisStrategy.php

@@ -382,8 +382,8 @@ class PredisStrategy implements StrategyInterface
     protected function extractKeyTag($key)
     {
         if (false !== $start = strpos($key, '{')) {
-            if (false !== $end = strpos($key, '}', $start)) {
-                $key = substr($key, ++$start, $end - $start);
+            if (false !== ($end = strpos($key, '}', $start)) && $end !== ++$start) {
+                $key = substr($key, $start, $end - $start);
             }
         }
 

+ 6 - 2
tests/Predis/Cluster/PredisStrategyTest.php

@@ -32,10 +32,14 @@ class PredisStrategyTest extends PredisTestCase
         $this->assertSame($expected, $strategy->getKeyHash('{foo}'));
         $this->assertSame($expected, $strategy->getKeyHash('{foo}:bar'));
         $this->assertSame($expected, $strategy->getKeyHash('{foo}:baz'));
-        $this->assertSame($expected, $strategy->getKeyHash('bar:{foo}:bar'));
+        $this->assertSame($expected, $strategy->getKeyHash('bar:{foo}:baz'));
+        $this->assertSame($expected, $strategy->getKeyHash('bar:{foo}:{baz}'));
+
+        $this->assertSame($expected, $strategy->getKeyHash('bar:{foo}:baz{}'));
+        $this->assertSame(PHP_INT_SIZE == 4 ? -1346986340 : 2947980956,  $strategy->getKeyHash('{}bar:{foo}:baz'));
 
         $this->assertSame(0, $strategy->getKeyHash(''));
-        $this->assertSame(0, $strategy->getKeyHash('{}'));
+        $this->assertSame(PHP_INT_SIZE == 4 ? -1549353149 : 2745614147, $strategy->getKeyHash('{}'));
     }
 
     /**