From b3acd4fb5d1263de5735c714a11f7a170777d1f1 Mon Sep 17 00:00:00 2001 From: Timo Tijhof Date: Tue, 27 Oct 2015 23:43:40 +0000 Subject: [PATCH] User: Migrate from foreign cache to global cache for UserRightsProxy Avoid having one wiki access another wiki's local keyspace. Instead, use the global keyspace to share values across wikis. Also, imitating wfMemcKey from wfForeignMemcKey was semantically incorrect due to $wgCachePrefix having precedence. Most interfaces (e.g. UserRightsProxy, FileRepo, JobQueue etc.) only have access to the wiki id (dbname + prefix). The local cache configuration for wgCachePrefix is not and shouldn't have to be exposed. Start enforcing that local cache keys are left private and to share keys, one must use global keys. Global keys (prefixed with "global:") have their own space and we can use the wiki-id as regular key segment for keys about users. Also: * Expose a method to keep formatting of this key in one place. As it used used in many different places in core, as well as in CentralAuth. * Make use of wfWikiId() in getDefaultKeyspace() to avoid duplicating this logic. Change-Id: I58836a24b9e239f460ab489bd2fe8ced8259833c --- includes/User.php | 37 +++++++++++++++++++++------- includes/UserRightsProxy.php | 7 +++--- includes/objectcache/ObjectCache.php | 9 ++----- 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/includes/User.php b/includes/User.php index eb3ab9d2a2..b09e4e456e 100644 --- a/includes/User.php +++ b/includes/User.php @@ -387,6 +387,25 @@ class User implements IDBAccessObject { return true; } + /** + * @since 1.27 + * @param string $wikiId + * @param integer $userId + */ + public static function purge( $wikiId, $userId ) { + $cache = ObjectCache::getMainWANInstance(); + $cache->delete( $cache->makeGlobalKey( 'user', 'id', $wikiId, $userId ) ); + } + + /** + * @since 1.27 + * @param WANObjectCache $cache + * @return string + */ + protected function getCacheKey( WANObjectCache $cache ) { + return $cache->makeGlobalKey( 'user', 'id', wfWikiID(), $this->mId ); + } + /** * Load user data from shared cache, given mId has already been set. * @@ -399,8 +418,8 @@ class User implements IDBAccessObject { return false; } - $key = wfMemcKey( 'user', 'id', $this->mId ); - $data = ObjectCache::getMainWANInstance()->get( $key ); + $cache = ObjectCache::getMainWANInstance(); + $data = $cache->get( $this->getCacheKey( $cache ) ); if ( !is_array( $data ) || $data['mVersion'] < self::VERSION ) { // Object is expired return false; @@ -439,7 +458,7 @@ class User implements IDBAccessObject { $opts = Database::getCacheSetOptions( wfGetDB( DB_SLAVE ) ); $cache = ObjectCache::getMainWANInstance(); - $key = wfMemcKey( 'user', 'id', $this->mId ); + $key = $this->getCacheKey( $cache ); $cache->set( $key, $data, $cache::TTL_HOUR, $opts ); } @@ -2228,17 +2247,17 @@ class User implements IDBAccessObject { * @param string $mode Use 'refresh' to clear now; otherwise before DB commit */ public function clearSharedCache( $mode = 'changed' ) { - $id = $this->getId(); - if ( !$id ) { + if ( !$this->getId() ) { return; } - $key = wfMemcKey( 'user', 'id', $id ); + $cache = ObjectCache::getMainWANInstance(); + $key = $this->getCacheKey( $cache ); if ( $mode === 'refresh' ) { - ObjectCache::getMainWANInstance()->delete( $key, 1 ); + $cache->delete( $key, 1 ); } else { - wfGetDB( DB_MASTER )->onTransactionPreCommitOrIdle( function() use ( $key ) { - ObjectCache::getMainWANInstance()->delete( $key ); + wfGetDB( DB_MASTER )->onTransactionPreCommitOrIdle( function() use ( $cache, $key ) { + $cache->delete( $key ); } ); } } diff --git a/includes/UserRightsProxy.php b/includes/UserRightsProxy.php index 3a3eb53873..e686ae3fc5 100644 --- a/includes/UserRightsProxy.php +++ b/includes/UserRightsProxy.php @@ -278,9 +278,10 @@ class UserRightsProxy { array( 'user_id' => $this->id ), __METHOD__ ); - $key = wfForeignMemcKey( $this->database, false, 'user', 'id', $this->id ); - $this->db->onTransactionPreCommitOrIdle( function() use ( $key ) { - ObjectCache::getMainWANInstance()->delete( $key ); + $wikiId = $this->db->getWikiID(); + $userId = $this->id; + $this->db->onTransactionPreCommitOrIdle( function() use ( $wikiId, $userId ) { + User::purge( $wikiId, $userId ); } ); } } diff --git a/includes/objectcache/ObjectCache.php b/includes/objectcache/ObjectCache.php index 3d14c33f10..abb88bac77 100644 --- a/includes/objectcache/ObjectCache.php +++ b/includes/objectcache/ObjectCache.php @@ -137,19 +137,14 @@ class ObjectCache { * @return string */ public static function getDefaultKeyspace() { - global $wgCachePrefix, $wgDBname, $wgDBprefix; + global $wgCachePrefix; $keyspace = $wgCachePrefix; if ( is_string( $keyspace ) && $keyspace !== '' ) { return $keyspace; } - $keyspace = $wgDBname; - if ( is_string( $wgDBprefix ) && $wgDBprefix !== '' ) { - $keyspace .= '-' . $wgDBprefix; - } - - return $keyspace; + return wfWikiID(); } /** -- 2.20.1