Addshore has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/278596

Change subject: WatchedItemStore use Taggable PSR6 cache
......................................................................

WatchedItemStore use Taggable PSR6 cache

Depends-On: I9ccd16afa63b60b3fb3ee8c73654aac48bb7d19a
Change-Id: I3a775d77f59086b2206ccbf52d6a7bc2f471cf26
---
M composer.json
M includes/WatchedItemStore.php
M tests/phpunit/includes/WatchedItemStoreUnitTest.php
3 files changed, 72 insertions(+), 38 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core 
refs/changes/96/278596/3

diff --git a/composer.json b/composer.json
index ccb9398..e67c73d 100644
--- a/composer.json
+++ b/composer.json
@@ -16,6 +16,7 @@
                "wiki": "https://www.mediawiki.org/";
        },
        "require": {
+               "cache/taggable-cache": "0.4.0",
                "composer/semver": "1.2.0",
                "cssjanus/cssjanus": "1.1.2",
                "ext-iconv": "*",
diff --git a/includes/WatchedItemStore.php b/includes/WatchedItemStore.php
index 1c6053c..b44ce35 100644
--- a/includes/WatchedItemStore.php
+++ b/includes/WatchedItemStore.php
@@ -1,6 +1,7 @@
 <?php
 
-use Psr\Cache\CacheItemPoolInterface;
+use Cache\Taggable\TaggablePoolInterface;
+use Cache\Taggable\TaggablePSR6PoolAdapter;
 use Wikimedia\Assert\Assert;
 
 /**
@@ -19,17 +20,9 @@
        private $loadBalancer;
 
        /**
-        * @var CacheItemPoolInterface
+        * @var TaggablePoolInterface
         */
        private $cache;
-
-       /**
-        * @var array[] Looks like $cacheIndex[Namespace ID][Target DB 
Key][User Id] => 'key'
-        * The index is needed so that on mass changes all relevant items can 
be un-cached.
-        * For example: Clearing a users watchlist of all items or updating 
notification timestamps
-        *              for all users watching a single target.
-        */
-       private $cacheIndex = [];
 
        /**
         * @var callable|null
@@ -48,11 +41,11 @@
 
        /**
         * @param LoadBalancer $loadBalancer
-        * @param CacheItemPoolInterface $cache
+        * @param TaggablePoolInterface $cache
         */
        public function __construct(
                LoadBalancer $loadBalancer,
-               CacheItemPoolInterface $cache
+               TaggablePoolInterface $cache
        ) {
                $this->loadBalancer = $loadBalancer;
                $this->cache = $cache;
@@ -144,7 +137,11 @@
                if ( !self::$instance ) {
                        self::$instance = new self(
                                wfGetLB(),
-                               new BagOStuffPsrCache( new HashBagOStuff( [ 
'maxKeys' => 100 ] ) )
+                               TaggablePSR6PoolAdapter::makeTaggable(
+                                       new BagOStuffPsrCache(
+                                               new HashBagOStuff( [ 'maxKeys' 
=> 100 ] )
+                                       )
+                               )
                        );
                }
                return self::$instance;
@@ -163,23 +160,24 @@
        private function cache( WatchedItem $item ) {
                $user = $item->getUser();
                $target = $item->getLinkTarget();
-               $key = $this->getCacheKey( $user, $target );
-               $this->cache->save( $this->cache->getItem( $key )->set( $item ) 
);
-               
$this->cacheIndex[$target->getNamespace()][$target->getDBkey()][$user->getId()] 
= $key;
+               $this->cache->save(
+                       $this->cache->getItem( $this->getCacheKey( $user, 
$target ) )
+                               ->set( $item )
+                               ->setTags(
+                                       [
+                                               'user-' . $user->getId(),
+                                               'target-' . 
$target->getNamespace() . '-' . $target->getDBkey(),
+                                       ]
+                               )
+               );
        }
 
        private function uncache( User $user, LinkTarget $target ) {
                $this->cache->deleteItem( $this->getCacheKey( $user, $target ) 
);
-               unset( 
$this->cacheIndex[$target->getNamespace()][$target->getDBkey()][$user->getId()] 
);
        }
 
        private function uncacheLinkTarget( LinkTarget $target ) {
-               if ( !isset( 
$this->cacheIndex[$target->getNamespace()][$target->getDBkey()] ) ) {
-                       return;
-               }
-               foreach ( 
$this->cacheIndex[$target->getNamespace()][$target->getDBkey()] as $key ) {
-                       $this->cache->deleteItem( $key );
-               }
+               $this->cache->clearTags( [ 'target-' . $target->getNamespace() 
. '-' . $target->getDBkey() ] );
        }
 
        /**
diff --git a/tests/phpunit/includes/WatchedItemStoreUnitTest.php 
b/tests/phpunit/includes/WatchedItemStoreUnitTest.php
index 2c6b8e6..92e23f8 100644
--- a/tests/phpunit/includes/WatchedItemStoreUnitTest.php
+++ b/tests/phpunit/includes/WatchedItemStoreUnitTest.php
@@ -1,5 +1,7 @@
 <?php
-use Psr\Cache\CacheItemPoolInterface;
+
+use Cache\Taggable\TaggableItemInterface;
+use Cache\Taggable\TaggablePoolInterface;
 
 /**
  * @author Addshore
@@ -32,10 +34,10 @@
        }
 
        /**
-        * @return 
PHPUnit_Framework_MockObject_MockObject|CacheItemPoolInterface
+        * @return PHPUnit_Framework_MockObject_MockObject|TaggablePoolInterface
         */
        private function getMockCache() {
-               $mock = $this->getMockBuilder( BagOStuffPsrCache::class )
+               $mock = $this->getMockBuilder( TaggablePoolInterface::class )
                        ->disableOriginalConstructor()
                        ->getMock();
                return $mock;
@@ -45,7 +47,7 @@
         * @param bool $isHit
         * @param string[] $expectedMethods Method names that we want to expect
         *
-        * @return PHPUnit_Framework_MockObject_MockObject|BagOStuffPsrCacheItem
+        * @return PHPUnit_Framework_MockObject_MockObject|TaggableItemInterface
         */
        private function getMockCacheItem( $isHit, array $expectedMethods = [] 
) {
                $methods = [
@@ -54,8 +56,11 @@
                        'set',
                        'expiresAt',
                        'expiresAfter',
+                       'getTags',
+                       'setTags',
+                       'addTag',
                ];
-               $mock = $this->getMockBuilder( BagOStuffPsrCacheItem::class )
+               $mock = $this->getMockBuilder( TaggableItemInterface::class )
                        ->disableOriginalConstructor()
                        ->getMock();
                $mock->expects( $this->any() )
@@ -70,7 +75,7 @@
        /**
         * @param string[] $expectedMethods Method names that we want to expect
         *
-        * @return 
PHPUnit_Framework_MockObject_MockObject|CacheItemPoolInterface
+        * @return PHPUnit_Framework_MockObject_MockObject|TaggablePoolInterface
         */
        private function getMockCacheWithNoExpectedCalls( array 
$expectedMethods = [] ) {
                $methods =
@@ -84,6 +89,7 @@
                                'save',
                                'saveDeferred',
                                'commit',
+                               'clearTags',
                        ];
                $mockCache = $this->getMockCache();
                foreach ( array_diff( $methods, $expectedMethods ) as $method ) 
{
@@ -1052,10 +1058,14 @@
                                $this->getFakeRow( [ 'wl_notificationtimestamp' 
=> '20151212010101' ] )
                        ) );
 
-               $mockCacheItem = $this->getMockCacheItem( false, [ 'set' ] );
+               $mockCacheItem = $this->getMockCacheItem( false, [ 'set', 
'setTags' ] );
                $mockCacheItem->expects( $this->once() )
                        ->method( 'set' )
                        ->with( $this->isInstanceOf( WatchedItem::class ) )
+                       ->will( $this->returnValue( $mockCacheItem ) );
+               $mockCacheItem->expects( $this->once() )
+                       ->method( 'setTags' )
+                       ->with( [ 'user-1', 'target-0-SomeDbKey' ] )
                        ->will( $this->returnValue( $mockCacheItem ) );
 
                $mockCache = $this->getMockCache();
@@ -1248,10 +1258,14 @@
                                $this->getFakeRow( [ 'wl_notificationtimestamp' 
=> '20151212010101' ] )
                        ) );
 
-               $mockCacheItem = $this->getMockCacheItem( false, [ 'set' ] );
+               $mockCacheItem = $this->getMockCacheItem( false, [ 'set', 
'setTags' ] );
                $mockCacheItem->expects( $this->once() )
                        ->method( 'set' )
                        ->with( $this->isInstanceOf( WatchedItem::class ) )
+                       ->will( $this->returnValue( $mockCacheItem ) );
+               $mockCacheItem->expects( $this->once() )
+                       ->method( 'setTags' )
+                       ->with( [ 'user-1', 'target-0-SomeDbKey' ] )
                        ->will( $this->returnValue( $mockCacheItem ) );
 
                $mockCache = $this->getMockCache();
@@ -1389,10 +1403,14 @@
                                $this->getFakeRow( [ 'wl_notificationtimestamp' 
=> '20151212010101' ] )
                        ) );
 
-               $mockCacheItem = $this->getMockCacheItem( false, [ 'set' ] );
+               $mockCacheItem = $this->getMockCacheItem( false, [ 'set', 
'setTags' ] );
                $mockCacheItem->expects( $this->once() )
                        ->method( 'set' )
                        ->with( $this->isInstanceOf( WatchedItem::class ) )
+                       ->will( $this->returnValue( $mockCacheItem ) );
+               $mockCacheItem->expects( $this->once() )
+                       ->method( 'setTags' )
+                       ->with( [ 'user-1', 'target-0-SomeDbKey' ] )
                        ->will( $this->returnValue( $mockCacheItem ) );
 
                $mockCache = $this->getMockCache();
@@ -1540,10 +1558,14 @@
                                $this->getFakeRow( [ 'wl_notificationtimestamp' 
=> '20151212010101' ] )
                        ) );
 
-               $mockCacheItem = $this->getMockCacheItem( false, [ 'set' ] );
+               $mockCacheItem = $this->getMockCacheItem( false, [ 'set', 
'setTags' ] );
                $mockCacheItem->expects( $this->once() )
                        ->method( 'set' )
                        ->with( $this->isInstanceOf( WatchedItem::class ) )
+                       ->will( $this->returnValue( $mockCacheItem ) );
+               $mockCacheItem->expects( $this->once() )
+                       ->method( 'setTags' )
+                       ->with( [ 'user-1', 'target-0-SomeDbKey' ] )
                        ->will( $this->returnValue( $mockCacheItem ) );
 
                $mockCache = $this->getMockCache();
@@ -1699,10 +1721,14 @@
                                $this->getFakeRow( [ 'wl_notificationtimestamp' 
=> '20151212010101' ] )
                        ) );
 
-               $mockCacheItem = $this->getMockCacheItem( false, [ 'set' ] );
+               $mockCacheItem = $this->getMockCacheItem( false, [ 'set', 
'setTags' ] );
                $mockCacheItem->expects( $this->once() )
                        ->method( 'set' )
                        ->with( $this->isInstanceOf( WatchedItem::class ) )
+                       ->will( $this->returnValue( $mockCacheItem ) );
+               $mockCacheItem->expects( $this->once() )
+                       ->method( 'setTags' )
+                       ->with( [ 'user-1', 'target-0-SomeDbKey' ] )
                        ->will( $this->returnValue( $mockCacheItem ) );
 
                $mockCache = $this->getMockCacheWithNoExpectedCalls( [ 
'getItem', 'save', 'deleteItem' ] );
@@ -1793,9 +1819,14 @@
                                ]
                        );
 
+               $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->once() )
+                       ->method( 'clearTags' )
+                       ->with( [ 'target-0-SomeDbKey' ] );
+
                $store = new WatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
-                       $this->getMockCacheWithNoExpectedCalls()
+                       $mockCache
                );
 
                $this->assertEquals(
@@ -1871,10 +1902,14 @@
                $mockDb->expects( $this->once() )
                        ->method( 'update' );
 
-               $mockCacheItem = $this->getMockCacheItem( false, [ 'set' ] );
+               $mockCacheItem = $this->getMockCacheItem( false, [ 'set', 
'setTags' ] );
                $mockCacheItem->expects( $this->once() )
                        ->method( 'set' )
                        ->with( $this->isInstanceOf( WatchedItem::class ) )
+                       ->will( $this->returnValue( $mockCacheItem ) );
+               $mockCacheItem->expects( $this->once() )
+                       ->method( 'setTags' )
+                       ->with( [ 'user-1', 'target-0-SomeDbKey' ] )
                        ->will( $this->returnValue( $mockCacheItem ) );
 
                $mockCache = $this->getMockCache();
@@ -1886,8 +1921,8 @@
                        ->method( 'save' )
                        ->with( $mockCacheItem );
                $mockCache->expects( $this->once() )
-                       ->method( 'deleteItem' )
-                       ->with( '0|SomeDbKey|1' );
+                       ->method( 'clearTags' )
+                       ->with( [ 'target-0-SomeDbKey' ] );
 
                $store = new WatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),

-- 
To view, visit https://gerrit.wikimedia.org/r/278596
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I3a775d77f59086b2206ccbf52d6a7bc2f471cf26
Gerrit-PatchSet: 3
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Addshore <[email protected]>
Gerrit-Reviewer: Addshore <[email protected]>
Gerrit-Reviewer: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to