mirror of
https://github.com/predis/predis.git
synced 2026-08-24 01:39:36 +00:00
Merge branch 'command_hashing'
This commit is contained in:
@@ -3,6 +3,6 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class Auth extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'AUTH'; }
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class BackgroundRewriteAppendOnlyFile extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'BGREWRITEAOF'; }
|
||||
public function parseResponse($data) {
|
||||
return $data == 'Background append only file rewriting started';
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class BackgroundSave extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'BGSAVE'; }
|
||||
public function parseResponse($data) {
|
||||
if ($data == 'Background saving started') {
|
||||
|
||||
@@ -8,7 +8,33 @@ abstract class Command implements ICommand {
|
||||
private $_hash;
|
||||
private $_arguments = array();
|
||||
|
||||
public function canBeHashed() {
|
||||
protected function canBeHashed() {
|
||||
return isset($this->_arguments[0]);
|
||||
}
|
||||
|
||||
protected function getHashablePart($key) {
|
||||
$start = strpos($key, '{');
|
||||
if ($start !== false) {
|
||||
$end = strpos($key, '}', $start);
|
||||
if ($end !== false) {
|
||||
$key = substr($key, ++$start, $end - $start);
|
||||
}
|
||||
}
|
||||
return $key;
|
||||
}
|
||||
|
||||
protected function checkSameHashForKeys(Array $keys) {
|
||||
if (($count = count($keys)) === 0) {
|
||||
return false;
|
||||
}
|
||||
$currentKey = $this->getHashablePart($keys[0]);
|
||||
for ($i = 1; $i < $count; $i++) {
|
||||
$nextKey = $this->getHashablePart($keys[$i]);
|
||||
if ($currentKey !== $nextKey) {
|
||||
return false;
|
||||
}
|
||||
$currentKey = $nextKey;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -16,19 +42,8 @@ abstract class Command implements ICommand {
|
||||
if (isset($this->_hash)) {
|
||||
return $this->_hash;
|
||||
}
|
||||
if (isset($this->_arguments[0])) {
|
||||
// TODO: should we throw an exception if the command does not
|
||||
// support sharding?
|
||||
$key = $this->_arguments[0];
|
||||
|
||||
$start = strpos($key, '{');
|
||||
if ($start !== false) {
|
||||
$end = strpos($key, '}', $start);
|
||||
if ($end !== false) {
|
||||
$key = substr($key, ++$start, $end - $start);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->canBeHashed()) {
|
||||
$key = $this->getHashablePart($this->_arguments[0]);
|
||||
$this->_hash = $distributor->generateKey($key);
|
||||
return $this->_hash;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class Config extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'CONFIG'; }
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class DatabaseSize extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'DBSIZE'; }
|
||||
}
|
||||
|
||||
@@ -5,6 +5,13 @@ namespace Predis\Commands;
|
||||
use Predis\Utils;
|
||||
|
||||
class Delete extends Command {
|
||||
protected function canBeHashed() {
|
||||
$args = $this->getArguments();
|
||||
if (count($args) === 1) {
|
||||
return true;
|
||||
}
|
||||
return $this->checkSameHashForKeys($args);
|
||||
}
|
||||
public function getId() { return 'DEL'; }
|
||||
public function filterArguments(Array $arguments) {
|
||||
return Utils::filterArrayArguments($arguments);
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class Discard extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'DISCARD'; }
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class DoEcho extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'ECHO'; }
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class Exec extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'EXEC'; }
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class FlushAll extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'FLUSHALL'; }
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class FlushDatabase extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'FLUSHDB'; }
|
||||
}
|
||||
|
||||
@@ -5,7 +5,9 @@ namespace Predis\Commands;
|
||||
use Predis\Utils;
|
||||
|
||||
class GetMultiple extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() {
|
||||
return $this->checkSameHashForKeys($this->getArguments());
|
||||
}
|
||||
public function getId() { return 'MGET'; }
|
||||
public function filterArguments(Array $arguments) {
|
||||
return Utils::filterArrayArguments($arguments);
|
||||
|
||||
@@ -6,7 +6,6 @@ use Predis\Distribution\IDistributionStrategy;
|
||||
|
||||
interface ICommand {
|
||||
public function getId();
|
||||
public function canBeHashed();
|
||||
public function getHash(IDistributionStrategy $distributor);
|
||||
public function setArgumentsArray(Array $arguments);
|
||||
public function getArguments();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class Info extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'INFO'; }
|
||||
public function parseResponse($data) {
|
||||
$info = array();
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class InfoV24x extends Info {
|
||||
public function canBeHashed() { return false; }
|
||||
public function parseResponse($data) {
|
||||
$info = array();
|
||||
$current = null;
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class Keys extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'KEYS'; }
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class LastSave extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'LASTSAVE'; }
|
||||
}
|
||||
|
||||
@@ -3,5 +3,10 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class ListPopFirstBlocking extends Command {
|
||||
protected function canBeHashed() {
|
||||
return $this->checkSameHashForKeys(
|
||||
array_slice(($args = $this->getArguments()), 0, count($args) - 1)
|
||||
);
|
||||
}
|
||||
public function getId() { return 'BLPOP'; }
|
||||
}
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
|
||||
namespace Predis\Commands;
|
||||
|
||||
class ListPopLastBlocking extends Command {
|
||||
class ListPopLastBlocking extends ListPopFirstBlocking {
|
||||
public function getId() { return 'BRPOP'; }
|
||||
}
|
||||
|
||||
@@ -3,5 +3,8 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class ListPopLastPushHead extends Command {
|
||||
protected function canBeHashed() {
|
||||
return $this->checkSameHashForKeys($this->getArguments());
|
||||
}
|
||||
public function getId() { return 'RPOPLPUSH'; }
|
||||
}
|
||||
|
||||
@@ -3,5 +3,10 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class ListPopLastPushHeadBlocking extends Command {
|
||||
protected function canBeHashed() {
|
||||
return $this->checkSameHashForKeys(
|
||||
array_slice($args = $this->getArguments(), 0, count($args) - 1)
|
||||
);
|
||||
}
|
||||
public function getId() { return 'BRPOPLPUSH'; }
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class MoveKey extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'MOVE'; }
|
||||
public function parseResponse($data) { return (bool) $data; }
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class Multi extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'MULTI'; }
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class Ping extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'PING'; }
|
||||
public function parseResponse($data) {
|
||||
return $data === 'PONG' ? true : false;
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class Publish extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'PUBLISH'; }
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class Quit extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'QUIT'; }
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class RandomKey extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'RANDOMKEY'; }
|
||||
public function parseResponse($data) { return $data !== '' ? $data : null; }
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class Rename extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'RENAME'; }
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class RenamePreserve extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'RENAMENX'; }
|
||||
public function parseResponse($data) { return (bool) $data; }
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class Save extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'SAVE'; }
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class SelectDatabase extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'SELECT'; }
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@ namespace Predis\Commands;
|
||||
use Predis\Utils;
|
||||
|
||||
class SetIntersection extends Command {
|
||||
protected function canBeHashed() {
|
||||
return $this->checkSameHashForKeys($this->getArguments());
|
||||
}
|
||||
public function getId() { return 'SINTER'; }
|
||||
public function filterArguments(Array $arguments) {
|
||||
return Utils::filterArrayArguments($arguments);
|
||||
|
||||
@@ -5,6 +5,9 @@ namespace Predis\Commands;
|
||||
use Predis\Utils;
|
||||
|
||||
class SetIntersectionStore extends Command {
|
||||
protected function canBeHashed() {
|
||||
return $this->checkSameHashForKeys($this->getArguments());
|
||||
}
|
||||
public function getId() { return 'SINTERSTORE'; }
|
||||
public function filterArguments(Array $arguments) {
|
||||
if (count($arguments) === 2 && is_array($arguments[1])) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class SetMove extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'SMOVE'; }
|
||||
public function parseResponse($data) { return (bool) $data; }
|
||||
}
|
||||
|
||||
@@ -3,7 +3,14 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class SetMultiple extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() {
|
||||
$args = $this->getArguments();
|
||||
$keys = array();
|
||||
for ($i = 0; $i < count($args); $i += 2) {
|
||||
$keys[] = $args[$i];
|
||||
}
|
||||
return $this->checkSameHashForKeys($keys);
|
||||
}
|
||||
public function getId() { return 'MSET'; }
|
||||
public function filterArguments(Array $arguments) {
|
||||
if (count($arguments) === 1 && is_array($arguments[0])) {
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class SetMultiplePreserve extends SetMultiple {
|
||||
public function canBeHashed() { return false; }
|
||||
public function getId() { return 'MSETNX'; }
|
||||
public function parseResponse($data) { return (bool) $data; }
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class Shutdown extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'SHUTDOWN'; }
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class SlaveOf extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'SLAVEOF'; }
|
||||
public function filterArguments(Array $arguments) {
|
||||
if (count($arguments) === 0 || $arguments[0] === 'NO ONE') {
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Predis\Commands;
|
||||
use Predis\Utils;
|
||||
|
||||
class Subscribe extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'SUBSCRIBE'; }
|
||||
public function filterArguments(Array $arguments) {
|
||||
return Utils::filterArrayArguments($arguments);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class SubscribeByPattern extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'PSUBSCRIBE'; }
|
||||
public function filterArguments(Array $arguments) {
|
||||
return Utils::filterArrayArguments($arguments);
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class Unsubscribe extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'UNSUBSCRIBE'; }
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class UnsubscribeByPattern extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'PUNSUBSCRIBE'; }
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class Unwatch extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'UNWATCH'; }
|
||||
public function parseResponse($data) { return (bool) $data; }
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class Watch extends Command {
|
||||
public function canBeHashed() { return false; }
|
||||
protected function canBeHashed() { return false; }
|
||||
public function getId() { return 'WATCH'; }
|
||||
public function filterArguments(Array $arguments) {
|
||||
if (isset($arguments[0]) && is_array($arguments[0])) {
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
namespace Predis\Commands;
|
||||
|
||||
class ZSetUnionStore extends Command {
|
||||
protected function canBeHashed() {
|
||||
$args = $this->getArguments();
|
||||
return $this->checkSameHashForKeys(
|
||||
array_merge(array($args[0]), array_slice($args, 2, $args[1]))
|
||||
);
|
||||
}
|
||||
public function getId() { return 'ZUNIONSTORE'; }
|
||||
public function filterArguments(Array $arguments) {
|
||||
$options = array();
|
||||
|
||||
@@ -47,12 +47,13 @@ class ConnectionCluster implements IConnectionCluster, \IteratorAggregate {
|
||||
}
|
||||
|
||||
public function getConnection(ICommand $command) {
|
||||
if ($command->canBeHashed() === false) {
|
||||
throw new ClientException(
|
||||
sprintf("Cannot send '%s' commands to a cluster of connections", $command->getId())
|
||||
);
|
||||
$cmdHash = $command->getHash($this->_distributor);
|
||||
if (isset($cmdHash)) {
|
||||
return $this->_distributor->get($cmdHash);
|
||||
}
|
||||
return $this->_distributor->get($command->getHash($this->_distributor));
|
||||
throw new ClientException(
|
||||
sprintf("Cannot send '%s' commands to a cluster of connections", $command->getId())
|
||||
);
|
||||
}
|
||||
|
||||
public function getConnectionById($id = null) {
|
||||
|
||||
Reference in New Issue
Block a user