Jelajahi Sumber

Fix readPreference and writeConcern in MongoCollection

Andreas Braun 10 tahun lalu
induk
melakukan
197b01172c

+ 57 - 20
lib/Mongo/MongoCollection.php

@@ -13,6 +13,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
  */
 
 
+use Alcaeus\MongoDbAdapter\Helper;
 use Alcaeus\MongoDbAdapter\TypeConverter;
 use Alcaeus\MongoDbAdapter\TypeConverter;
 
 
 /**
 /**
@@ -21,6 +22,9 @@ use Alcaeus\MongoDbAdapter\TypeConverter;
  */
  */
 class MongoCollection
 class MongoCollection
 {
 {
+    use Helper\ReadPreference;
+    use Helper\WriteConcern;
+
     const ASCENDING = 1;
     const ASCENDING = 1;
     const DESCENDING = -1;
     const DESCENDING = -1;
 
 
@@ -40,16 +44,6 @@ class MongoCollection
     protected $collection;
     protected $collection;
 
 
     /**
     /**
-     * @var int<p>
-     */
-    public $w;
-
-    /**
-     * @var int <p>
-     */
-    public $wtimeout;
-
-    /**
      * Creates a new collection
      * Creates a new collection
      * @link http://www.php.net/manual/en/mongocollection.construct.php
      * @link http://www.php.net/manual/en/mongocollection.construct.php
      * @param MongoDB $db Parent database.
      * @param MongoDB $db Parent database.
@@ -61,7 +55,11 @@ class MongoCollection
     {
     {
         $this->db = $db;
         $this->db = $db;
         $this->name = $name;
         $this->name = $name;
-        $this->collection = $this->db->getDb()->selectCollection($name);
+
+        $this->setReadPreferenceFromArray($db->getReadPreference());
+        $this->setWriteConcernFromArray($db->getWriteConcern());
+
+        $this->createCollectionObject();
     }
     }
 
 
     /**
     /**
@@ -93,10 +91,29 @@ class MongoCollection
      */
      */
     public function __get($name)
     public function __get($name)
     {
     {
+        // Handle w and wtimeout properties that replicate data stored in $readPreference
+        if ($name === 'w' || $name === 'wtimeout') {
+            return $this->getWriteConcern()[$name];
+        }
+
         return $this->db->selectCollection($this->name . '.' . $name);
         return $this->db->selectCollection($this->name . '.' . $name);
     }
     }
 
 
     /**
     /**
+     * @param string $name
+     * @param mixed $value
+     */
+    public function __set($name, $value)
+    {
+        if ($name === 'w' || $name === 'wtimeout') {
+            $this->setWriteConcernFromArray([$name => $value] + $this->getWriteConcern());
+            $this->createCollectionObject();
+        } else {
+            $this->$name = $value;
+        }
+    }
+
+    /**
      * @link http://www.php.net/manual/en/mongocollection.aggregate.php
      * @link http://www.php.net/manual/en/mongocollection.aggregate.php
      * @param array $pipeline
      * @param array $pipeline
      * @param array $op
      * @param array $op
@@ -187,22 +204,25 @@ class MongoCollection
     }
     }
 
 
     /**
     /**
-     * @link http://www.php.net/manual/en/mongocollection.getreadpreference.php
-     * @return array
+     * {@inheritdoc}
      */
      */
-    public function getReadPreference()
+    public function setReadPreference($readPreference, $tags = null)
     {
     {
-        $this->notImplemented();
+        $result = $this->setReadPreferenceFromParameters($readPreference, $tags);
+        $this->createCollectionObject();
+
+        return $result;
     }
     }
 
 
     /**
     /**
-     * @param string $read_preference
-     * @param array $tags
-     * @return bool
+     * {@inheritdoc}
      */
      */
-    public function setReadPreference($read_preference, array $tags)
+    public function setWriteConcern($wstring, $wtimeout = 0)
     {
     {
-        $this->notImplemented();
+        $result = $this->setWriteConcernFromParameters($wstring, $wtimeout);
+        $this->createCollectionObject();
+
+        return $result;
     }
     }
 
 
     /**
     /**
@@ -512,5 +532,22 @@ class MongoCollection
     {
     {
         throw new \Exception('Not implemented');
         throw new \Exception('Not implemented');
     }
     }
+
+    /**
+     * @return \MongoDB\Collection
+     */
+    private function createCollectionObject()
+    {
+        $options = [
+            'readPreference' => $this->readPreference,
+            'writeConcern' => $this->writeConcern,
+        ];
+
+        if ($this->collection === null) {
+            $this->collection = $this->db->getDb()->selectCollection($this->name, $options);
+        } else {
+            $this->collection = $this->collection->withOptions($options);
+        }
+    }
 }
 }
 
 

+ 66 - 1
tests/Alcaeus/MongoDbAdapter/MongoCollectionTest.php

@@ -1,6 +1,7 @@
 <?php
 <?php
 
 
 namespace Alcaeus\MongoDbAdapter\Tests;
 namespace Alcaeus\MongoDbAdapter\Tests;
+use MongoDB\Driver\ReadPreference;
 
 
 /**
 /**
  * @author alcaeus <alcaeus@alcaeus.org>
  * @author alcaeus <alcaeus@alcaeus.org>
@@ -136,14 +137,78 @@ class MongoCollectionTest extends TestCase
         ], iterator_to_array($cursor));
         ], iterator_to_array($cursor));
     }
     }
 
 
+    public function testReadPreference()
+    {
+        $collection = $this->getCollection();
+        $this->assertSame(['type' => \MongoClient::RP_PRIMARY], $collection->getReadPreference());
+
+        $this->assertTrue($collection->setReadPreference(\MongoClient::RP_SECONDARY, ['a' => 'b']));
+        $this->assertSame(['type' => \MongoClient::RP_SECONDARY, 'tagsets' => ['a' => 'b']], $collection->getReadPreference());
+
+        // Only way to check whether options are passed down is through debugInfo
+        $writeConcern = $collection->getCollection()->__debugInfo()['readPreference'];
+
+        $this->assertSame(ReadPreference::RP_SECONDARY, $writeConcern->getMode());
+        $this->assertSame(['a' => 'b'], $writeConcern->getTagSets());
+    }
+
+    public function testReadPreferenceIsInherited()
+    {
+        $database = $this->getDatabase();
+        $database->setReadPreference(\MongoClient::RP_SECONDARY, ['a' => 'b']);
+
+        $collection = $database->selectCollection('test');
+        $this->assertSame(['type' => \MongoClient::RP_SECONDARY, 'tagsets' => ['a' => 'b']], $collection->getReadPreference());
+    }
+
+    public function testWriteConcern()
+    {
+        $collection = $this->getCollection();
+        $this->assertSame(['w' => 1, 'wtimeout' => 0], $collection->getWriteConcern());
+        $this->assertSame(1, $collection->w);
+        $this->assertSame(0, $collection->wtimeout);
+
+        $this->assertTrue($collection->setWriteConcern('majority', 100));
+        $this->assertSame(['w' => 'majority', 'wtimeout' => 100], $collection->getWriteConcern());
+
+        $collection->w = 2;
+        $this->assertSame(['w' => 2, 'wtimeout' => 100], $collection->getWriteConcern());
+
+        $collection->wtimeout = -1;
+        $this->assertSame(['w' => 2, 'wtimeout' => 0], $collection->getWriteConcern());
+
+        // Only way to check whether options are passed down is through debugInfo
+        $writeConcern = $collection->getCollection()->__debugInfo()['writeConcern'];
+
+        $this->assertSame(2, $writeConcern->getW());
+        $this->assertSame(0, $writeConcern->getWtimeout());
+    }
+
+    public function testWriteConcernIsInherited()
+    {
+        $database = $this->getDatabase();
+        $database->setWriteConcern('majority', 100);
+
+        $collection = $database->selectCollection('test');
+        $this->assertSame(['w' => 'majority', 'wtimeout' => 100], $collection->getWriteConcern());
+    }
+
     /**
     /**
      * @return \MongoCollection
      * @return \MongoCollection
      */
      */
     protected function getCollection($name = 'test')
     protected function getCollection($name = 'test')
     {
     {
+        return $this->getDatabase()->selectCollection($name);
+    }
+
+    /**
+     * @return \MongoDB
+     */
+    protected function getDatabase()
+    {
         $client = new \MongoClient();
         $client = new \MongoClient();
 
 
-        return $client->selectCollection('mongo-php-adapter', $name);
+        return $client->selectDB('mongo-php-adapter');
     }
     }
 
 
     /**
     /**