private $loadBalancer;
/**
- * @var BagOStuff
+ * @var HashBagOStuff
*/
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
*/
*/
private static $instance;
- public function __construct( LoadBalancer $loadBalancer, BagOStuff $cache ) {
+ public function __construct( LoadBalancer $loadBalancer, HashBagOStuff $cache ) {
$this->loadBalancer = $loadBalancer;
$this->cache = $cache;
$this->deferredUpdatesAddCallableUpdateCallback = [ 'DeferredUpdates', 'addCallableUpdate' ];
}
private function cache( WatchedItem $item ) {
- $this->cache->set(
- $this->getCacheKey( $item->getUser(), $item->getLinkTarget() ),
- $item
- );
+ $user = $item->getUser();
+ $target = $item->getLinkTarget();
+ $key = $this->getCacheKey( $user, $target );
+ $this->cache->set( $key, $item );
+ $this->cacheIndex[$target->getNamespace()][$target->getDBkey()][$user->getId()] = $key;
}
private function uncache( User $user, LinkTarget $target ) {
$this->cache->delete( $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->delete( $key );
+ }
}
/**
'wl_title' => $target->getDBkey(),
], $fname
);
+ $this->uncacheLinkTarget( $target );
}
);
}
}
/**
- * @return PHPUnit_Framework_MockObject_MockObject|BagOStuff
+ * @return PHPUnit_Framework_MockObject_MockObject|HashBagOStuff
*/
private function getMockCache() {
- $mock = $this->getMockBuilder( BagOStuff::class )
+ $mock = $this->getMockBuilder( HashBagOStuff::class )
->disableOriginalConstructor()
->getMock();
$mock->expects( $this->any() )