Эх сурвалжийг харах

Users can now choose at runtime how to handle multibulk responses. The new (and optional) iterator-based approach is slightly slower than the usual fetch-all behaviour, but in certain scenarios (e.g. when dealing with massive multibulk responses) it can save a lot of memory on the client.

Daniele Alessandri 15 жил өмнө
parent
commit
0cd7b446c6
1 өөрчлөгдсөн 27 нэмэгдсэн , 2 устгасан
  1. 27 2
      lib/Predis.php

+ 27 - 2
lib/Predis.php

@@ -85,6 +85,10 @@ class Client {
         return $this->_serverProfile;
     }
 
+    public function useMultiBulkIterator($value = true) {
+        Response::useMultiBulkIterator($value);
+    }
+
     public function connect() {
         $this->_connection->connect();
     }
@@ -336,6 +340,15 @@ class ResponseMultiBulkHandler implements IResponseHandler {
     }
 }
 
+class ResponseMultiBulkStreamHandler implements IResponseHandler {
+    public function handle($socket, $prefix, $rawLength) {
+        if (!is_numeric($rawLength)) {
+            throw new ClientException("Cannot parse '$rawLength' as data length");
+        }
+        return new Utilities\MultiBulkResponseIterator($socket, (int)$rawLength);
+    }
+}
+
 class ResponseIntegerHandler implements IResponseHandler {
     public function handle($socket, $prefix, $number) {
         if (is_numeric($number)) {
@@ -357,7 +370,7 @@ class Response {
     const QUEUED  = 'QUEUED';
     const NULL    = 'nil';
 
-    private static $_prefixHandlers;
+    private static $_prefixHandlers, $_useMultiBulkIterator;
 
     private static function initializePrefixHandlers() {
         return array(
@@ -365,10 +378,22 @@ class Response {
             '-' => new ResponseErrorHandler(), 
             ':' => new ResponseIntegerHandler(), 
             '$' => new ResponseBulkHandler(), 
-            '*' => new ResponseMultiBulkHandler()
+            '*' => self::$_useMultiBulkIterator
+                    ? new ResponseMultiBulkStreamHandler()
+                    : new ResponseMultiBulkHandler()
         );
     }
 
+    public static function useMultiBulkIterator($value = null) {
+        if (is_bool($value)) {
+            self::$_useMultiBulkIterator = $value;
+            self::$_prefixHandlers = self::initializePrefixHandlers();
+        }
+        else {
+            return self::$_useMultiBulkIterator;
+        }
+    }
+
     public static function read($socket) {
         $header  = fgets($socket);
         if ($header === false) {