Use global user ID in global cache keys

We were using the local user ID instead, which is not the
same on every wiki, which caused strange cache staleness
and pollution behavior.

Run sets through a wrapper function (gets were already wrapped)
so we can update the instance cache and deal with uncomputable
cache keys in one place. A global cache key may be uncomputable
if we fail to obtain the user's global user ID (users aren't
supposed to be unattached, but some are).

Also bump the cache version to get rid of polluted cache entries.
Bumping this version number was probably a good idea anyway,
with all the recent changes.

Bug: T134533
Change-Id: I1c4f0c2f2eded480c80f8ec7a49a04feb7c5ecfb
This commit is contained in:
Roan Kattouw 2016-05-05 16:38:55 -07:00
parent e57dbfc86b
commit ac85f28f3e
2 changed files with 54 additions and 15 deletions

View file

@ -529,7 +529,7 @@ $wgDefaultUserOptions['echo-subscriptions-web-article-linked'] = false;
// Echo Configuration for EventLogging
$wgEchoConfig = array(
'version' => '1.6',
'version' => '1.7',
'eventlogging' => array(
/**
* Properties:

View file

@ -225,7 +225,7 @@ class MWEchoNotifUser {
$count += $this->getForeignNotifications()->getCount( $section );
}
$this->cache->set( $memcKey, $count, 86400 );
$this->setInCache( $memcKey, $count, 86400 );
return $count;
}
@ -320,7 +320,7 @@ class MWEchoNotifUser {
$cacheValue = $timestamp->getTimestamp( TS_MW );
}
$this->cache->set( $memcKey, $cacheValue, 86400 );
$this->setInCache( $memcKey, $cacheValue, 86400 );
return $returnValue;
}
@ -474,14 +474,14 @@ class MWEchoNotifUser {
$globalAlertUnread : $globalMsgUnread;
// Write computed values to cache
$this->cache->set( $this->getMemcKey( 'echo-notification-count' ), $allCount, 86400 );
$this->cache->set( $this->getGlobalMemcKey( 'echo-notification-count-alert' ), $globalAlertCount, 86400 );
$this->cache->set( $this->getGlobalMemcKey( 'echo-notification-count-message' ), $globalMsgCount, 86400 );
$this->cache->set( $this->getGlobalMemcKey( 'echo-notification-count' ), $globalAllCount, 86400 );
$this->cache->set( $this->getMemcKey( 'echo-notification-timestamp', $allUnread === false ? -1 : $allUnread->getTimestamp( TS_MW ) ), 86400 );
$this->cache->set( $this->getGlobalMemcKey( 'echo-notification-timestamp-alert' ), $globalAlertUnread === false ? -1 : $globalAlertUnread->getTimestamp( TS_MW ), 86400 );
$this->cache->set( $this->getGlobalMemcKey( 'echo-notification-timestamp-message' ), $globalMsgUnread === false ? -1 : $globalMsgUnread->getTimestamp( TS_MW ), 86400 );
$this->cache->set( $this->getGlobalMemcKey( 'echo-notification-timestamp' ), $globalAllUnread === false ? -1 : $globalAllUnread->getTimestamp( TS_MW ), 86400 );
$this->setInCache( $this->getMemcKey( 'echo-notification-count' ), $allCount, 86400 );
$this->setInCache( $this->getGlobalMemcKey( 'echo-notification-count-alert' ), $globalAlertCount, 86400 );
$this->setInCache( $this->getGlobalMemcKey( 'echo-notification-count-message' ), $globalMsgCount, 86400 );
$this->setInCache( $this->getGlobalMemcKey( 'echo-notification-count' ), $globalAllCount, 86400 );
$this->setInCache( $this->getMemcKey( 'echo-notification-timestamp' ), $allUnread === false ? -1 : $allUnread->getTimestamp( TS_MW ), 86400 );
$this->setInCache( $this->getGlobalMemcKey( 'echo-notification-timestamp-alert' ), $globalAlertUnread === false ? -1 : $globalAlertUnread->getTimestamp( TS_MW ), 86400 );
$this->setInCache( $this->getGlobalMemcKey( 'echo-notification-timestamp-message' ), $globalMsgUnread === false ? -1 : $globalMsgUnread->getTimestamp( TS_MW ), 86400 );
$this->setInCache( $this->getGlobalMemcKey( 'echo-notification-timestamp' ), $globalAllUnread === false ? -1 : $globalAllUnread->getTimestamp( TS_MW ), 86400 );
// Invalidate the user's cache
$user = $this->mUser;
@ -510,7 +510,18 @@ class MWEchoNotifUser {
}
}
/**
* Get a cache entry from the cache, using a preloaded instance cache.
* @param string|false $memcKey Cache key returned by getMemcKey()
* @return mixed Cache value
*/
protected function getFromCache( $memcKey ) {
// getMemcKey() can return false
if ( $memcKey === false ) {
return false;
}
// Populate the instance cache
if ( $this->cached === null ) {
$keys = $this->preloadKeys();
$this->cached = $this->cache->getMulti( $keys );
@ -526,6 +537,27 @@ class MWEchoNotifUser {
return $this->cache->get( $memcKey );
}
/**
* Set a cache entry both in the cache and in the instance cache.
* Use this to write to keys that were loaded with getFromCache().
* @param string|false $memcKey Cache key returned by getMemcKey()
* @param mixed $value Cache value to set
* @param int $expiry Expiry, see BagOStuff::set()
*/
protected function setInCache( $memcKey, $value, $expiry ) {
// getMemcKey() can return false
if ( $memcKey === false ) {
return;
}
// Update the instance cache if it's already been populated
if ( $this->cached !== null ) {
$this->cached[$memcKey] = $value;
}
$this->cache->set( $memcKey, $value, $expiry );
}
/**
* Array of memcached keys to load at once.
*
@ -551,14 +583,21 @@ class MWEchoNotifUser {
* Build a memcached key.
* @param string $key Key, typically prefixed with echo-notification-
* @param bool $global If true, return a global memc key; if false, return one local to this wiki
* @return string Memcached key
* @return string|false Memcached key, or false if one could not be generated
*/
protected function getMemcKey( $key, $global = false ) {
global $wgEchoConfig;
if ( $global ) {
return wfGlobalCacheKey( $key, $this->mUser->getId(), $wgEchoConfig['version'] );
if ( !$global ) {
return wfMemcKey( $key, $this->mUser->getId(), $wgEchoConfig['version'] );
}
return wfMemcKey( $key, $this->mUser->getId(), $wgEchoConfig['version'] );
$lookup = CentralIdLookup::factory();
$globalId = $lookup->centralIdFromLocalUser( $this->mUser, CentralIdLookup::AUDIENCE_RAW );
if ( !$globalId ) {
return false;
}
return wfGlobalCacheKey( $key, $globalId, $wgEchoConfig['version'] );
}
protected function getGlobalMemcKey( $key ) {