From ecb0de9fc1f86dee8e4a50b46f26b64b66372429 Mon Sep 17 00:00:00 2001 From: Geolim4 Date: Sun, 15 Aug 2021 06:07:06 +0200 Subject: [PATCH 1/4] Updating build + upgrading mongodb & predis dependencies --- .travis.yml | 29 +++++++++++++++-------------- bin/ci/install_dependencies.sh | 4 ++-- composer.json | 4 ++-- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/.travis.yml b/.travis.yml index 893580e45..6b6b62ad3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,20 +17,6 @@ services: - couchdb - mongodb -before_script: - - | - if [[ $TRAVIS_PHP_VERSION = "hhv"* ]]; then - cat bin/ci/hhvm_phpfastcache.ini >> /etc/hhvm/php.ini - else - pecl channel-update pecl.php.net; - yes | pecl install -f mongodb-stable; - yes | pecl install -f memcached; - yes | pecl install -f apcu-stable || true; - phpenv config-add bin/ci/php_phpfastcache.ini; - fi - - sleep 15 - - mongo pfc_test --eval 'db.createUser({user:"travis",pwd:"test",roles:["readWrite"]});' - php: - 7.3 - 7.4 @@ -51,6 +37,21 @@ jobs: php: 7.3 - dist: bionic php: 7.4 + +before_install: + - | + if [[ $TRAVIS_PHP_VERSION = "hhv"* ]]; then + cat bin/ci/hhvm_phpfastcache.ini >> /etc/hhvm/php.ini + else + pecl channel-update pecl.php.net; + yes | pecl install -f mongodb-stable; + yes | pecl install -f memcached; + yes | pecl install -f apcu-stable || true; + phpenv config-add bin/ci/php_phpfastcache.ini; + fi + - sleep 15 + - mongo pfc_test --eval 'db.createUser({user:"travis",pwd:"test",roles:["readWrite"]});' + install: - ./bin/ci/install_dependencies.sh diff --git a/bin/ci/install_dependencies.sh b/bin/ci/install_dependencies.sh index 49c8eb2f8..304831a0c 100755 --- a/bin/ci/install_dependencies.sh +++ b/bin/ci/install_dependencies.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash composer self-update; -composer install --ignore-platform-reqs; -composer require "phpfastcache/couchdb:~1.0.0" "phpfastcache/phpssdb:~1.0.0" "predis/predis:~1.1.0" "mongodb/mongodb:^1.1" --ignore-platform-reqs; +composer install; +composer require "phpfastcache/couchdb:~1.0.0" "phpfastcache/phpssdb:~1.0.0" "predis/predis:~1.1.0" "mongodb/mongodb:^1.9"; diff --git a/composer.json b/composer.json index 9bb5752a6..e6b22951e 100644 --- a/composer.json +++ b/composer.json @@ -43,8 +43,8 @@ "ext-wincache": "*", "ext-leveldb": "*", "ext-couchbase": "*", - "predis/predis": "~1.1.0", - "mongodb/mongodb": "^1.1", + "predis/predis": "^1.1", + "mongodb/mongodb": "^1.9", "phpfastcache/phpssdb": "~1.0.0", "phpfastcache/couchdb": "~1.0.0" }, From a48c904a258e4633e3560306b0a0c0aeb3458344 Mon Sep 17 00:00:00 2001 From: Geolim4 Date: Sun, 15 Aug 2021 10:48:58 +0200 Subject: [PATCH 2/4] Improved Mongodb config --- lib/Phpfastcache/Drivers/Mongodb/Config.php | 4 +- lib/Phpfastcache/Drivers/Mongodb/Driver.php | 40 +++++++----- tests/Mongodb.test.php | 70 +++------------------ 3 files changed, 33 insertions(+), 81 deletions(-) diff --git a/lib/Phpfastcache/Drivers/Mongodb/Config.php b/lib/Phpfastcache/Drivers/Mongodb/Config.php index 11f86daed..86511b622 100644 --- a/lib/Phpfastcache/Drivers/Mongodb/Config.php +++ b/lib/Phpfastcache/Drivers/Mongodb/Config.php @@ -53,7 +53,7 @@ class Config extends ConfigurationOption /** * @var string */ - protected $collectionName = 'Cache'; + protected $collectionName = 'phpfastcache'; /** * @var string @@ -273,4 +273,4 @@ public function setProtocol(string $protocol): self $this->protocol = $protocol; return $this; } -} \ No newline at end of file +} diff --git a/lib/Phpfastcache/Drivers/Mongodb/Driver.php b/lib/Phpfastcache/Drivers/Mongodb/Driver.php index 0f326daec..5575382f0 100644 --- a/lib/Phpfastcache/Drivers/Mongodb/Driver.php +++ b/lib/Phpfastcache/Drivers/Mongodb/Driver.php @@ -18,6 +18,7 @@ namespace Phpfastcache\Drivers\Mongodb; use DateTime; +use Exception; use LogicException; use MongoClient; use MongoDB\{BSON\Binary, BSON\UTCDateTime, Client, Collection, Database, DeleteResult, Driver\Command, Driver\Exception\Exception as MongoDBException, Driver\Manager}; @@ -75,7 +76,7 @@ public function driverCheck(): bool public function getStats(): DriverStatistic { $serverStats = $this->instance->getManager()->executeCommand( - 'phpFastCache', + $this->getConfig()->getDatabaseName(), new Command( [ 'serverStatus' => 1, @@ -87,10 +88,10 @@ public function getStats(): DriverStatistic )->toArray()[0]; $collectionStats = $this->instance->getManager()->executeCommand( - 'phpFastCache', + $this->getConfig()->getDatabaseName(), new Command( [ - 'collStats' => (isset($this->getConfig()['collectionName']) ? $this->getConfig()['collectionName'] : 'Cache'), + 'collStats' => $this->getConfig()->getCollectionName(), 'verbose' => true, ] ) @@ -146,25 +147,19 @@ public function getStats(): DriverStatistic */ protected function driverRead(CacheItemInterface $item) { - $document = $this->getCollection()->findOne(['_id' => $item->getEncodedKey()]); + $document = $this->getCollection()->findOne(['_id' => $this->getMongoDbItemKey($item)]); if ($document) { $return = [ self::DRIVER_DATA_WRAPPER_INDEX => $this->decode($document[self::DRIVER_DATA_WRAPPER_INDEX]->getData()), self::DRIVER_TAGS_WRAPPER_INDEX => $this->decode($document[self::DRIVER_TAGS_WRAPPER_INDEX]->getData()), - self::DRIVER_EDATE_WRAPPER_INDEX => (new DateTime())->setTimestamp($document[self::DRIVER_EDATE_WRAPPER_INDEX]->toDateTime()->getTimestamp()), + self::DRIVER_EDATE_WRAPPER_INDEX => $document[self::DRIVER_EDATE_WRAPPER_INDEX]->toDateTime(), ]; if (!empty($this->getConfig()->isItemDetailedDate())) { $return += [ - self::DRIVER_MDATE_WRAPPER_INDEX => (new DateTime())->setTimestamp( - $document[self::DRIVER_MDATE_WRAPPER_INDEX]->toDateTime() - ->getTimestamp() - ), - self::DRIVER_CDATE_WRAPPER_INDEX => (new DateTime())->setTimestamp( - $document[self::DRIVER_CDATE_WRAPPER_INDEX]->toDateTime() - ->getTimestamp() - ), + self::DRIVER_MDATE_WRAPPER_INDEX => $document[self::DRIVER_MDATE_WRAPPER_INDEX]->toDateTime(), + self::DRIVER_CDATE_WRAPPER_INDEX => $document[self::DRIVER_CDATE_WRAPPER_INDEX]->toDateTime(), ]; } @@ -196,6 +191,7 @@ protected function driverWrite(CacheItemInterface $item): bool if ($item instanceof Item) { try { $set = [ + self::DRIVER_KEY_WRAPPER_INDEX => $item->getKey(), self::DRIVER_DATA_WRAPPER_INDEX => new Binary($this->encode($item->get()), Binary::TYPE_GENERIC), self::DRIVER_TAGS_WRAPPER_INDEX => new Binary($this->encode($item->getTags()), Binary::TYPE_GENERIC), self::DRIVER_EDATE_WRAPPER_INDEX => ($item->getTtl() > 0 ? new UTCDateTime((time() + $item->getTtl()) * 1000) : new UTCDateTime(time() * 1000)), @@ -214,7 +210,7 @@ protected function driverWrite(CacheItemInterface $item): bool ]; } $result = (array)$this->getCollection()->updateOne( - ['_id' => $item->getEncodedKey()], + ['_id' => $this->getMongoDbItemKey($item)], [ '$set' => $set, ], @@ -244,7 +240,7 @@ protected function driverDelete(CacheItemInterface $item): bool /** * @var DeleteResult $deletionResult */ - $deletionResult = $this->getCollection()->deleteOne(['_id' => $item->getEncodedKey()]); + $deletionResult = $this->getCollection()->deleteOne(['_id' => $this->getMongoDbItemKey($item)]); return $deletionResult->isAcknowledged(); } @@ -257,7 +253,11 @@ protected function driverDelete(CacheItemInterface $item): bool */ protected function driverClear(): bool { - return $this->collection->deleteMany([])->isAcknowledged(); + try { + return $this->collection->deleteMany([])->isAcknowledged(); + } catch (MongoDBException $e) { + throw new PhpfastcacheDriverException('Got error while trying to empty the collection: ' . $e->getMessage(), 0, $e); + } } /** @@ -294,8 +294,9 @@ protected function driverConnect(): bool * @param string $databaseName * @return string The connection URI. */ - protected function buildConnectionURI($databaseName = ''): string + protected function buildConnectionURI(string $databaseName): string { + $databaseName = \urlencode($databaseName); $servers = $this->getConfig()->getServers(); $options = $this->getConfig()->getOptions(); @@ -332,6 +333,11 @@ static function ($carry, $data) { ); } + protected function getMongoDbItemKey(CacheItemInterface $item) + { + return 'pfc_' . $item->getEncodedKey(); + } + /******************** * * PSR-6 Extended Methods diff --git a/tests/Mongodb.test.php b/tests/Mongodb.test.php index 03ed5d207..f8785dc31 100644 --- a/tests/Mongodb.test.php +++ b/tests/Mongodb.test.php @@ -8,78 +8,24 @@ use Phpfastcache\CacheManager; use Phpfastcache\Drivers\Mongodb\Config; use Phpfastcache\Exceptions\PhpfastcacheDriverCheckException; -use Phpfastcache\Exceptions\phpFastCacheDriverException; use Phpfastcache\Tests\Helper\TestHelper; chdir(__DIR__); require_once __DIR__ . '/../vendor/autoload.php'; $testHelper = new TestHelper('Mongodb driver'); +$config = new Config(); +$config->setItemDetailedDate(true) + ->setDatabaseName('pfc_test') + ->setCollectionName('pfc_' . str_pad('0', 3, random_int(1, 100))) + ->setUsername('travis') + ->setPassword('test'); try{ - $cacheInstance = CacheManager::getInstance('Mongodb', new Config([ - 'databaseName' => 'pfc_test', - 'username' => 'travis', - 'password' => 'test', - ])); + $cacheInstance = CacheManager::getInstance('Mongodb', $config); }catch(PhpfastcacheDriverCheckException $exception){ $testHelper->exceptionHandler($exception); $testHelper->terminateTest(); } - -$cacheKey = str_shuffle(uniqid('pfc', true)); -$cacheValue = str_shuffle(uniqid('pfc', true)); - -try{ - $item = $cacheInstance->getItem($cacheKey); - $item->set($cacheValue)->expiresAfter(300); - $cacheInstance->save($item); - $testHelper->assertPass('Successfully saved a new cache item into Mongodb server'); -}catch(phpFastCacheDriverException $e){ - $testHelper->assertFail('Failed to save a new cache item into Mongodb server with exception: ' . $e->getMessage()); -} - -try{ - unset($item); - $cacheInstance->detachAllItems(); - $item = $cacheInstance->getItem($cacheKey); - - if($item->get() === $cacheValue){ - $testHelper->assertPass('Getter returned expected value: ' . $cacheValue); - }else{ - $testHelper->assertFail('Getter returned unexpected value, expecting "' . $cacheValue . '", got "' . $item->get() . '"'); - } -}catch(phpFastCacheDriverException $e){ - $testHelper->assertFail('Failed to save a new cache item into Mongodb server with exception: ' . $e->getMessage()); -} - -try{ - unset($item); - $cacheInstance->detachAllItems(); - $cacheInstance->clear(); - $item = $cacheInstance->getItem($cacheKey); - - if(!$item->isHit()){ - $testHelper->assertPass('Successfully cleared the Mongodb server, no cache item found'); - }else{ - $testHelper->assertFail('Failed to clear the Mongodb server, a cache item has been found'); - } -}catch(phpFastCacheDriverException $e){ - $testHelper->assertFail('Failed to clear the Mongodb server with exception: ' . $e->getMessage()); -} - -try{ - $item = $cacheInstance->getItem($cacheKey); - $item->set($cacheValue)->expiresAfter(300); - $cacheInstance->save($item); - - if($cacheInstance->deleteItem($item->getKey())){ - $testHelper->assertPass('Deleter successfully removed the item from cache'); - }else{ - $testHelper->assertFail('Deleter failed to remove the item from cache'); - } -}catch(phpFastCacheDriverException $e){ - $testHelper->assertFail('Failed to remove a cache item from Mongodb server with exception: ' . $e->getMessage()); -} - +$testHelper->runCRUDTests($cacheInstance); $testHelper->terminateTest(); From 2bb45b57219f8032d75f32ae6a67c568a6200790 Mon Sep 17 00:00:00 2001 From: Geolim4 Date: Sun, 15 Aug 2021 10:49:29 +0200 Subject: [PATCH 3/4] Improved test helper --- tests/lib/Helper/TestHelper.php | 84 ++++++++++++++++++++++++++++----- 1 file changed, 73 insertions(+), 11 deletions(-) diff --git a/tests/lib/Helper/TestHelper.php b/tests/lib/Helper/TestHelper.php index 7074f37a1..53fd0a91a 100644 --- a/tests/lib/Helper/TestHelper.php +++ b/tests/lib/Helper/TestHelper.php @@ -397,12 +397,13 @@ public function runCRUDTests(ExtendedCacheItemPoolInterface $pool) $cacheKey = 'cache_key_' . bin2hex(random_bytes(8) . '_' . random_int(100, 999)); $cacheValue = 'cache_data_' . random_int(1000, 999999); $cacheTag = 'cache_tag_' . bin2hex(random_bytes(8) . '_' . random_int(100, 999)); + $cacheTag2 = 'cache_tag_' . bin2hex(random_bytes(8) . '_' . random_int(100, 999)); $cacheItem = $pool->getItem($cacheKey); $this->printInfoText('Using cache key: ' . $cacheKey); $cacheItem->set($cacheValue) ->expiresAfter(600) - ->addTag($cacheTag); + ->addTags([$cacheTag, $cacheTag2]); if ($pool->save($cacheItem)) { $this->assertPass('The pool successfully saved an item.'); @@ -410,14 +411,69 @@ public function runCRUDTests(ExtendedCacheItemPoolInterface $pool) $this->assertFail('The pool failed to save an item.'); return; } + unset($cacheItem); + $pool->detachAllItems(); - /*** - * Detach the items to force "re-pull" from the backend + /** + * Tag strategy ALL success and fail */ + + $this->printInfoText('Re-fetching item by its tags and an unknown tag (tag strategy "ALL")...'); + $cacheItems = $pool->getItemsByTags([$cacheTag, $cacheTag2, 'unknown_tag'], $pool::TAG_STRATEGY_ALL); + + if (!isset($cacheItems[$cacheKey])) { + $this->assertPass('The pool expectedly failed to retrieve the cache item.'); + } else { + $this->assertFail('The pool unexpectedly retrieved the cache item.'); + return; + } + unset($cacheItems); + $pool->detachAllItems(); + + $this->printInfoText('Re-fetching item by its tags (tag strategy "ALL")...'); + $cacheItems = $pool->getItemsByTags([$cacheTag, $cacheTag2], $pool::TAG_STRATEGY_ALL); + + if (isset($cacheItems[$cacheKey])) { + $this->assertPass('The pool successfully retrieved the cache item.'); + } else { + $this->assertFail('The pool failed to retrieve the cache item.'); + return; + } + unset($cacheItems); + $pool->detachAllItems(); + + /** + * Tag strategy ONLY success and fail + */ + $this->printInfoText('Re-fetching item by its tags and an unknown tag (tag strategy "ONLY")...'); + $cacheItems = $pool->getItemsByTags([$cacheTag, $cacheTag2, 'unknown_tag'], $pool::TAG_STRATEGY_ONLY); + + if (!isset($cacheItems[$cacheKey])) { + $this->assertPass('The pool expectedly failed to retrieve the cache item.'); + } else { + $this->assertFail('The pool unexpectedly retrieved the cache item.'); + return; + } + unset($cacheItems); + $pool->detachAllItems(); + + $this->printInfoText('Re-fetching item by one of its tags (tag strategy "ONLY")...'); + $cacheItems = $pool->getItemsByTags([$cacheTag, $cacheTag2], $pool::TAG_STRATEGY_ONLY); + + if (isset($cacheItems[$cacheKey])) { + $this->assertPass('The pool successfully retrieved the cache item.'); + } else { + $this->assertFail('The pool failed to retrieve the cache item.'); + return; + } + unset($cacheItems); $pool->detachAllItems(); - $this->printInfoText('Re-fetching item by its tag...'); - $cacheItems = $pool->getItemsByTag($cacheTag); + /** + * Tag strategy ONE success and fail + */ + $this->printInfoText('Re-fetching item by one of its tags and an unknown tag (tag strategy "ONE")...'); + $cacheItems = $pool->getItemsByTags([$cacheTag, 'unknown_tag'], $pool::TAG_STRATEGY_ONE); if (isset($cacheItems[$cacheKey]) && $cacheItems[$cacheKey]->getKey() === $cacheKey) { $this->assertPass('The pool successfully retrieved the cache item.'); @@ -444,14 +500,10 @@ public function runCRUDTests(ExtendedCacheItemPoolInterface $pool) } else { $this->assertFail('The pool failed to commit deferred cache item.'); } - - /*** - * Detach the items to force "re-pull" from the backend - */ $pool->detachAllItems(); unset($cacheItem); - $cacheItem = $pool->getItem($cacheKey); + $cacheItem = $pool->getItem($cacheKey); if ($cacheItem->get() === $cacheValue) { $this->assertPass('The pool successfully retrieved the expected new value.'); } else { @@ -459,7 +511,6 @@ public function runCRUDTests(ExtendedCacheItemPoolInterface $pool) return; } - if ($pool->deleteItem($cacheKey)) { $this->assertPass('The pool successfully deleted the cache item.'); } else { @@ -471,8 +522,19 @@ public function runCRUDTests(ExtendedCacheItemPoolInterface $pool) } else { $this->assertFail('The cluster failed to clear.'); } + $pool->detachAllItems(); + unset($cacheItem); + + $cacheItem = $pool->getItem($cacheKey); + if (!$cacheItem->isHit()) { + $this->assertPass('The cache item does no longer exists in pool.'); + } else { + $this->assertFail('The cache item still exists in pool.'); + return; + } $this->printInfoText(sprintf('I/O stats: %d HIT, %s MISS, %d WRITE', $pool->getIO()->getReadHit(), $pool->getIO()->getReadMiss(), $pool->getIO()->getWriteHit())); + $this->printInfoText('Driver info: ' . $pool->getStats()->getInfo() . ''); } From 8a85a14b721a5ee954555cc14c5c1ed0b067d1cb Mon Sep 17 00:00:00 2001 From: Geolim4 Date: Sun, 15 Aug 2021 11:00:51 +0200 Subject: [PATCH 4/4] Fixed possible type error on Couchdb --- lib/Phpfastcache/Drivers/Couchdb/Driver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Phpfastcache/Drivers/Couchdb/Driver.php b/lib/Phpfastcache/Drivers/Couchdb/Driver.php index 5662bd27c..8374f3a11 100644 --- a/lib/Phpfastcache/Drivers/Couchdb/Driver.php +++ b/lib/Phpfastcache/Drivers/Couchdb/Driver.php @@ -66,7 +66,7 @@ public function getStats(): DriverStatistic $info = $this->instance->getDatabaseInfo(); return (new DriverStatistic()) - ->setSize($info['sizes']['active']) + ->setSize($info['sizes']['active'] ?? 0) ->setRawData($info) ->setData(implode(', ', array_keys($this->itemInstances))) ->setInfo('Couchdb version ' . $this->instance->getVersion() . "\n For more information see RawData.");