diff --git a/lib/Phpfastcache/Core/Item/ExtendedCacheItemTrait.php b/lib/Phpfastcache/Core/Item/ExtendedCacheItemTrait.php index 5ccfd44f..1ed2888b 100644 --- a/lib/Phpfastcache/Core/Item/ExtendedCacheItemTrait.php +++ b/lib/Phpfastcache/Core/Item/ExtendedCacheItemTrait.php @@ -77,15 +77,8 @@ public function setDriver(ExtendedCacheItemPoolInterface $driver): ExtendedCache */ public function getEncodedKey(): string { - // Only calculate the encoded key on demand to save resources if (!isset($this->encodedKey)) { - $keyHashFunction = $this->driver->getConfig()->getDefaultKeyHashFunction(); - - if ($keyHashFunction) { - $this->encodedKey = $keyHashFunction($this->getKey()); - } else { - $this->encodedKey = $this->getKey(); - } + $this->encodedKey = $this->driver->getEncodedKey($this->getKey()); } return $this->encodedKey; diff --git a/lib/Phpfastcache/Core/Pool/DriverBaseTrait.php b/lib/Phpfastcache/Core/Pool/DriverBaseTrait.php index f928500a..8fb00aef 100644 --- a/lib/Phpfastcache/Core/Pool/DriverBaseTrait.php +++ b/lib/Phpfastcache/Core/Pool/DriverBaseTrait.php @@ -142,6 +142,24 @@ public static function getItemClass(): string return self::$cacheItemClasses[static::class]; } + /** + * @inheritDoc + */ + public function getEncodedKey(string $key): string + { + $keyHashFunction = $this->getConfig()->getDefaultKeyHashFunction(); + + if ($keyHashFunction) { + if (\is_callable($keyHashFunction)) { + return $keyHashFunction($key); + } + throw new PhpfastcacheLogicException('Unable to build the encoded key (defaultKeyHashFunction is not callable)'); + } + + return $key; + } + + /** * @param ExtendedCacheItemInterface $item diff --git a/lib/Phpfastcache/Core/Pool/ExtendedCacheItemPoolInterface.php b/lib/Phpfastcache/Core/Pool/ExtendedCacheItemPoolInterface.php index 2687135a..2701be8f 100644 --- a/lib/Phpfastcache/Core/Pool/ExtendedCacheItemPoolInterface.php +++ b/lib/Phpfastcache/Core/Pool/ExtendedCacheItemPoolInterface.php @@ -77,6 +77,12 @@ public static function getConfigClass(): string; */ public static function getItemClass(): string; + /** + * @param string $key + * @return string + */ + public function getEncodedKey(string $key): string; + /** * @return ConfigurationOptionInterface */ diff --git a/lib/Phpfastcache/Drivers/Couchbasev3/Driver.php b/lib/Phpfastcache/Drivers/Couchbasev3/Driver.php index 34d8ccf7..226e19e7 100644 --- a/lib/Phpfastcache/Drivers/Couchbasev3/Driver.php +++ b/lib/Phpfastcache/Drivers/Couchbasev3/Driver.php @@ -22,6 +22,7 @@ use Couchbase\ClusterOptions; use Couchbase\Collection; use Couchbase\DocumentNotFoundException; +use Couchbase\GetResult; use Couchbase\Scope; use Couchbase\UpsertOptions; use DateTimeInterface; @@ -35,6 +36,8 @@ use Phpfastcache\Exceptions\PhpfastcacheDriverCheckException; use Phpfastcache\Exceptions\PhpfastcacheInvalidArgumentException; use Phpfastcache\Exceptions\PhpfastcacheLogicException; +use Phpfastcache\Exceptions\PhpfastcacheUnsupportedException; +use Phpfastcache\Exceptions\PhpfastcacheUnsupportedMethodException; /** * @property Cluster $instance Instance of driver service @@ -105,6 +108,33 @@ protected function driverRead(ExtendedCacheItemInterface $item): ?array } } + /** + * @param ExtendedCacheItemInterface $item + * @return ?array + */ + protected function driverReadMultiple(ExtendedCacheItemInterface ...$items): array + { + try { + $keys = $this->getKeys($items, true); + $results = []; + /** + * CouchbaseBucket::get() returns a GetResult interface + */ + /** @var GetResult $document */ + foreach ($this->getCollection()->getMulti($this->getKeys($items, true)) as $document) { + $content = $document->content(); + if ($content) { + $decodedDocument = $this->decodeDocument($content); + $results[$decodedDocument[ExtendedCacheItemPoolInterface::DRIVER_KEY_WRAPPER_INDEX]] = $this->decodeDocument($content); + } + } + + return $results; + } catch (DocumentNotFoundException) { + return []; + } + } + /** * @param ExtendedCacheItemInterface $item * @return bool @@ -135,8 +165,7 @@ protected function driverDelete(string $key, string $encodedKey): bool { try { - $this->getCollection()->remove($encodedKey); - return true; + return $this->getCollection()->remove($encodedKey)->mutationToken() !== null; } catch (DocumentNotFoundException) { return true; } catch (CouchbaseException) { @@ -144,12 +173,39 @@ protected function driverDelete(string $key, string $encodedKey): bool } } + + /** + * @param string[] $keys + * @return bool + */ + protected function driverDeleteMultiple(array $keys): bool + { + try { + $this->getCollection()->removeMulti(array_map(fn(string $key) => $this->getEncodedKey($key), $keys)); + return true; + } catch (CouchbaseException) { + return false; + } + } + + /** * @return bool + * @throws PhpfastcacheUnsupportedMethodException */ protected function driverClear(): bool { + if (!$this->instance->buckets()->getBucket($this->getConfig()->getBucketName())->flushEnabled()) { + $this->instance->buckets()->getBucket($this->getConfig()->getBucketName())->enableFlush(true); + if (!$this->instance->buckets()->getBucket($this->getConfig()->getBucketName())->flushEnabled()) { + throw new PhpfastcacheUnsupportedMethodException( + 'Flushing operation is not enabled on your Bucket. See https://docs.couchbase.com/server/current/manage/manage-buckets/flush-bucket.html' + ); + } + } + $this->instance->buckets()->flush($this->getConfig()->getBucketName()); + return true; } diff --git a/tests/lib/Helper/TestHelper.php b/tests/lib/Helper/TestHelper.php index 8de0c807..7152a34c 100644 --- a/tests/lib/Helper/TestHelper.php +++ b/tests/lib/Helper/TestHelper.php @@ -18,6 +18,7 @@ use League\CLImate\CLImate; use Phpfastcache\Api; use Phpfastcache\Config\ConfigurationOptionInterface; +use Phpfastcache\Core\Item\ExtendedCacheItemInterface; use Phpfastcache\Core\Pool\ExtendedCacheItemPoolInterface; use Phpfastcache\Event\EventManagerInterface; use Phpfastcache\Exceptions\PhpfastcacheDriverCheckException; @@ -543,12 +544,20 @@ public function runCRUDTests(ExtendedCacheItemPoolInterface|PhpfastcacheAbstract } unset($cacheItem); + $this->printInfoText('Testing deleting multiple keys at once.'); $cacheItems = $pool->getItems([$cacheKey, $cacheKey2]); foreach ($cacheItems as $cacheItem) { $cacheItem->set(str_shuffle($cacheValue)); $pool->save($cacheItem); } $pool->deleteItems(array_keys($cacheItems)); + + if(count(array_filter(array_map(fn(ExtendedCacheItemInterface $item) => $item->isHit(), $pool->getItems([$cacheKey, $cacheKey2])))) === 0) { + $this->assertPass('The cache items does no longer exists in pool.'); + } else { + $this->assertFail('The cache items still exists in pool.'); + return; + } } $this->printInfoText(