From b23e0b0a835fa84031442b8b3b313860a6affadf Mon Sep 17 00:00:00 2001 From: Aaron Schulz Date: Mon, 28 Sep 2015 14:07:01 -0700 Subject: [PATCH] Fixed sanity cache clear in User::saveSettings() * This works by adding a refresh mode to clearSharedCache() when we want to purge the cache in case it might stale to avoid further CAS errors. Because an exception will be thrown, the usual DB callback will not get fired, so avoid using commit hooks when doing these cache purges. * Also lowered the tombstone TTL for such purges, since no data actually changed. Bug: T114023 Change-Id: Iaad87b4ed24733dac40bc9607d3c97c940710087 --- includes/User.php | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/includes/User.php b/includes/User.php index faf1bdc48c..168c4aceb4 100644 --- a/includes/User.php +++ b/includes/User.php @@ -1484,11 +1484,12 @@ class User implements IDBAccessObject { if ( $success ) { $this->mTouched = $newTouched; + $this->clearSharedCache(); + } else { + // Clears on failure too since that is desired if the cache is stale + $this->clearSharedCache( 'refresh' ); } - // Clears on failure too since that is desired if the cache is stale - $this->clearSharedCache(); - return $success; } @@ -2282,22 +2283,29 @@ class User implements IDBAccessObject { } /** - * Clear user data from memcached. - * Use after applying fun updates to the database; caller's + * Clear user data from memcached + * + * Use after applying updates to the database; caller's * responsibility to update user_touched if appropriate. * * Called implicitly from invalidateCache() and saveSettings(). + * + * @param string $mode Use 'refresh' to clear now; otherwise before DB commit */ - public function clearSharedCache() { + public function clearSharedCache( $mode = 'changed' ) { $id = $this->getId(); if ( !$id ) { return; } $key = wfMemcKey( 'user', 'id', $id ); - wfGetDB( DB_MASTER )->onTransactionPreCommitOrIdle( function() use ( $key ) { - ObjectCache::getMainWANInstance()->delete( $key ); - } ); + if ( $mode === 'refresh' ) { + ObjectCache::getMainWANInstance()->delete( $key, 1 ); + } else { + wfGetDB( DB_MASTER )->onTransactionPreCommitOrIdle( function() use ( $key ) { + ObjectCache::getMainWANInstance()->delete( $key ); + } ); + } } /** @@ -3702,7 +3710,7 @@ class User implements IDBAccessObject { if ( !$dbw->affectedRows() ) { // Maybe the problem was a missed cache update; clear it to be safe - $this->clearSharedCache(); + $this->clearSharedCache( 'refresh' ); // User was changed in the meantime or loaded with stale data $from = ( $this->queryFlagsUsed & self::READ_LATEST ) ? 'master' : 'slave'; throw new MWException( -- 2.20.1