Bladeren bron

Add missing command: MIGRATE (Redis 2.6.0).

Fixes #209.
Daniele Alessandri 9 jaren geleden
bovenliggende
commit
474f3ddbe7

+ 49 - 0
src/Command/KeyMigrate.php

@@ -0,0 +1,49 @@
+<?php
+
+/*
+ * This file is part of the Predis package.
+ *
+ * (c) Daniele Alessandri <suppakilla@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Predis\Command;
+
+/**
+ * @link http://redis.io/commands/migrate
+ * @author Daniele Alessandri <suppakilla@gmail.com>
+ */
+class KeyMigrate extends Command
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function getId()
+    {
+        return 'MIGRATE';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function filterArguments(array $arguments)
+    {
+        if (is_array(end($arguments))) {
+            foreach (array_pop($arguments) as $modifier => $value) {
+                $modifier = strtoupper($modifier);
+
+                if ($modifier === 'COPY' && $value == true) {
+                    $arguments[] = $modifier;
+                }
+
+                if ($modifier === 'REPLACE' && $value == true) {
+                    $arguments[] = $modifier;
+                }
+            }
+        }
+
+        return $arguments;
+    }
+}

+ 15 - 0
src/Command/Processor/KeyPrefixProcessor.php

@@ -145,6 +145,7 @@ class KeyPrefixProcessor implements ProcessorInterface
             'HINCRBYFLOAT'              => 'self::first',
             'EVAL'                      => 'self::evalKeys',
             'EVALSHA'                   => 'self::evalKeys',
+            'MIGRATE'                   => 'self::migrate',
             /* ---------------- Redis 2.8 ---------------- */
             'SSCAN'                     => 'self::first',
             'ZSCAN'                     => 'self::first',
@@ -396,4 +397,18 @@ class KeyPrefixProcessor implements ProcessorInterface
             $command->setRawArguments($arguments);
         }
     }
+
+    /**
+     * Applies the specified prefix to the key of a MIGRATE command.
+     *
+     * @param CommandInterface $command Command instance.
+     * @param string           $prefix  Prefix string.
+     */
+    public static function migrate(CommandInterface $command, $prefix)
+    {
+        if ($arguments = $command->getArguments()) {
+            $arguments[2] = "$prefix{$arguments[2]}";
+            $command->setRawArguments($arguments);
+        }
+    }
 }

+ 1 - 0
src/Profile/RedisVersion260.php

@@ -211,6 +211,7 @@ class RedisVersion260 extends RedisProfile
             'PTTL'                      => 'Predis\Command\KeyPreciseTimeToLive',
             'PEXPIRE'                   => 'Predis\Command\KeyPreciseExpire',
             'PEXPIREAT'                 => 'Predis\Command\KeyPreciseExpireAt',
+            'MIGRATE'                   => 'Predis\Command\KeyMigrate',
 
             /* commands operating on string values */
             'PSETEX'                    => 'Predis\Command\StringPreciseSetExpire',

+ 1 - 0
src/Profile/RedisVersion280.php

@@ -211,6 +211,7 @@ class RedisVersion280 extends RedisProfile
             'PTTL'                      => 'Predis\Command\KeyPreciseTimeToLive',
             'PEXPIRE'                   => 'Predis\Command\KeyPreciseExpire',
             'PEXPIREAT'                 => 'Predis\Command\KeyPreciseExpireAt',
+            'MIGRATE'                   => 'Predis\Command\KeyMigrate',
 
             /* commands operating on string values */
             'PSETEX'                    => 'Predis\Command\StringPreciseSetExpire',

+ 1 - 0
src/Profile/RedisVersion300.php

@@ -211,6 +211,7 @@ class RedisVersion300 extends RedisProfile
             'PTTL'                      => 'Predis\Command\KeyPreciseTimeToLive',
             'PEXPIRE'                   => 'Predis\Command\KeyPreciseExpire',
             'PEXPIREAT'                 => 'Predis\Command\KeyPreciseExpireAt',
+            'MIGRATE'                   => 'Predis\Command\KeyMigrate',
 
             /* commands operating on string values */
             'PSETEX'                    => 'Predis\Command\StringPreciseSetExpire',

+ 112 - 0
tests/Predis/Command/KeyMigrateTest.php

@@ -0,0 +1,112 @@
+<?php
+
+/*
+ * This file is part of the Predis package.
+ *
+ * (c) Daniele Alessandri <suppakilla@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Predis\Command;
+
+/**
+ * @group commands
+ * @group realm-key
+ */
+class KeyMigrateTest extends PredisCommandTestCase
+{
+    /**
+     * {@inheritdoc}
+     */
+    protected function getExpectedCommand()
+    {
+        return 'Predis\Command\KeyMigrate';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function getExpectedId()
+    {
+        return 'MIGRATE';
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testFilterArguments()
+    {
+        $arguments = array('127.0.0.1', '6379', 'key', '0', '10');
+        $expected = array('127.0.0.1', '6379', 'key', '0', '10');
+
+        $command = $this->getCommand();
+        $command->setArguments($arguments);
+
+        $this->assertSame($expected, $command->getArguments());
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testFilterArgumentsRedis300()
+    {
+        $arguments = array('127.0.0.1', '6379', 'key', '0', '10', 'COPY', 'REPLACE');
+        $expected = array('127.0.0.1', '6379', 'key', '0', '10', 'COPY', 'REPLACE');
+
+        $command = $this->getCommand();
+        $command->setArguments($arguments);
+
+        $this->assertSame($expected, $command->getArguments());
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testFilterArgumentsWithOptionsArray()
+    {
+        $arguments = array('127.0.0.1', '6379', 'key', '0', '10', array('COPY' => true, 'REPLACE' => true));
+        $expected = array('127.0.0.1', '6379', 'key', '0', '10', 'COPY', 'REPLACE');
+
+        $command = $this->getCommand();
+        $command->setArguments($arguments);
+
+        $this->assertSame($expected, $command->getArguments());
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testParseResponse()
+    {
+        $command = $this->getCommand();
+
+        $this->assertSame('OK', $command->parseResponse('OK'));
+    }
+
+    /**
+     * @group connected
+     */
+    public function testReturnsStatusNOKEYOnNonExistingKey()
+    {
+        $redis = $this->getClient();
+
+        $this->assertEquals('NOKEY', $response = $redis->migrate('169.254.10.10', 16379, 'foo', 15, 1));
+        $this->assertInstanceOf('Predis\Response\Status', $response);
+    }
+
+    /**
+     * @group connected
+     * @group slow
+     * @expectedException \Predis\Response\ServerException
+     * @expectedExceptionMessage IOERR
+     */
+    public function testReturnsErrorOnUnreacheableDestination()
+    {
+        $redis = $this->getClient();
+
+        $redis->set('foo', 'bar');
+        $redis->migrate('169.254.10.10', 16379, 'foo', 15, 1);
+    }
+}

+ 31 - 0
tests/Predis/Command/Processor/KeyPrefixProcessorTest.php

@@ -217,6 +217,7 @@ class KeyPrefixProcessorTest extends PredisTestCase
         KeyPrefixProcessor::zsetStore($command, 'prefix:');
         $this->assertEmpty($command->getArguments());
     }
+
     /**
      * @group disconnected
      */
@@ -240,6 +241,27 @@ class KeyPrefixProcessorTest extends PredisTestCase
         $this->assertEmpty($command->getArguments());
     }
 
+    /**
+     * @group disconnected
+     */
+    public function testPrefixMigrate()
+    {
+        $arguments = array('127.0.0.1', '6379', 'key', '0', '10', 'COPY', 'REPLACE');
+        $expected = array('127.0.0.1', '6379', 'prefix:key', '0', '10', 'COPY', 'REPLACE');
+
+        $command = $this->getMockForAbstractClass('Predis\Command\Command');
+        $command->setRawArguments($arguments);
+
+        KeyPrefixProcessor::migrate($command, 'prefix:');
+        $this->assertSame($expected, $command->getArguments());
+
+        // Empty arguments
+        $command = $this->getMockForAbstractClass('Predis\Command\Command');
+
+        KeyPrefixProcessor::sort($command, 'prefix:');
+        $this->assertEmpty($command->getArguments());
+    }
+
     /**
      * @group disconnected
      * @dataProvider commandArgumentsDataProvider
@@ -792,6 +814,10 @@ class KeyPrefixProcessorTest extends PredisTestCase
                 array('key', 0),
                 array('prefix:key', 0),
             ),
+            array('MIGRATE',
+                array('127.0.0.1', '6379', 'key', '0', '10'),
+                array('127.0.0.1', '6379', 'prefix:key', '0', '10'),
+            ),
             /* ---------------- Redis 2.8 ---------------- */
             array('SSCAN',
                 array('key', '0', 'MATCH', 'member:*', 'COUNT', 10),
@@ -833,6 +859,11 @@ class KeyPrefixProcessorTest extends PredisTestCase
                 array('key', '+', '-', 'LIMIT', '0', '10'),
                 array('prefix:key', '+', '-', 'LIMIT', '0', '10'),
             ),
+            /* ---------------- Redis 3.0 ---------------- */
+            array('MIGRATE',
+                array('127.0.0.1', '6379', 'key', '0', '10', 'COPY', 'REPLACE'),
+                array('127.0.0.1', '6379', 'prefix:key', '0', '10', 'COPY', 'REPLACE'),
+            ),
         );
     }
 }

+ 25 - 24
tests/Predis/Profile/RedisUnstableTest.php

@@ -164,30 +164,31 @@ class RedisUnstableTest extends PredisProfileTestCase
             123 => 'PTTL',
             124 => 'PEXPIRE',
             125 => 'PEXPIREAT',
-            126 => 'PSETEX',
-            127 => 'INCRBYFLOAT',
-            128 => 'BITOP',
-            129 => 'BITCOUNT',
-            130 => 'HINCRBYFLOAT',
-            131 => 'EVAL',
-            132 => 'EVALSHA',
-            133 => 'SCRIPT',
-            134 => 'TIME',
-            135 => 'SENTINEL',
-            136 => 'SCAN',
-            137 => 'BITPOS',
-            138 => 'SSCAN',
-            139 => 'ZSCAN',
-            140 => 'ZLEXCOUNT',
-            141 => 'ZRANGEBYLEX',
-            142 => 'ZREMRANGEBYLEX',
-            143 => 'ZREVRANGEBYLEX',
-            144 => 'HSCAN',
-            145 => 'PUBSUB',
-            146 => 'PFADD',
-            147 => 'PFCOUNT',
-            148 => 'PFMERGE',
-            149 => 'COMMAND',
+            126 => 'MIGRATE',
+            127 => 'PSETEX',
+            128 => 'INCRBYFLOAT',
+            129 => 'BITOP',
+            130 => 'BITCOUNT',
+            131 => 'HINCRBYFLOAT',
+            132 => 'EVAL',
+            133 => 'EVALSHA',
+            134 => 'SCRIPT',
+            135 => 'TIME',
+            136 => 'SENTINEL',
+            137 => 'SCAN',
+            138 => 'BITPOS',
+            139 => 'SSCAN',
+            140 => 'ZSCAN',
+            141 => 'ZLEXCOUNT',
+            142 => 'ZRANGEBYLEX',
+            143 => 'ZREMRANGEBYLEX',
+            144 => 'ZREVRANGEBYLEX',
+            145 => 'HSCAN',
+            146 => 'PUBSUB',
+            147 => 'PFADD',
+            148 => 'PFCOUNT',
+            149 => 'PFMERGE',
+            150 => 'COMMAND',
         );
     }
 }

+ 11 - 10
tests/Predis/Profile/RedisVersion260Test.php

@@ -164,16 +164,17 @@ class RedisVersion260Test extends PredisProfileTestCase
             123 => 'PTTL',
             124 => 'PEXPIRE',
             125 => 'PEXPIREAT',
-            126 => 'PSETEX',
-            127 => 'INCRBYFLOAT',
-            128 => 'BITOP',
-            129 => 'BITCOUNT',
-            130 => 'HINCRBYFLOAT',
-            131 => 'EVAL',
-            132 => 'EVALSHA',
-            133 => 'SCRIPT',
-            134 => 'TIME',
-            135 => 'SENTINEL',
+            126 => 'MIGRATE',
+            127 => 'PSETEX',
+            128 => 'INCRBYFLOAT',
+            129 => 'BITOP',
+            130 => 'BITCOUNT',
+            131 => 'HINCRBYFLOAT',
+            132 => 'EVAL',
+            133 => 'EVALSHA',
+            134 => 'SCRIPT',
+            135 => 'TIME',
+            136 => 'SENTINEL',
         );
     }
 }

+ 25 - 24
tests/Predis/Profile/RedisVersion280Test.php

@@ -164,30 +164,31 @@ class RedisVersion280Test extends PredisProfileTestCase
             123 => 'PTTL',
             124 => 'PEXPIRE',
             125 => 'PEXPIREAT',
-            126 => 'PSETEX',
-            127 => 'INCRBYFLOAT',
-            128 => 'BITOP',
-            129 => 'BITCOUNT',
-            130 => 'HINCRBYFLOAT',
-            131 => 'EVAL',
-            132 => 'EVALSHA',
-            133 => 'SCRIPT',
-            134 => 'TIME',
-            135 => 'SENTINEL',
-            136 => 'SCAN',
-            137 => 'BITPOS',
-            138 => 'SSCAN',
-            139 => 'ZSCAN',
-            140 => 'ZLEXCOUNT',
-            141 => 'ZRANGEBYLEX',
-            142 => 'ZREMRANGEBYLEX',
-            143 => 'ZREVRANGEBYLEX',
-            144 => 'HSCAN',
-            145 => 'PUBSUB',
-            146 => 'PFADD',
-            147 => 'PFCOUNT',
-            148 => 'PFMERGE',
-            149 => 'COMMAND',
+            126 => 'MIGRATE',
+            127 => 'PSETEX',
+            128 => 'INCRBYFLOAT',
+            129 => 'BITOP',
+            130 => 'BITCOUNT',
+            131 => 'HINCRBYFLOAT',
+            132 => 'EVAL',
+            133 => 'EVALSHA',
+            134 => 'SCRIPT',
+            135 => 'TIME',
+            136 => 'SENTINEL',
+            137 => 'SCAN',
+            138 => 'BITPOS',
+            139 => 'SSCAN',
+            140 => 'ZSCAN',
+            141 => 'ZLEXCOUNT',
+            142 => 'ZRANGEBYLEX',
+            143 => 'ZREMRANGEBYLEX',
+            144 => 'ZREVRANGEBYLEX',
+            145 => 'HSCAN',
+            146 => 'PUBSUB',
+            147 => 'PFADD',
+            148 => 'PFCOUNT',
+            149 => 'PFMERGE',
+            150 => 'COMMAND',
         );
     }
 }

+ 25 - 24
tests/Predis/Profile/RedisVersion300Test.php

@@ -164,30 +164,31 @@ class RedisVersion300Test extends PredisProfileTestCase
             123 => 'PTTL',
             124 => 'PEXPIRE',
             125 => 'PEXPIREAT',
-            126 => 'PSETEX',
-            127 => 'INCRBYFLOAT',
-            128 => 'BITOP',
-            129 => 'BITCOUNT',
-            130 => 'HINCRBYFLOAT',
-            131 => 'EVAL',
-            132 => 'EVALSHA',
-            133 => 'SCRIPT',
-            134 => 'TIME',
-            135 => 'SENTINEL',
-            136 => 'SCAN',
-            137 => 'BITPOS',
-            138 => 'SSCAN',
-            139 => 'ZSCAN',
-            140 => 'ZLEXCOUNT',
-            141 => 'ZRANGEBYLEX',
-            142 => 'ZREMRANGEBYLEX',
-            143 => 'ZREVRANGEBYLEX',
-            144 => 'HSCAN',
-            145 => 'PUBSUB',
-            146 => 'PFADD',
-            147 => 'PFCOUNT',
-            148 => 'PFMERGE',
-            149 => 'COMMAND',
+            126 => 'MIGRATE',
+            127 => 'PSETEX',
+            128 => 'INCRBYFLOAT',
+            129 => 'BITOP',
+            130 => 'BITCOUNT',
+            131 => 'HINCRBYFLOAT',
+            132 => 'EVAL',
+            133 => 'EVALSHA',
+            134 => 'SCRIPT',
+            135 => 'TIME',
+            136 => 'SENTINEL',
+            137 => 'SCAN',
+            138 => 'BITPOS',
+            139 => 'SSCAN',
+            140 => 'ZSCAN',
+            141 => 'ZLEXCOUNT',
+            142 => 'ZRANGEBYLEX',
+            143 => 'ZREMRANGEBYLEX',
+            144 => 'ZREVRANGEBYLEX',
+            145 => 'HSCAN',
+            146 => 'PUBSUB',
+            147 => 'PFADD',
+            148 => 'PFCOUNT',
+            149 => 'PFMERGE',
+            150 => 'COMMAND',
         );
     }
 }